Compare commits

..

No commits in common. "master" and "v1.0.0" have entirely different histories.

1429 changed files with 21591 additions and 28007 deletions

12
.github/FUNDING.yml vendored Executable file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # orange_management
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://paypal.me/orangemgmt']

37
.github/dev_bug_report.md vendored Executable file
View File

@ -0,0 +1,37 @@
---
name: Dev Bug Report
about: Create a report to help us improve
title: ''
labels: stat_backlog, type_bug
assignees: ''
---
# Bug Description
A clear and concise description of what the bug is.
# How to Reproduce
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
## Minimal Code Example
```php
<?php
// your code ...
?>
```
# Expected Behavior
A clear and concise description of what you expected to happen.
# Screenshots
If applicable, add screenshots to help explain your problem.
# Additional Information
Add any other context about the problem here.

18
.github/dev_feature_request.md vendored Executable file
View File

@ -0,0 +1,18 @@
---
name: Dev Feature Request
about: Suggest an idea for this project
title: ''
labels: stat_backlog, type_feature
assignees: ''
---
# What is the feature you request
* A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
* A clear and concise description of what you want to happen.
# Alternatives
A clear and concise description of any alternative solutions or features you've considered.
# Additional Information
Add any other context or screenshots about the feature request here.

View File

@ -3,9 +3,8 @@ name: CI
on: [push, pull_request]
jobs:
general_module_workflow_php:
general_module_workflow:
uses: Karaka-Management/Karaka/.github/workflows/php_template.yml@develop
secrets:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_PAT: ${{ secrets.GH_PAT }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
GH_PAT: ${{ secrets.GH_PAT }}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
@ -15,6 +15,7 @@ declare(strict_types=1);
namespace phpOMS\Account;
use phpOMS\Localization\Localization;
use phpOMS\Stdlib\Base\Exception\InvalidEnumValue;
use phpOMS\Validation\Network\Email;
/**
@ -163,12 +164,12 @@ class Account implements \JsonSerializable
*/
public function hasPermission(
int $permission,
?int $unit = null,
?int $app = null,
?string $module = null,
?int $category = null,
?int $element = null,
?int $component = null
int $unit = null,
int $app = null,
string $module = null,
int $category = null,
int $element = null,
int $component = null
) : bool
{
foreach ($this->groups as $group) {
@ -316,6 +317,70 @@ class Account implements \JsonSerializable
$this->email = \mb_strtolower($email);
}
/**
* Get status.
*
* @return int Returns the status (AccountStatus)
*
* @since 1.0.0
*/
public function getStatus() : int
{
return $this->status;
}
/**
* Get status.
*
* @param int $status Status
*
* @return void
*
* @throws InvalidEnumValue This exception is thrown if a invalid status is used
*
* @since 1.0.0
*/
public function setStatus(int $status) : void
{
if (!AccountStatus::isValidValue($status)) {
throw new InvalidEnumValue($status);
}
$this->status = $status;
}
/**
* Get type.
*
* @return int Returns the type (AccountType)
*
* @since 1.0.0
*/
public function getType() : int
{
return $this->type;
}
/**
* Get type.
*
* @param int $type Type
*
* @return void
*
* @throws InvalidEnumValue This exception is thrown if an invalid type is used
*
* @since 1.0.0
*/
public function setType(int $type) : void
{
if (!AccountType::isValidValue($type)) {
throw new InvalidEnumValue($type);
}
$this->type = $type;
}
/**
* Get last activity.
*
@ -380,8 +445,8 @@ class Account implements \JsonSerializable
public function toArray() : array
{
return [
'id' => $this->id,
'name' => [
'id' => $this->id,
'name' => [
$this->name1,
$this->name2,
$this->name3,

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
@ -71,8 +71,8 @@ final class AccountManager implements \Countable
if ($id === 0) {
$account = new Account(Auth::authenticate($this->session));
if (!isset($this->accounts[$account->id])) {
$this->accounts[$account->id] = $account;
if (!isset($this->accounts[$account->getId()])) {
$this->accounts[$account->getId()] = $account;
}
return $account;
@ -92,8 +92,8 @@ final class AccountManager implements \Countable
*/
public function add(Account $account) : bool
{
if (!isset($this->accounts[$account->id])) {
$this->accounts[$account->id] = $account;
if (!isset($this->accounts[$account->getId()])) {
$this->accounts[$account->getId()] = $account;
return true;
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
@ -14,6 +14,8 @@ declare(strict_types=1);
namespace phpOMS\Account;
use phpOMS\Stdlib\Base\Exception\InvalidEnumValue;
/**
* Account group class.
*
@ -86,6 +88,38 @@ class Group implements \JsonSerializable
return $this->id;
}
/**
* Get group status.
*
* @return int Group status
*
* @since 1.0.0
*/
public function getStatus() : int
{
return $this->status;
}
/**
* Set group status.
*
* @param int $status Group status
*
* @return void
*
* @throws InvalidEnumValue This exception is thrown if an invalid status is used
*
* @since 1.0.0
*/
public function setStatus(int $status) : void
{
if (!GroupStatus::isValidValue($status)) {
throw new InvalidEnumValue($status);
}
$this->status = $status;
}
/**
* Get string representation.
*

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
@ -24,18 +24,6 @@ namespace phpOMS\Account;
*/
final class NullAccount extends Account
{
/**
* Constructor
*
* @param int $id Model id
*
* @since 1.0.0
*/
public function __construct(int $id = 0)
{
$this->id = $id;
}
/**
* {@inheritdoc}
*/

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
@ -169,13 +169,13 @@ class PermissionAbstract implements \JsonSerializable
* @since 1.0.0
*/
public function __construct(
?int $unit = null,
?int $app = null,
?string $module = null,
?string $from = null,
?int $category = null,
?int $element = null,
?int $component = null,
int $unit = null,
int $app = null,
string $module = null,
string $from = null,
int $category = null,
int $element = null,
int $component = null,
int $permission = PermissionType::NONE
) {
$this->unit = $unit;
@ -308,12 +308,12 @@ class PermissionAbstract implements \JsonSerializable
*/
public function hasPermission(
int $permission,
?int $unit = null,
?int $app = null,
?string $module = null,
?int $category = null,
?int $element = null,
?int $component = null
int $unit = null,
int $app = null,
string $module = null,
int $category = null,
int $element = null,
int $component = null
) : bool
{
return $permission === PermissionType::NONE ||
@ -352,15 +352,15 @@ class PermissionAbstract implements \JsonSerializable
public function jsonSerialize() : mixed
{
return [
'id' => $this->id,
'unit' => $this->unit,
'app' => $this->app,
'module' => $this->module,
'from' => $this->from,
'category' => $this->category,
'element' => $this->element,
'component' => $this->component,
'permission' => $this->getPermission(),
'id' => $this->id,
'unit' => $this->unit,
'app' => $this->app,
'module' => $this->module,
'from' => $this->from,
'category' => $this->category,
'element' => $this->element,
'component' => $this->component,
'permission' => $this->getPermission(),
];
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
@ -135,12 +135,12 @@ trait PermissionHandlingTrait
*/
public function hasPermission(
int $permission,
?int $unit = null,
?int $app = null,
?string $module = null,
?int $category = null,
?int $element = null,
?int $component = null
int $unit = null,
int $app = null,
string $module = null,
int $category = null,
int $element = null,
int $component = null
) : bool
{
foreach ($this->permissions as $p) {

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Ai\NeuralNetwork
* @copyright Dennis Eichhorn
@ -22,7 +22,7 @@ namespace phpOMS\Ai\NeuralNetwork;
* @link https://jingga.app
* @since 1.0.0
*/
final class Neuron
class Neuron
{
/**
* Neuron inputs

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Ai\Ocr
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Ai\Ocr\Tesseract
* @copyright Dennis Eichhorn
@ -85,34 +85,14 @@ final class TesseractOcr
*
* @since 1.0.0
*/
public function parseImage(string $image, array $languages = ['eng', 'deu'], int $psm = 3, int $oem = 3) : string
public function parseImage(string $image, array $languages = ['eng'], int $psm = 3, int $oem = 3) : string
{
$temp = \tempnam(\sys_get_temp_dir(), 'oms_ocr_');
if ($temp === false) {
return '';
}
$extension = 'png';
try {
// Tesseract needs higher dpi to work properly (identify + adjust if necessary)
$dpi = (int) \trim(\implode('', SystemUtils::runProc(
'identify',
'-quiet -format "%x" ' . $image
)));
if ($dpi < 300) {
$split = \explode('.', $image);
$extension = \end($split);
SystemUtils::runProc(
'convert',
'-units PixelsPerInch ' . $image . ' -resample 300 ' . $temp . '.' . $extension
);
$image = $temp . '.' . $extension;
}
// Do actual parsing
SystemUtils::runProc(
self::$bin,
$image . ' '
@ -120,20 +100,12 @@ final class TesseractOcr
. ' -c preserve_interword_spaces=1'
. ' --psm ' . $psm
. ' --oem ' . $oem
. (empty($languages) ? '' : ' -l ' . \implode('+', $languages))
. ' -l ' . \implode('+', $languages)
);
} catch (\Throwable $_) {
if (\is_file($temp . '.' . $extension)) {
\unlink($temp . '.' . $extension);
}
return '';
}
if (\is_file($temp . '.' . $extension)) {
\unlink($temp . '.' . $extension);
}
$filepath = \is_file($temp . '.txt')
? $temp . '.txt'
: $temp;
@ -148,7 +120,11 @@ final class TesseractOcr
$parsed = \file_get_contents($filepath);
if ($parsed === false) {
$parsed = '';
// @codeCoverageIgnoreStart
\unlink($temp);
return '';
// @codeCoverageIgnoreEnd
}
\unlink($filepath);

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -14,141 +14,17 @@ declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
use phpOMS\Math\Topology\MetricsND;
/**
* Clustering points
*
* The parent category of this clustering algorithm is hierarchical clustering.
*
* @package phpOMS\Algorithm\Clustering
* @license Base: MIT Copyright (c) 2020 Greene Laboratory
* @license OMS License 2.0
* @link https://jingga.app
* @see ./DivisiveClustering.php
* @see ./clustering_overview.png
* @see https://en.wikipedia.org/wiki/Hierarchical_clustering
* @see https://github.com/greenelab/hclust/blob/master/README.md
* @since 1.0.0
*
* @todo Implement
* @todo Implement missing linkage functions
*/
final class AgglomerativeClustering implements ClusteringInterface
final class AgglomerativeClustering
{
/**
* Metric to calculate the distance between two points
*
* @var \Closure
* @since 1.0.0
*/
public \Closure $metric;
/**
* Metric to calculate the distance between two points
*
* @var \Closure
* @since 1.0.0
*/
public \Closure $linkage;
/**
* Constructor
*
* @param null|\Closure $metric metric to use for the distance between two points
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null, ?\Closure $linkage = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
return MetricsND::euclidean($aCoordinates, $bCoordinates);
};
$this->linkage = $linkage ?? function (array $a, array $b, array $distances) {
return self::averageDistanceLinkage($a, $b, $distances);
};
}
/**
* Maximum/Complete-Linkage clustering
*/
public static function maximumDistanceLinkage(array $setA, array $setB, array $distances) : float
{
$max = \PHP_INT_MIN;
foreach ($setA as $a) {
foreach ($setB as $b) {
if ($distances[$a][$b] > $max) {
$max = $distances[$a][$b];
}
}
}
return $max;
}
/**
* Minimum/Single-Linkage clustering
*/
public static function minimumDistanceLinkage(array $setA, array $setB, array $distances) : float
{
$min = \PHP_INT_MAX;
foreach ($setA as $a) {
foreach ($setB as $b) {
if ($distances[$a][$b] < $min) {
$min = $distances[$a][$b];
}
}
}
return $min;
}
/**
* Unweighted average linkage clustering (UPGMA)
*/
public static function averageDistanceLinkage(array $setA, array $setB, array $distances) : float
{
$distance = 0;
foreach ($setA as $a) {
$distance += \array_sum($distances[$a]);
}
return $distance / \count($setA) / \count($setB);
}
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -25,37 +25,6 @@ namespace phpOMS\Algorithm\Clustering;
*
* @todo Implement
*/
final class Birch implements ClusteringInterface
final class Birch
{
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

View File

@ -1,71 +0,0 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering interface.
*
* @package phpOMS\Algorithm\Clustering;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
interface ClusteringInterface
{
/**
* Get cluster centroids
*
* @return Point[]
*
* @since 1.0.0
*/
public function getCentroids() : array;
/**
* Get cluster assignments of the training data
*
* @return Point[]
*
* @since 1.0.0
*/
public function getClusters() : array;
/**
* Cluster a single point
*
* This point doesn't have to be in the training data.
*
* @param Point $point Point to cluster
*
* @return null|Point
*
* @since 1.0.0
*/
public function cluster(Point $point) : ?Point;
/**
* Get noise data.
*
* Data points from the training data that are not part of a cluster.
*
* @return Point[]
*
* @since 1.0.0
*/
public function getNoise() : array;
// Not possible to interface due to different implementations
// public function generateClusters(...) : void
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -29,7 +29,7 @@ use phpOMS\Math\Topology\MetricsND;
*
* @todo Expand to n dimensions
*/
final class DBSCAN implements ClusteringInterface
final class DBSCAN
{
/**
* Epsilon for float comparison.
@ -50,7 +50,7 @@ final class DBSCAN implements ClusteringInterface
/**
* Points outside of any cluster
*
* @var Point[]
* @var PointInterface[]
* @since 1.0.0
*/
private array $noisePoints = [];
@ -58,25 +58,17 @@ final class DBSCAN implements ClusteringInterface
/**
* All points
*
* @var Point[]
* @var PointInterface[]
* @since 1.0.0
*/
private array $points = [];
/**
* Points of the cluster centers
*
* @var Point[]
* @since 1.0.0
*/
private array $clusterCenters = [];
/**
* Clusters
*
* Array of points assigned to a cluster
*
* @var array<int, Point[]>
* @var array<int, array>
* @since 1.0.0
*/
private array $clusters = [];
@ -116,9 +108,9 @@ final class DBSCAN implements ClusteringInterface
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null)
public function __construct(\Closure $metric = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$this->metric = $metric ?? function (PointInterface $a, PointInterface $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
@ -129,18 +121,18 @@ final class DBSCAN implements ClusteringInterface
/**
* Expand cluster with additional point and potential neighbors.
*
* @param Point $point Point to add to a cluster
* @param array $neighbors Neighbors of point
* @param int $c Cluster id
* @param float $epsilon Max distance
* @param int $minPoints Min amount of points required for a cluster
* @param PointInterface $point Point to add to a cluster
* @param array $neighbors Neighbors of point
* @param int $c Cluster id
* @param float $epsilon Max distance
* @param int $minPoints Min amount of points required for a cluster
*
* @return void
*
* @since 1.0.0
*/
private function expandCluster(
Point $point,
PointInterface $point,
array $neighbors,
int $c,
float $epsilon,
@ -174,14 +166,14 @@ final class DBSCAN implements ClusteringInterface
/**
* Find neighbors of a point
*
* @param Point $point Base point for potential neighbors
* @param float $epsilon Max distance to neighbor
* @param PointInterface $point Base point for potential neighbors
* @param float $epsilon Max distance to neighbor
*
* @return array
*
* @since 1.0.0
*/
private function findNeighbors(Point $point, float $epsilon) : array
private function findNeighbors(PointInterface $point, float $epsilon) : array
{
$neighbors = [];
foreach ($this->points as $point2) {
@ -223,9 +215,15 @@ final class DBSCAN implements ClusteringInterface
}
/**
* {@inheritdoc}
* Find the cluster for a point
*
* @param PointInterface $point Point to find the cluster for
*
* @return int Cluster id
*
* @since 1.0.0
*/
public function cluster(Point $point) : ?Point
public function cluster(PointInterface $point) : int
{
if ($this->convexHulls === []) {
foreach ($this->clusters as $c => $cluster) {
@ -234,26 +232,26 @@ final class DBSCAN implements ClusteringInterface
$points[] = $p->coordinates;
}
// @todo this is only good for 2D. Fix this for ND.
// @todo: this is only good for 2D. Fix this for ND.
$this->convexHulls[$c] = MonotoneChain::createConvexHull($points);
}
}
foreach ($this->convexHulls as $c => $hull) {
if (Polygon::isPointInPolygon($point->coordinates, $hull) <= 0) {
return $hull;
return $c;
}
}
return null;
return -1;
}
/**
* Generate the clusters of the points
*
* @param Point[] $points Points to cluster
* @param float $epsilon Max distance
* @param int $minPoints Min amount of points required for a cluster
* @param PointInterface[] $points Points to cluster
* @param float $epsilon Max distance
* @param int $minPoints Min amount of points required for a cluster
*
* @return void
*
@ -284,48 +282,4 @@ final class DBSCAN implements ClusteringInterface
}
}
}
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
if (!empty($this->clusterCenters)) {
return $this->clusterCenters;
}
$dim = \count(\reset($this->points)->getCoordinates());
foreach ($this->clusters as $cluster) {
$middle = \array_fill(0, $dim, 0);
foreach ($cluster as $point) {
for ($i = 0; $i < $dim; ++$i) {
$middle[$i] += $point->getCoordinate($i);
}
}
for ($i = 0; $i < $dim; ++$i) {
$middle[$i] /= \count($cluster);
}
$this->clusterCenters = new Point($middle);
}
return $this->clusterCenters;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return $this->noisePoints;
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return $this->clusters;
}
}

View File

@ -1,65 +0,0 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering points
*
* The parent category of this clustering algorithm is hierarchical clustering.
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./AgglomerativeClustering.php
* @see ./clustering_overview.png
* @see https://en.wikipedia.org/wiki/Hierarchical_clustering
* @since 1.0.0
*
* @todo Implement
*/
final class DivisiveClustering implements ClusteringInterface
{
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -25,7 +25,7 @@ use phpOMS\Math\Topology\MetricsND;
* @see ./clustering_overview.png
* @since 1.0.0
*/
final class Kmeans implements ClusteringInterface
final class Kmeans
{
/**
* Epsilon for float comparison.
@ -46,26 +46,10 @@ final class Kmeans implements ClusteringInterface
/**
* Points of the cluster centers
*
* @var Point[]
* @var PointInterface[]
* @since 1.0.0
*/
private array $clusterCenters = [];
/**
* Points of the clusters
*
* @var Point[]
* @since 1.0.0
*/
private array $clusters = [];
/**
* Points
*
* @var Point[]
* @since 1.0.0
*/
private array $points = [];
private $clusterCenters = [];
/**
* Constructor
@ -74,20 +58,28 @@ final class Kmeans implements ClusteringInterface
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null)
public function __construct(\Closure $metric = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$this->metric = $metric ?? function (PointInterface $a, PointInterface $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
return MetricsND::euclidean($aCoordinates, $bCoordinates);
};
//$this->generateClusters($points, $clusters);
}
/**
* {@inheritdoc}
* Find the cluster for a point
*
* @param PointInterface $point Point to find the cluster for
*
* @return null|PointInterface Cluster center point
*
* @since 1.0.0
*/
public function cluster(Point $point) : ?Point
public function cluster(PointInterface $point) : ?PointInterface
{
$bestCluster = null;
$bestDistance = \PHP_FLOAT_MAX;
@ -103,26 +95,22 @@ final class Kmeans implements ClusteringInterface
}
/**
* {@inheritdoc}
* Get cluster centroids
*
* @return array
*
* @since 1.0.0
*/
public function getCentroids() : array
{
return $this->clusterCenters;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
/**
* Generate the clusters of the points
*
* @param Point[] $points Points to cluster
* @param int<1, max> $clusters Amount of clusters
* @param PointInterface[] $points Points to cluster
* @param int<0, max> $clusters Amount of clusters
*
* @return void
*
@ -130,7 +118,6 @@ final class Kmeans implements ClusteringInterface
*/
public function generateClusters(array $points, int $clusters) : void
{
$this->points = $points;
$n = \count($points);
$clusterCenters = $this->kpp($points, $clusters);
$coordinates = \count($points[0]->coordinates);
@ -153,7 +140,8 @@ final class Kmeans implements ClusteringInterface
foreach ($clusterCenters as $center) {
for ($i = 0; $i < $coordinates; ++$i) {
$center->setCoordinate($i, $center->getCoordinate($i) / $center->group);
// @todo Invalid center coodinate value in like 5 % of the runs
$center->setCoordinate($i, $center->getCoordinate($i) / ($center->group === 0 ? 1 : $center->group));
}
}
@ -161,7 +149,7 @@ final class Kmeans implements ClusteringInterface
foreach ($points as $point) {
$min = $this->nearestClusterCenter($point, $clusterCenters)[0];
if ($clusters !== $point->group) {
if ($min !== $point->group) {
++$changed;
$point->group = $min;
}
@ -183,14 +171,14 @@ final class Kmeans implements ClusteringInterface
/**
* Get the index and distance to the nearest cluster center
*
* @param Point $point Point to get the cluster for
* @param Point[] $clusterCenters All cluster centers
* @param PointInterface $point Point to get the cluster for
* @param PointInterface[] $clusterCenters All cluster centers
*
* @return array [index, distance]
*
* @since 1.0.0
*/
private function nearestClusterCenter(Point $point, array $clusterCenters) : array
private function nearestClusterCenter(PointInterface $point, array $clusterCenters) : array
{
$index = $point->group;
$dist = \PHP_FLOAT_MAX;
@ -208,71 +196,43 @@ final class Kmeans implements ClusteringInterface
}
/**
* Initialize cluster centers
* Initializae cluster centers
*
* @param Point[] $points Points to use for the cluster center initialization
* @param int<0, max> $n Amount of clusters to use
* @param PointInterface[] $points Points to use for the cluster center initialization
* @param int<0, max> $n Amount of clusters to use
*
* @return Point[]
* @return PointInterface[]
*
* @since 1.0.0
*/
private function kpp(array $points, int $n) : array
{
$clusters = [clone $points[\array_rand($points, 1)]];
$d = \array_fill(0, $n, 0.0);
$clusters = [clone $points[\mt_rand(0, \count($points) - 1)]];
$d = \array_fill(0, $n, 0.0);
for ($i = 1; $i < $n; ++$i) {
$sum = 0;
foreach ($points as $key => $point) {
$d[$key] = $this->nearestClusterCenter($point, $clusters)[1];
$sum += $d[$key];
$d[$key] = $this->nearestClusterCenter($point, \array_slice($clusters, 0, 5))[1];
$sum += $d[$key];
}
$sum *= \mt_rand(0, \mt_getrandmax()) / \mt_getrandmax();
$found = false;
foreach ($d as $key => $di) {
$sum -= $di;
// The in array check is important to avoid duplicate cluster centers
if ($sum <= 0 && !\in_array($c = $points[$key], $clusters)) {
$clusters[$i] = clone $c;
$found = true;
}
}
while (!$found) {
if (!\in_array($c = $points[\array_rand($points)], $clusters)) {
$clusters[$i] = clone $c;
$found = true;
if ($sum <= 0) {
$clusters[$i] = clone $points[$key];
}
}
}
foreach ($points as $point) {
$point->group = $this->nearestClusterCenter($point, $clusters)[0];
$point->group = ($this->nearestClusterCenter($point, $clusters)[0]);
}
return $clusters;
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
if (!empty($this->clusters)) {
return $this->clusters;
}
foreach ($this->points as $point) {
$c = $this->cluster($point);
$this->clusters[$c?->name] = $point;
}
return $this->clusters;
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -25,10 +25,8 @@ use phpOMS\Math\Topology\MetricsND;
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*
* @todo Implement noise points
*/
final class MeanShift implements ClusteringInterface
final class MeanShift
{
/**
* Min distance for clustering
@ -61,7 +59,7 @@ final class MeanShift implements ClusteringInterface
/**
* Points outside of any cluster
*
* @var Point[]
* @var PointInterface[]
* @since 1.0.0
*/
private array $noisePoints = [];
@ -79,10 +77,10 @@ final class MeanShift implements ClusteringInterface
/**
* Points of the cluster centers
*
* @var Point[]
* @var PointInterface[]
* @since 1.0.0
*/
private array $clusterCenters = [];
private $clusterCenters = [];
/**
* Max distance to cluster to be still considered part of cluster
@ -102,9 +100,9 @@ final class MeanShift implements ClusteringInterface
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null, ?\Closure $kernel = null)
public function __construct(\Closure $metric = null, \Closure $kernel = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$this->metric = $metric ?? function (PointInterface $a, PointInterface $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
@ -119,7 +117,7 @@ final class MeanShift implements ClusteringInterface
/**
* Generate the clusters of the points
*
* @param Point[] $points Points to cluster
* @param PointInterface[] $points Points to cluster
* @param array<int|float> $bandwidth Bandwidth(s)
*
* @return void
@ -128,9 +126,8 @@ final class MeanShift implements ClusteringInterface
*/
public function generateClusters(array $points, array $bandwidth) : void
{
$this->points = $points;
$shiftPoints = $points;
$maxMinDist = 1;
$shiftPoints = $points;
$maxMinDist = 1;
$stillShifting = \array_fill(0, \count($points), true);
@ -170,15 +167,15 @@ final class MeanShift implements ClusteringInterface
/**
* Perform shift on a point
*
* @param Point $point Point to shift
* @param Point $points Array of all points
* @param PointInterface $point Point to shift
* @param PointInterface $points Array of all points
* @param array<int|float> $bandwidth Bandwidth(s)
*
* @return Point
* @return PointInterface
*
* @since 1.0.0
*/
private function shiftPoint(Point $point, array $points, array $bandwidth) : Point
private function shiftPoint(PointInterface $point, array $points, array $bandwidth) : PointInterface
{
$scaleFactor = 0.0;
@ -209,7 +206,7 @@ final class MeanShift implements ClusteringInterface
/**
* Group points together into clusters
*
* @param Point[] $points Array of points to assign to groups
* @param PointInterface[] $points Array of points to assign to groups
*
* @return array
*
@ -242,14 +239,14 @@ final class MeanShift implements ClusteringInterface
/**
* Find the closest cluster/group of a point
*
* @param Point $point Point to find the cluster for
* @param array<Point[]> $groups Clusters
* @param PointInterface $point Point to find the cluster for
* @param array<PointInterface[]> $groups Clusters
*
* @return int
*
* @since 1.0.0
*/
private function findNearestGroup(Point $point, array $groups) : int
private function findNearestGroup(PointInterface $point, array $groups) : int
{
$nearestGroupIndex = -1;
$index = 0;
@ -272,14 +269,14 @@ final class MeanShift implements ClusteringInterface
/**
* Find distance of point to best cluster/group
*
* @param Point $point Point to find the cluster for
* @param Point[] $group Clusters
* @param PointInterface $point Point to find the cluster for
* @param PointInterface[] $group Clusters
*
* @return float Distance
*
* @since 1.0.0
*/
private function distanceToGroup(Point $point, array $group) : float
private function distanceToGroup(PointInterface $point, array $group) : float
{
$minDistance = \PHP_FLOAT_MAX;
@ -295,36 +292,18 @@ final class MeanShift implements ClusteringInterface
}
/**
* {@inheritdoc}
* Find the cluster for a point
*
* @param PointInterface $point Point to find the cluster for
*
* @return null|PointInterface Cluster center point
*
* @since 1.0.0
*/
public function getCentroids() : array
{
return $this->clusterCenters;
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
public function cluster(PointInterface $point) : ?PointInterface
{
$clusterId = $this->findNearestGroup($point, $this->clusters);
return $this->clusterCenters[$clusterId] ?? null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return $this->noisePoints;
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return $this->clusters;
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -28,7 +28,7 @@ class Point implements PointInterface
* Coordinates of the point
*
* @var array<int, int|float>
* @since 1.0.0
* @sicne 1.0.0
*/
public array $coordinates = [];
@ -89,7 +89,7 @@ class Point implements PointInterface
/**
* {@inheritdoc}
*/
public function isEquals(Point $point) : bool
public function isEquals(PointInterface $point) : bool
{
return $this->name === $point->name && $this->coordinates === $point->coordinates;
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -25,10 +25,6 @@ namespace phpOMS\Algorithm\Clustering;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @property array<int, int|float> $coordinates
* @property string $name
* @property int $group
*/
interface PointInterface
{
@ -67,11 +63,11 @@ interface PointInterface
/**
* Check if two points are equal
*
* @param Point $point Point to compare with
* @param self $point Point to compare with
*
* @return bool
*
* @since 1.0.0
*/
public function isEquals(Point $point) : bool;
public function isEquals(self $point) : bool;
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
@ -25,37 +25,6 @@ namespace phpOMS\Algorithm\Clustering;
*
* @todo Implement
*/
final class SpectralClustering implements ClusteringInterface
final class SpectralClustering
{
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

View File

@ -0,0 +1,30 @@
<?php
/**
* Jingga
*
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering points
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*
* @todo Implement
*/
final class Ward
{
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\CoinMatching
* @copyright Dennis Eichhorn

View File

@ -2,9 +2,9 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Frequency
* @package phpOMS\Algorithm\CoinMatching
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
@ -12,14 +12,14 @@
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Frequency;
namespace phpOMS\Algorithm\CoinMatching;
/**
* Apriori algorithm.
*
* The algorithm checks how often a set exists in a given set of sets.
* The algorithm cheks how often a set exists in a given set of sets.
*
* @package phpOMS\Algorithm\Frequency
* @package phpOMS\Algorithm\CoinMatching
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
@ -39,7 +39,7 @@ final class Apriori
/**
* Generate all possible subsets
*
* @param array $arr Array of elements
* @param array $arr Array of eleements
*
* @return array<array>
*
@ -70,14 +70,13 @@ final class Apriori
*
* The algorithm cheks how often a set exists in a given set of sets.
*
* @param array<string[]> $sets Sets of a set (e.g. [[1,2,3,4], [1,2], [1]])
* @param string[] $subset Subset to check for (empty array -> all subsets are checked)
* @param array<array> $sets Sets of a set (e.g. [[1,2,3,4], [1,2], [1]])
*
* @return array
*
* @since 1.0.0
*/
public static function apriori(array $sets, array $subset = []) : array
public static function apriori(array $sets) : array
{
// Unique single items
$totalSet = [];
@ -91,7 +90,6 @@ final class Apriori
$totalSet = \array_unique($totalSet);
\sort($totalSet);
\sort($subset);
// Combinations of items
$combinations = self::generateSubsets($totalSet);
@ -100,18 +98,10 @@ final class Apriori
$table = [];
foreach ($combinations as &$c) {
\sort($c);
if (!empty($subset) && $c !== $subset) {
continue;
}
$table[\implode(':', $c)] = 0;
}
foreach ($combinations as $combination) {
if (!empty($subset) && $combination !== $subset) {
continue;
}
foreach ($sets as $set) {
foreach ($combination as $item) {
if (!\in_array($item, $set)) {

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Graph;
* @copyright Dennis Eichhorn
@ -67,7 +67,7 @@ final class DependencyResolver
$unresolved[] = $dependency;
self::dependencyResolve($dependency, $items, $resolved, $unresolved);
} else {
return; // circular dependency
continue; // circular dependency
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Graph
* @copyright Dennis Eichhorn
@ -21,185 +21,9 @@ namespace phpOMS\Algorithm\Graph;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @todo Implement
*/
final class MarkovChain
{
/**
* Order of the markov chain
*
* @var int
* @since 1.0.0
*/
private int $order = 1;
/**
* Trained data
*
* @var array
* @since 1.0.0
*/
private array $data = [];
/**
* Constructor
*
* @param int $order Order of the markov chain
*
* @since 1.0.0
*/
public function __construct(int $order = 1)
{
$this->order = $order;
}
/**
* Create markov chain based on input
*
* @param array $values Training values
*
* @return void
*
* @since 1.0.0
*/
public function train(array $values) : void
{
$temp = [];
$length = \count($values) - $this->order;
$unique = \array_unique($values);
for ($i = 0; $i < $length; ++$i) {
$key = [];
for ($j = 0; $j < $this->order; ++$j) {
$key[] = $values[$i + $j];
}
$keyString = \implode(' ', $key);
if (!isset($temp[$keyString])) {
foreach ($unique as $value) {
$temp[$keyString][$value] = 0;
}
}
++$temp[$keyString][$values[$i + 1]];
}
foreach ($temp as $key => $values) {
$sum = \array_sum($values);
foreach ($values as $idx => $value) {
$this->data[$key][$idx] = $value / $sum;
}
}
}
/**
* Set training data
*
* @param array<array<int, int>> $values Training values
*
* @return void
*
* @since 1.0.0
*/
public function setTraining(array $values) : void
{
$this->data = $values;
}
/**
* Generate a markov chain based on the training data.
*
* @param int $length Length of the markov chain
* @param array $start Start values of the markov chain
*
* @return array
*
* @since 1.0.0
*/
public function generate(int $length, ?array $start = null) : array
{
$orderKeys = \array_keys($this->data);
$orderValues = \array_keys(\reset($this->data));
$output = $start ?? \explode(' ', $orderKeys[\array_rand($orderKeys)]);
$key = $output;
for ($i = $this->order; $i < $length; ++$i) {
$keyString = \implode(' ', $key);
$prob = \mt_rand(1, 100) / 100;
$cProb = 0.0;
$val = null;
$new = null;
foreach (($this->data[$keyString] ?? []) as $val => $p) {
$cProb += $p;
if ($prob <= $cProb) {
$new = $val;
break;
}
}
// Couldn't find possible key
$new ??= $orderValues[\array_rand($orderValues)];
$output[] = $new;
$key[] = $new;
\array_shift($key);
}
return $output;
}
/**
* Calculate the probability for a certain markov chain.
*
* @param array $path Markov chain
*
* @return float
*
* @since 1.0.0
*/
public function pathProbability(array $path) : float
{
$length = \count($path);
if ($length <= $this->order) {
return 0.0;
}
$key = \array_slice($path, 0, $this->order);
$prob = 1.0;
for ($i = $this->order; $i < $length; ++$i) {
$prob *= $this->data[\implode(' ', $key)][$path[$i]] ?? 0.0;
$key[] = $path[$i];
\array_shift($key);
}
return $prob;
}
/**
* Calculate the probability for a certain state change in a markov chain
*
* @param array $state Current state of the markov chain
* @param mixed $next Next markov state
*
* @return float
*
* @since 1.0.0
*/
public function stepProbability(array $state, mixed $next) : float
{
if (\count($state) !== $this->order) {
return 0.0;
}
return $this->data[\implode(' ', $state)][$next] ?? 0.0;
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\JobScheduling
* @copyright Dennis Eichhorn
@ -57,7 +57,7 @@ class Job implements JobInterface
public string $name = '';
/**
* Constructor.
* Cosntructor.
*
* @param float $value Value of the job
* @param \DateTime $start Start time of the job

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\JobScheduling
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\JobScheduling
* @copyright Dennis Eichhorn
@ -62,7 +62,7 @@ final class Weighted
}
/**
* Search for a none-conflicting job that comes before a defined job
* Search for a none-conflicting job that comes befor a defined job
*
* @param JobInterface[] $jobs List of jobs
* @param int $pivot Job to find the previous job to
@ -130,7 +130,7 @@ final class Weighted
if ($l != -1) {
$value += $valueTable[$l];
$jList = \array_merge($resultTable[$l], $jList);
$jList = \array_merge($resultTable[$l], $jList);
}
if ($value > $valueTable[$i - 1]) {

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn

View File

@ -1,28 +0,0 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Material.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Material
{
public int $id = 0;
}

View File

@ -1,28 +0,0 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Material.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Qualification
{
public int $id = 0;
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling
* @copyright Dennis Eichhorn
@ -24,96 +24,32 @@ namespace phpOMS\Scheduling;
*/
class Job
{
/**
* Id
*
* @var int
* @since 1.0.0
*/
public int $id = 0;
/**
* Time of the execution
*
* @var int
* @since 1.0.0
*/
public int $executionTime = 0;
/**
* Priority.
*
* @var float
* @since 1.0.0
*/
public float $priority = 0.0;
/**
* Value this job generates.
*
* @var float
* @since 1.0.0
*/
public float $value = 0.0;
/**
* Cost of executing this job.
*
* @var float
* @since 1.0.0
*/
public float $cost = 0.0;
/**
* How many iterations has this job been on hold in the queue.
*
* @var int
* @since 1.0.0
*/
/** How many iterations has this job been on hold in the queue */
public int $onhold = 0;
/**
* How many iterations has this job been in process in the queue.
*
* @var int
* @since 1.0.0
*/
/** How many iterations has this job been in process in the queue */
public int $inprocessing = 0;
/**
* What is the deadline for this job?
*
* @param \DateTime
* @since 1.0.0
*/
public \DateTime $deadline;
/**
* Which steps must be taken during the job execution
*
* @var JobStep[]
* @since 1.0.0
*/
public array $steps = [];
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct()
{
$this->deadline = new \DateTime('now');
}
/**
* Get the profit of the job
*
* @return float
*
* @since 1.0.0
*/
public function getProfit() : float
public function getProfit()
{
return $this->value - $this->cost;
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Scheduling
* @copyright Dennis Eichhorn
@ -24,24 +24,8 @@ namespace phpOMS\Scheduling;
*/
final class ScheduleQueue
{
/**
* Queue
*
* @var Job[]
* @since 1.0.0
*/
public array $queue = [];
/**
* Get element from queue
*
* @param int $size Amount of elements to return
* @param int $type Priority type to use for return
*
* @return Job[]
*
* @since 1.0.0
*/
public function get(int $size = 1, int $type = PriorityMode::FIFO) : array
{
$jobs = [];
@ -119,33 +103,11 @@ final class ScheduleQueue
return $jobs;
}
/**
* Insert new element into queue
*
* @param int $id Element id
* @param Job $job Element to add
*
* @return void
*
* @since 1.0.0
*/
public function insert(int $id, Job $job) : void
{
$this->queue[$id] = $job;
}
/**
* Pop elements from the queue.
*
* This also removes the elements from the queue
*
* @param int $size Amount of elements to return
* @param int $type Priority type to use for return
*
* @return Job[]
*
* @since 1.0.0
*/
public function pop(int $size = 1, int $type = PriorityMode::FIFO) : array
{
$jobs = $this->get($size, $type);
@ -156,15 +118,6 @@ final class ScheduleQueue
return $jobs;
}
/**
* Increases the hold counter of an element
*
* @param int $id Id of the element (0 = all elements)
*
* @return void
*
* @since 1.0.0
*/
public function bumpHold(int $id = 0) : void
{
if ($id === 0) {
@ -176,16 +129,6 @@ final class ScheduleQueue
}
}
/**
* Change the priority of an element
*
* @param int $id Id of the element (0 = all elements)
* @param float $priority Priority to increase by
*
* @return void
*
* @since 1.0.0
*/
public function adjustPriority(int $id = 0, float $priority = 0.1) : void
{
if ($id === 0) {
@ -197,16 +140,7 @@ final class ScheduleQueue
}
}
/**
* Remove an element from the queue
*
* @param int $id Id of the element
*
* @return void
*
* @since 1.0.0
*/
public function remove(int $id) : void
public function remove(string $id) : void
{
unset($this->queue[$id]);
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
@ -106,7 +106,7 @@ class Backpack implements BackpackInterface
public function addItem(ItemInterface $item, int | float $quantity = 1) : void
{
$this->items[] = ['item' => $item, 'quantity' => $quantity];
$this->value += $item->getValue() * $quantity;
$this->cost += $item->getCost() * $quantity;
$this->value += $item->getValue() * $quantity;
$this->cost += $item->getCost() * $quantity;
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
@ -49,7 +49,7 @@ class Item implements ItemInterface
public string $name = '';
/**
* Constructor.
* Cosntructor.
*
* @param float $value Value of the item
* @param float $cost Cost of the item

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Maze
* @copyright Dennis Eichhorn
@ -81,7 +81,7 @@ class MazeGenerator
if (!empty($neighbors)) {
--$n;
$next = $neighbors[\array_rand($neighbors, 1)];
$next = $neighbors[\mt_rand(0, \count($neighbors) - 1)];
$unvisited[$next[0] + 1][$next[1] + 1] = false;
if ($next[0] === $pos[0]) {

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
@ -80,9 +80,9 @@ class GeneticOptimization
*
* @example See unit test for example use case
*
* @param array<array> $population List of all elements with their parameters (i.e. list of "objects" as arrays).
* @param array<array> $population List of all elements with ther parameters (i.e. list of "objects" as arrays).
* The constraints are defined as array values.
* @param \Closure $fitness Fitness function calculates score/feasibility of solution
* @param \Closure $fitness Fitness function calculates score/feasability of solution
* @param \Closure $mutate Mutation function to change the parameters of an "object"
* @param \Closure $crossover Crossover function to exchange parameter values between "objects".
* Sometimes single parameters can be exchanged but sometimes interdependencies exist between parameters which is why this function is required.

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
@ -40,7 +40,7 @@ class SimulatedAnnealing
return $x;
}
// can be many things, e.g. swapping parameters, increasing/decreasing, random generation
// can be many things, e.g. swapping parameters, increasing/decrising, random generation
public static function neighbor(array $generation, $parameterCount)
{
$newGeneration = $generation;
@ -57,17 +57,17 @@ class SimulatedAnnealing
*/
// Simulated Annealing algorithm
// @todo allow to create a solution space (currently all solutions need to be in space)
// @todo currently only replacing generations, not altering them
// @todo allow to create a solution space (currently all soluctions need to be in space)
// @todo: currently only replacing generations, not altering them
/**
* Perform optimization
*
* @example See unit test for example use case
*
* @param array $space List of all elements with their parameters (i.e. list of "objects" as arrays).
* @param array $space List of all elements with ther parameters (i.e. list of "objects" as arrays).
* The constraints are defined as array values.
* @param int $initialTemperature Starting temperature
* @param \Closure $costFunction Fitness function calculates score/feasibility of solution
* @param \Closure $costFunction Fitness function calculates score/feasability of solution
* @param \Closure $neighbor Neighbor function to find a new solution/neighbor
* @param float $coolingRate Rate at which cooling takes place
* @param int $iterations Number of iterations

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
@ -54,7 +54,7 @@ class Path
private array $expandedNodes = [];
/**
* Constructor.
* Cosntructor.
*
* @param Grid $grid Grid this path belongs to
*
@ -152,7 +152,7 @@ class Path
}
/**
* Find nodes in between two nodes.
* Find nodes in bettween two nodes.
*
* The path may only contain the jump points or pivot points.
* In order to get every node it needs to be expanded.
@ -190,7 +190,7 @@ class Path
if ($e2 > -$dy) {
$err -= $dy;
$x0 += $sx;
$x0 += $sx;
}
if ($e2 < $dx) {

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
@ -74,37 +74,4 @@ final class Elo
'elo' => (int) \max($eloNew, $this->MIN_ELO),
];
}
/**
* Calculate an approximated win probability based on elo points.
*
* @param int $elo1 Elo of the player we want to calculate the win probability for
* @param int $elo2 Opponent elo
* @param bool $canDraw Is a draw possible?
*
* @return float
*
* @since 1.0.0
*/
public function winProbability(int $elo1, int $elo2, bool $canDraw = false) : float
{
return $canDraw
? -1.0 // @todo implement
: 1 / (1 + \pow(10, ($elo2 - $elo1) / 400));
}
/**
* Calculate an approximated draw probability based on elo points.
*
* @param int $elo1 Elo of the player we want to calculate the win probability for
* @param int $elo2 Opponent elo
*
* @return float
*
* @since 1.0.0
*/
public function drawProbability(int $elo1, int $elo2) : float
{
return -1.0; // @todo implement
}
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
@ -102,7 +102,7 @@ final class Glicko1
}
/**
* Calculate the glicko-1 elo
* Calcualte the glicko-1 elo
*
* @param int $elo Current player "elo"
* @param int $rdOld Current player deviation (RD)

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
@ -25,6 +25,8 @@ use phpOMS\Math\Solver\Root\Bisection;
* @see https://en.wikipedia.org/wiki/Glicko_rating_system
* @see http://www.glicko.net/glicko/glicko2.pdf
* @since 1.0.0
*
* @todo: implement
*/
final class Glicko2
{
@ -91,7 +93,7 @@ final class Glicko2
public int $MIN_RD = 50;
/**
* Calculate the glicko-2 elo
* Calcualte the glicko-2 elo
*
* @example $glicko->elo(1500, 200, 0.06, [1,0,0], [1400,1550,1700], [30,100,300]) // 1464, 151, 0.059
*
@ -119,7 +121,7 @@ final class Glicko2
// Step 0:
$rdOld /= self::Q;
$elo = ($elo - $this->DEFAULT_ELO) / self::Q;
$elo = ($elo - $this->DEFAULT_ELO) / self::Q;
foreach ($oElo as $idx => $value) {
$oElo[$idx] = ($value - $this->DEFAULT_ELO) / self::Q;

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Rating
* @copyright Microsoft
@ -22,93 +22,25 @@ use phpOMS\Math\Stochastic\Distribution\NormalDistribution;
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://www.moserware.com/assets/computing-your-skill/The%20Math%20Behind%20TrueSkill.pdf
* @since 1.0.0
* @see https://www.moserware.com/assets/computing-your-skill/The%20Math%20Behind%20TrueSkill.pdf
*
* @todo Implement https://github.com/sublee/trueskill/blob/master/trueskill/__init__.py
* https://github.com/Karaka-Management/phpOMS/issues/337
* @todo implement https://github.com/sublee/trueskill/blob/master/trueskill/__init__.py
*/
// phpcs:ignoreFile
class TrueSkill
{
public const DEFAULT_MU = 25;
public int $DEFAULT_MU = 25;
public const DEFAULT_SIGMA = 25 / 3;
public float $DEFAULT_SIGMA = 25 / 3;
public const DEFAULT_BETA = 25 / 3 / 2;
public float $DEFAULT_BETA = 25 / 3 / 2;
public const DEFAULT_TAU = 25 / 3 / 100;
public float $DEFAULT_TAU = 25 / 3 / 100;
public const DEFAULT_DRAW_PROBABILITY = 0.1;
public float $DEFAULT_DRAW_PROBABILITY = 0.1;
private float $mu = 0.0;
private float $sigma = 0.0;
private float $beta = 0.0;
private float $tau = 0.0;
private float $drawProbability = 0.0;
/**
* Constructor.
*
* @param null|float $mu Mu
* @param null|float $sigma Sigma
* @param null|float $beta Beta
* @param null|float $tau Tau
* @param null|float $drawProbability Draw probability
*
* @since 1.0.0
*/
public function __construct(
?float $mu = null,
?float $sigma = null,
?float $beta = null,
?float $tau = null,
?float $drawProbability = null)
public function __construct()
{
$this->mu = $mu ?? self::DEFAULT_MU;
$this->sigma = $sigma ?? self::DEFAULT_SIGMA;
$this->beta = $beta ?? self::DEFAULT_BETA;
$this->tau = $tau ?? self::DEFAULT_TAU;
$this->drawProbability = $drawProbability ?? self::DEFAULT_DRAW_PROBABILITY;
}
/**
* Calculate win probability
*
* @param array $team1 Team 1
* @param array $team2 Team 2
* @param float $drawMargin Draw margin
*
* @return float
*
* @since 1.0.0
*/
public function winProbability(array $team1, array $team2, float $drawMargin = 0.0) : float
{
$sigmaSum = 0.0;
$mu1 = 0.0;
foreach ($team1 as $player) {
$mu1 += $player->mu;
$sigmaSum += $player->sigma * $player->sigma;
}
$mu2 = 0.0;
foreach ($team2 as $player) {
$mu2 += $player->mu;
$sigmaSum += $player->sigma * $player->sigma;
}
$deltaMu = $mu1 - $mu2;
return NormalDistribution::getCdf(
($deltaMu - $drawMargin) / \sqrt((\count($team1) + \count($team2)) * ($this->beta * $this->beta) + $sigmaSum),
0,
1
);
}
// Draw margin = epsilon

View File

@ -1,28 +0,0 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Rating;
/**
* Elo rating calculation using Elo rating
*
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://en.wikipedia.org/wiki/Elo_rating_system
* @since 1.0.0
*/
final class TrueSkillFactoryGraph
{
}

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

View File

@ -2,7 +2,7 @@
/**
* Jingga
*
* PHP Version 8.2
* PHP Version 8.1
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn

Some files were not shown because too many files have changed in this diff Show More