mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-01-11 17:58:41 +00:00
Compare commits
183 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cb4c61fb5b | |||
| a480f4712f | |||
| 250f64556d | |||
|
|
326e2172ec | ||
|
|
af9a7e1f29 | ||
|
|
efd5580a75 | ||
|
|
4dff3d3289 | ||
|
|
126fca5574 | ||
|
|
5230892673 | ||
|
|
ca57051cd7 | ||
|
|
370e4fa420 | ||
|
|
f7fe30e545 | ||
| 167c7f08e7 | |||
|
|
982fab8018 | ||
|
|
189d37580d | ||
|
|
121e6b4486 | ||
|
|
1d49ceb5a0 | ||
|
|
f991f15889 | ||
|
|
1c2ecda287 | ||
|
|
ab3e8e0939 | ||
|
|
61f44bc044 | ||
|
|
b2cd928809 | ||
|
|
9ca0be2825 | ||
|
|
27ad14b4c5 | ||
|
|
d6ddf6cbe9 | ||
|
|
a1b591d141 | ||
| 7bb5c3eb83 | |||
|
|
8c2ea75430 | ||
|
|
384b784995 | ||
|
|
279bd8a3bf | ||
|
|
0bf99750b8 | ||
|
|
44098e33d2 | ||
|
|
5876d88901 | ||
|
|
7b76d797b8 | ||
|
|
a2e7ae6a25 | ||
|
|
cc243cffd7 | ||
|
|
48c5164e12 | ||
|
|
642b74ad22 | ||
|
|
2a41801b77 | ||
|
|
006a611a07 | ||
| 381bf25f13 | |||
|
|
405638417e | ||
|
|
e7b708185e | ||
|
|
84fa78359b | ||
|
|
01649f0489 | ||
|
|
84d73bf821 | ||
|
|
f14f65ffd3 | ||
|
|
8f735ef121 | ||
|
|
b92e1f08e7 | ||
|
|
67886a9dc8 | ||
|
|
4e1630a124 | ||
|
|
f1a64bdc64 | ||
|
|
560f8a2796 | ||
|
|
ea0b033e1c | ||
|
|
b5944503d8 | ||
|
|
b447c0772c | ||
|
|
96f9db5395 | ||
|
|
047d96a776 | ||
|
|
5433e64d8e | ||
|
|
d4aa5b1bc5 | ||
|
|
f3b0ff3756 | ||
|
|
ce150dea48 | ||
|
|
03723410dc | ||
|
|
3bed5e3cc0 | ||
|
|
bf235e34ee | ||
|
|
b7fa018718 | ||
|
|
f3f3f2846b | ||
|
|
5c38b8b250 | ||
|
|
0c9921b737 | ||
|
|
6448930755 | ||
|
|
bbb9d06f29 | ||
|
|
36b7143829 | ||
|
|
7b90d4eb54 | ||
|
|
fa3d48bc24 | ||
|
|
171413c108 | ||
|
|
268495a5f3 | ||
|
|
d547401cb1 | ||
|
|
889e71e5ab | ||
|
|
91c59ba329 | ||
|
|
d904e6e0bc | ||
|
|
4645d59b8a | ||
|
|
9018cf5b57 | ||
|
|
1675a82410 | ||
|
|
dd0a71421a | ||
|
|
d22f0a6d18 | ||
|
|
ec49bf2dc1 | ||
|
|
999ec823b3 | ||
|
|
d96a842e81 | ||
|
|
61253e92b4 | ||
|
|
b871ba283c | ||
|
|
1b738dfe5a | ||
|
|
45bab0c041 | ||
|
|
5f8004da25 | ||
|
|
b7c9453621 | ||
|
|
479c48b713 | ||
|
|
f79ba2f67e | ||
|
|
d2d0c6bfcf | ||
|
|
bf9d528076 | ||
|
|
ab7b467c1d | ||
|
|
660e2dbbfd | ||
|
|
8c5486bed4 | ||
|
|
60fa60a91a | ||
|
|
310a716769 | ||
|
|
ab5230b8bd | ||
|
|
58120ac97d | ||
|
|
b4384f965a | ||
|
|
484963099d | ||
|
|
31a77c08e5 | ||
|
|
bbbf96ad8e | ||
|
|
6e461461e0 | ||
|
|
5ba31111bc | ||
|
|
95eb37853e | ||
|
|
cd36282b4f | ||
|
|
17603e2d05 | ||
|
|
941bdac44e | ||
|
|
d8e0d40c6a | ||
|
|
630a38b897 | ||
|
|
4bed0db195 | ||
|
|
1e197375c5 | ||
|
|
f435905146 | ||
|
|
90b807093b | ||
|
|
1f9f97f8d9 | ||
|
|
c52b6c8863 | ||
|
|
8f0f105b8a | ||
|
|
3656d6df97 | ||
|
|
8c9e6929d0 | ||
|
|
8b3daf3c8d | ||
|
|
7a086fea93 | ||
|
|
2cbbe69bac | ||
|
|
a4f7d2e527 | ||
|
|
5a1ea1ee49 | ||
|
|
fdcf1645f2 | ||
|
|
8fd2cca24b | ||
|
|
9c02749567 | ||
|
|
772453e753 | ||
|
|
8a8ee4ed90 | ||
|
|
60ccfdb242 | ||
|
|
9d2b2e2e06 | ||
|
|
65264e33ae | ||
|
|
c224209c28 | ||
|
|
9b71428f88 | ||
|
|
b4af5e237c | ||
|
|
5e6ccb0b36 | ||
|
|
663cf6b11e | ||
|
|
4a208b8cd0 | ||
|
|
0d8a2fc59d | ||
|
|
9c86108a0f | ||
|
|
dcc60246df | ||
|
|
2b6e7b008d | ||
|
|
bd29e83c06 | ||
|
|
4807dcf5c2 | ||
|
|
e997408bb6 | ||
|
|
0b5d51f9b8 | ||
|
|
b9aec88a4b | ||
|
|
513fa7bf8b | ||
|
|
ae6391ecf8 | ||
|
|
624d6b517e | ||
|
|
2655c816a9 | ||
|
|
567ab3bfcd | ||
|
|
99211861eb | ||
|
|
eff9f243d9 | ||
|
|
007fc6dfe8 | ||
|
|
cd9a5cdc11 | ||
|
|
e873f909fd | ||
|
|
febcc20001 | ||
| 2e32c8a7cc | |||
|
|
6dcb540248 | ||
| a3f4d61b6e | |||
|
|
d42fee56af | ||
|
|
39418dbe23 | ||
|
|
e51b7ba93c | ||
|
|
cdea41f714 | ||
|
|
be8ae797db | ||
|
|
42ca4d6690 | ||
|
|
69f64f331b | ||
|
|
bdf238a522 | ||
|
|
7505eadee1 | ||
|
|
39a55a590b | ||
|
|
48de45149b | ||
|
|
3d8d0abaf6 | ||
| 695984e4fe | |||
| 9699842a7e | |||
|
|
d56488a58a |
12
.github/FUNDING.yml
vendored
12
.github/FUNDING.yml
vendored
|
|
@ -1,12 +0,0 @@
|
||||||
# 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
37
.github/dev_bug_report.md
vendored
|
|
@ -1,37 +0,0 @@
|
||||||
---
|
|
||||||
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
18
.github/dev_feature_request.md
vendored
|
|
@ -1,18 +0,0 @@
|
||||||
---
|
|
||||||
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.
|
|
||||||
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
|
|
@ -3,8 +3,9 @@ name: CI
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
general_module_workflow:
|
general_module_workflow_php:
|
||||||
uses: Karaka-Management/Karaka/.github/workflows/php_template.yml@develop
|
uses: Karaka-Management/Karaka/.github/workflows/php_template.yml@develop
|
||||||
secrets:
|
secrets:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GH_PAT: ${{ secrets.GH_PAT }}
|
GH_PAT: ${{ secrets.GH_PAT }}
|
||||||
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -15,7 +15,6 @@ declare(strict_types=1);
|
||||||
namespace phpOMS\Account;
|
namespace phpOMS\Account;
|
||||||
|
|
||||||
use phpOMS\Localization\Localization;
|
use phpOMS\Localization\Localization;
|
||||||
use phpOMS\Stdlib\Base\Exception\InvalidEnumValue;
|
|
||||||
use phpOMS\Validation\Network\Email;
|
use phpOMS\Validation\Network\Email;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -164,12 +163,12 @@ class Account implements \JsonSerializable
|
||||||
*/
|
*/
|
||||||
public function hasPermission(
|
public function hasPermission(
|
||||||
int $permission,
|
int $permission,
|
||||||
int $unit = null,
|
?int $unit = null,
|
||||||
int $app = null,
|
?int $app = null,
|
||||||
string $module = null,
|
?string $module = null,
|
||||||
int $category = null,
|
?int $category = null,
|
||||||
int $element = null,
|
?int $element = null,
|
||||||
int $component = null
|
?int $component = null
|
||||||
) : bool
|
) : bool
|
||||||
{
|
{
|
||||||
foreach ($this->groups as $group) {
|
foreach ($this->groups as $group) {
|
||||||
|
|
@ -317,70 +316,6 @@ class Account implements \JsonSerializable
|
||||||
$this->email = \mb_strtolower($email);
|
$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.
|
* Get last activity.
|
||||||
*
|
*
|
||||||
|
|
@ -445,8 +380,8 @@ class Account implements \JsonSerializable
|
||||||
public function toArray() : array
|
public function toArray() : array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'name' => [
|
'name' => [
|
||||||
$this->name1,
|
$this->name1,
|
||||||
$this->name2,
|
$this->name2,
|
||||||
$this->name3,
|
$this->name3,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -71,8 +71,8 @@ final class AccountManager implements \Countable
|
||||||
if ($id === 0) {
|
if ($id === 0) {
|
||||||
$account = new Account(Auth::authenticate($this->session));
|
$account = new Account(Auth::authenticate($this->session));
|
||||||
|
|
||||||
if (!isset($this->accounts[$account->getId()])) {
|
if (!isset($this->accounts[$account->id])) {
|
||||||
$this->accounts[$account->getId()] = $account;
|
$this->accounts[$account->id] = $account;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
|
|
@ -92,8 +92,8 @@ final class AccountManager implements \Countable
|
||||||
*/
|
*/
|
||||||
public function add(Account $account) : bool
|
public function add(Account $account) : bool
|
||||||
{
|
{
|
||||||
if (!isset($this->accounts[$account->getId()])) {
|
if (!isset($this->accounts[$account->id])) {
|
||||||
$this->accounts[$account->getId()] = $account;
|
$this->accounts[$account->id] = $account;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -14,8 +14,6 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace phpOMS\Account;
|
namespace phpOMS\Account;
|
||||||
|
|
||||||
use phpOMS\Stdlib\Base\Exception\InvalidEnumValue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account group class.
|
* Account group class.
|
||||||
*
|
*
|
||||||
|
|
@ -88,38 +86,6 @@ class Group implements \JsonSerializable
|
||||||
return $this->id;
|
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.
|
* Get string representation.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -24,6 +24,18 @@ namespace phpOMS\Account;
|
||||||
*/
|
*/
|
||||||
final class NullAccount extends 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}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -169,13 +169,13 @@ class PermissionAbstract implements \JsonSerializable
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
int $unit = null,
|
?int $unit = null,
|
||||||
int $app = null,
|
?int $app = null,
|
||||||
string $module = null,
|
?string $module = null,
|
||||||
string $from = null,
|
?string $from = null,
|
||||||
int $category = null,
|
?int $category = null,
|
||||||
int $element = null,
|
?int $element = null,
|
||||||
int $component = null,
|
?int $component = null,
|
||||||
int $permission = PermissionType::NONE
|
int $permission = PermissionType::NONE
|
||||||
) {
|
) {
|
||||||
$this->unit = $unit;
|
$this->unit = $unit;
|
||||||
|
|
@ -308,12 +308,12 @@ class PermissionAbstract implements \JsonSerializable
|
||||||
*/
|
*/
|
||||||
public function hasPermission(
|
public function hasPermission(
|
||||||
int $permission,
|
int $permission,
|
||||||
int $unit = null,
|
?int $unit = null,
|
||||||
int $app = null,
|
?int $app = null,
|
||||||
string $module = null,
|
?string $module = null,
|
||||||
int $category = null,
|
?int $category = null,
|
||||||
int $element = null,
|
?int $element = null,
|
||||||
int $component = null
|
?int $component = null
|
||||||
) : bool
|
) : bool
|
||||||
{
|
{
|
||||||
return $permission === PermissionType::NONE ||
|
return $permission === PermissionType::NONE ||
|
||||||
|
|
@ -352,15 +352,15 @@ class PermissionAbstract implements \JsonSerializable
|
||||||
public function jsonSerialize() : mixed
|
public function jsonSerialize() : mixed
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'unit' => $this->unit,
|
'unit' => $this->unit,
|
||||||
'app' => $this->app,
|
'app' => $this->app,
|
||||||
'module' => $this->module,
|
'module' => $this->module,
|
||||||
'from' => $this->from,
|
'from' => $this->from,
|
||||||
'category' => $this->category,
|
'category' => $this->category,
|
||||||
'element' => $this->element,
|
'element' => $this->element,
|
||||||
'component' => $this->component,
|
'component' => $this->component,
|
||||||
'permission' => $this->getPermission(),
|
'permission' => $this->getPermission(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -135,12 +135,12 @@ trait PermissionHandlingTrait
|
||||||
*/
|
*/
|
||||||
public function hasPermission(
|
public function hasPermission(
|
||||||
int $permission,
|
int $permission,
|
||||||
int $unit = null,
|
?int $unit = null,
|
||||||
int $app = null,
|
?int $app = null,
|
||||||
string $module = null,
|
?string $module = null,
|
||||||
int $category = null,
|
?int $category = null,
|
||||||
int $element = null,
|
?int $element = null,
|
||||||
int $component = null
|
?int $component = null
|
||||||
) : bool
|
) : bool
|
||||||
{
|
{
|
||||||
foreach ($this->permissions as $p) {
|
foreach ($this->permissions as $p) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Account
|
* @package phpOMS\Account
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Ai\NeuralNetwork
|
* @package phpOMS\Ai\NeuralNetwork
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -22,7 +22,7 @@ namespace phpOMS\Ai\NeuralNetwork;
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
class Neuron
|
final class Neuron
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Neuron inputs
|
* Neuron inputs
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Ai\Ocr
|
* @package phpOMS\Ai\Ocr
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Ai\Ocr\Tesseract
|
* @package phpOMS\Ai\Ocr\Tesseract
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -85,14 +85,34 @@ final class TesseractOcr
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function parseImage(string $image, array $languages = ['eng'], int $psm = 3, int $oem = 3) : string
|
public function parseImage(string $image, array $languages = ['eng', 'deu'], int $psm = 3, int $oem = 3) : string
|
||||||
{
|
{
|
||||||
$temp = \tempnam(\sys_get_temp_dir(), 'oms_ocr_');
|
$temp = \tempnam(\sys_get_temp_dir(), 'oms_ocr_');
|
||||||
if ($temp === false) {
|
if ($temp === false) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$extension = 'png';
|
||||||
try {
|
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(
|
SystemUtils::runProc(
|
||||||
self::$bin,
|
self::$bin,
|
||||||
$image . ' '
|
$image . ' '
|
||||||
|
|
@ -100,12 +120,20 @@ final class TesseractOcr
|
||||||
. ' -c preserve_interword_spaces=1'
|
. ' -c preserve_interword_spaces=1'
|
||||||
. ' --psm ' . $psm
|
. ' --psm ' . $psm
|
||||||
. ' --oem ' . $oem
|
. ' --oem ' . $oem
|
||||||
. ' -l ' . \implode('+', $languages)
|
. (empty($languages) ? '' : ' -l ' . \implode('+', $languages))
|
||||||
);
|
);
|
||||||
} catch (\Throwable $_) {
|
} catch (\Throwable $_) {
|
||||||
|
if (\is_file($temp . '.' . $extension)) {
|
||||||
|
\unlink($temp . '.' . $extension);
|
||||||
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\is_file($temp . '.' . $extension)) {
|
||||||
|
\unlink($temp . '.' . $extension);
|
||||||
|
}
|
||||||
|
|
||||||
$filepath = \is_file($temp . '.txt')
|
$filepath = \is_file($temp . '.txt')
|
||||||
? $temp . '.txt'
|
? $temp . '.txt'
|
||||||
: $temp;
|
: $temp;
|
||||||
|
|
@ -120,11 +148,7 @@ final class TesseractOcr
|
||||||
|
|
||||||
$parsed = \file_get_contents($filepath);
|
$parsed = \file_get_contents($filepath);
|
||||||
if ($parsed === false) {
|
if ($parsed === false) {
|
||||||
// @codeCoverageIgnoreStart
|
$parsed = '';
|
||||||
\unlink($temp);
|
|
||||||
|
|
||||||
return '';
|
|
||||||
// @codeCoverageIgnoreEnd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
\unlink($filepath);
|
\unlink($filepath);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -14,17 +14,141 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace phpOMS\Algorithm\Clustering;
|
namespace phpOMS\Algorithm\Clustering;
|
||||||
|
|
||||||
|
use phpOMS\Math\Topology\MetricsND;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clustering points
|
* Clustering points
|
||||||
*
|
*
|
||||||
|
* The parent category of this clustering algorithm is hierarchical clustering.
|
||||||
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
|
* @license Base: MIT Copyright (c) 2020 Greene Laboratory
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
|
* @see ./DivisiveClustering.php
|
||||||
* @see ./clustering_overview.png
|
* @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
|
* @since 1.0.0
|
||||||
*
|
*
|
||||||
* @todo Implement
|
* @todo Implement
|
||||||
|
* @todo Implement missing linkage functions
|
||||||
*/
|
*/
|
||||||
final class AgglomerativeClustering
|
final class AgglomerativeClustering implements ClusteringInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 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 [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -25,6 +25,37 @@ namespace phpOMS\Algorithm\Clustering;
|
||||||
*
|
*
|
||||||
* @todo Implement
|
* @todo Implement
|
||||||
*/
|
*/
|
||||||
final class Birch
|
final class Birch 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 [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
71
Algorithm/Clustering/ClusteringInterface.php
Normal file
71
Algorithm/Clustering/ClusteringInterface.php
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?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
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -29,7 +29,7 @@ use phpOMS\Math\Topology\MetricsND;
|
||||||
*
|
*
|
||||||
* @todo Expand to n dimensions
|
* @todo Expand to n dimensions
|
||||||
*/
|
*/
|
||||||
final class DBSCAN
|
final class DBSCAN implements ClusteringInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Epsilon for float comparison.
|
* Epsilon for float comparison.
|
||||||
|
|
@ -50,7 +50,7 @@ final class DBSCAN
|
||||||
/**
|
/**
|
||||||
* Points outside of any cluster
|
* Points outside of any cluster
|
||||||
*
|
*
|
||||||
* @var PointInterface[]
|
* @var Point[]
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private array $noisePoints = [];
|
private array $noisePoints = [];
|
||||||
|
|
@ -58,17 +58,25 @@ final class DBSCAN
|
||||||
/**
|
/**
|
||||||
* All points
|
* All points
|
||||||
*
|
*
|
||||||
* @var PointInterface[]
|
* @var Point[]
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private array $points = [];
|
private array $points = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points of the cluster centers
|
||||||
|
*
|
||||||
|
* @var Point[]
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private array $clusterCenters = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clusters
|
* Clusters
|
||||||
*
|
*
|
||||||
* Array of points assigned to a cluster
|
* Array of points assigned to a cluster
|
||||||
*
|
*
|
||||||
* @var array<int, array>
|
* @var array<int, Point[]>
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private array $clusters = [];
|
private array $clusters = [];
|
||||||
|
|
@ -108,9 +116,9 @@ final class DBSCAN
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct(\Closure $metric = null)
|
public function __construct(?\Closure $metric = null)
|
||||||
{
|
{
|
||||||
$this->metric = $metric ?? function (PointInterface $a, PointInterface $b) {
|
$this->metric = $metric ?? function (Point $a, Point $b) {
|
||||||
$aCoordinates = $a->coordinates;
|
$aCoordinates = $a->coordinates;
|
||||||
$bCoordinates = $b->coordinates;
|
$bCoordinates = $b->coordinates;
|
||||||
|
|
||||||
|
|
@ -121,18 +129,18 @@ final class DBSCAN
|
||||||
/**
|
/**
|
||||||
* Expand cluster with additional point and potential neighbors.
|
* Expand cluster with additional point and potential neighbors.
|
||||||
*
|
*
|
||||||
* @param PointInterface $point Point to add to a cluster
|
* @param Point $point Point to add to a cluster
|
||||||
* @param array $neighbors Neighbors of point
|
* @param array $neighbors Neighbors of point
|
||||||
* @param int $c Cluster id
|
* @param int $c Cluster id
|
||||||
* @param float $epsilon Max distance
|
* @param float $epsilon Max distance
|
||||||
* @param int $minPoints Min amount of points required for a cluster
|
* @param int $minPoints Min amount of points required for a cluster
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private function expandCluster(
|
private function expandCluster(
|
||||||
PointInterface $point,
|
Point $point,
|
||||||
array $neighbors,
|
array $neighbors,
|
||||||
int $c,
|
int $c,
|
||||||
float $epsilon,
|
float $epsilon,
|
||||||
|
|
@ -166,14 +174,14 @@ final class DBSCAN
|
||||||
/**
|
/**
|
||||||
* Find neighbors of a point
|
* Find neighbors of a point
|
||||||
*
|
*
|
||||||
* @param PointInterface $point Base point for potential neighbors
|
* @param Point $point Base point for potential neighbors
|
||||||
* @param float $epsilon Max distance to neighbor
|
* @param float $epsilon Max distance to neighbor
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private function findNeighbors(PointInterface $point, float $epsilon) : array
|
private function findNeighbors(Point $point, float $epsilon) : array
|
||||||
{
|
{
|
||||||
$neighbors = [];
|
$neighbors = [];
|
||||||
foreach ($this->points as $point2) {
|
foreach ($this->points as $point2) {
|
||||||
|
|
@ -215,15 +223,9 @@ final class DBSCAN
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the cluster for a point
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param PointInterface $point Point to find the cluster for
|
|
||||||
*
|
|
||||||
* @return int Cluster id
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
*/
|
||||||
public function cluster(PointInterface $point) : int
|
public function cluster(Point $point) : ?Point
|
||||||
{
|
{
|
||||||
if ($this->convexHulls === []) {
|
if ($this->convexHulls === []) {
|
||||||
foreach ($this->clusters as $c => $cluster) {
|
foreach ($this->clusters as $c => $cluster) {
|
||||||
|
|
@ -232,26 +234,26 @@ final class DBSCAN
|
||||||
$points[] = $p->coordinates;
|
$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);
|
$this->convexHulls[$c] = MonotoneChain::createConvexHull($points);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->convexHulls as $c => $hull) {
|
foreach ($this->convexHulls as $c => $hull) {
|
||||||
if (Polygon::isPointInPolygon($point->coordinates, $hull) <= 0) {
|
if (Polygon::isPointInPolygon($point->coordinates, $hull) <= 0) {
|
||||||
return $c;
|
return $hull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the clusters of the points
|
* Generate the clusters of the points
|
||||||
*
|
*
|
||||||
* @param PointInterface[] $points Points to cluster
|
* @param Point[] $points Points to cluster
|
||||||
* @param float $epsilon Max distance
|
* @param float $epsilon Max distance
|
||||||
* @param int $minPoints Min amount of points required for a cluster
|
* @param int $minPoints Min amount of points required for a cluster
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
@ -282,4 +284,48 @@ final class DBSCAN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
Algorithm/Clustering/DivisiveClustering.php
Normal file
65
Algorithm/Clustering/DivisiveClustering.php
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?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 [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -25,7 +25,7 @@ use phpOMS\Math\Topology\MetricsND;
|
||||||
* @see ./clustering_overview.png
|
* @see ./clustering_overview.png
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
final class Kmeans
|
final class Kmeans implements ClusteringInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Epsilon for float comparison.
|
* Epsilon for float comparison.
|
||||||
|
|
@ -46,10 +46,26 @@ final class Kmeans
|
||||||
/**
|
/**
|
||||||
* Points of the cluster centers
|
* Points of the cluster centers
|
||||||
*
|
*
|
||||||
* @var PointInterface[]
|
* @var Point[]
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private $clusterCenters = [];
|
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 = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
|
@ -58,28 +74,20 @@ final class Kmeans
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function __construct(\Closure $metric = null)
|
public function __construct(?\Closure $metric = null)
|
||||||
{
|
{
|
||||||
$this->metric = $metric ?? function (PointInterface $a, PointInterface $b) {
|
$this->metric = $metric ?? function (Point $a, Point $b) {
|
||||||
$aCoordinates = $a->coordinates;
|
$aCoordinates = $a->coordinates;
|
||||||
$bCoordinates = $b->coordinates;
|
$bCoordinates = $b->coordinates;
|
||||||
|
|
||||||
return MetricsND::euclidean($aCoordinates, $bCoordinates);
|
return MetricsND::euclidean($aCoordinates, $bCoordinates);
|
||||||
};
|
};
|
||||||
|
|
||||||
//$this->generateClusters($points, $clusters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the cluster for a point
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param PointInterface $point Point to find the cluster for
|
|
||||||
*
|
|
||||||
* @return null|PointInterface Cluster center point
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
*/
|
||||||
public function cluster(PointInterface $point) : ?PointInterface
|
public function cluster(Point $point) : ?Point
|
||||||
{
|
{
|
||||||
$bestCluster = null;
|
$bestCluster = null;
|
||||||
$bestDistance = \PHP_FLOAT_MAX;
|
$bestDistance = \PHP_FLOAT_MAX;
|
||||||
|
|
@ -95,22 +103,26 @@ final class Kmeans
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get cluster centroids
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
*/
|
||||||
public function getCentroids() : array
|
public function getCentroids() : array
|
||||||
{
|
{
|
||||||
return $this->clusterCenters;
|
return $this->clusterCenters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getNoise() : array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the clusters of the points
|
* Generate the clusters of the points
|
||||||
*
|
*
|
||||||
* @param PointInterface[] $points Points to cluster
|
* @param Point[] $points Points to cluster
|
||||||
* @param int<0, max> $clusters Amount of clusters
|
* @param int<1, max> $clusters Amount of clusters
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
|
|
@ -118,6 +130,7 @@ final class Kmeans
|
||||||
*/
|
*/
|
||||||
public function generateClusters(array $points, int $clusters) : void
|
public function generateClusters(array $points, int $clusters) : void
|
||||||
{
|
{
|
||||||
|
$this->points = $points;
|
||||||
$n = \count($points);
|
$n = \count($points);
|
||||||
$clusterCenters = $this->kpp($points, $clusters);
|
$clusterCenters = $this->kpp($points, $clusters);
|
||||||
$coordinates = \count($points[0]->coordinates);
|
$coordinates = \count($points[0]->coordinates);
|
||||||
|
|
@ -140,8 +153,7 @@ final class Kmeans
|
||||||
|
|
||||||
foreach ($clusterCenters as $center) {
|
foreach ($clusterCenters as $center) {
|
||||||
for ($i = 0; $i < $coordinates; ++$i) {
|
for ($i = 0; $i < $coordinates; ++$i) {
|
||||||
// @todo Invalid center coodinate value in like 5 % of the runs
|
$center->setCoordinate($i, $center->getCoordinate($i) / $center->group);
|
||||||
$center->setCoordinate($i, $center->getCoordinate($i) / ($center->group === 0 ? 1 : $center->group));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,7 +161,7 @@ final class Kmeans
|
||||||
foreach ($points as $point) {
|
foreach ($points as $point) {
|
||||||
$min = $this->nearestClusterCenter($point, $clusterCenters)[0];
|
$min = $this->nearestClusterCenter($point, $clusterCenters)[0];
|
||||||
|
|
||||||
if ($min !== $point->group) {
|
if ($clusters !== $point->group) {
|
||||||
++$changed;
|
++$changed;
|
||||||
$point->group = $min;
|
$point->group = $min;
|
||||||
}
|
}
|
||||||
|
|
@ -171,14 +183,14 @@ final class Kmeans
|
||||||
/**
|
/**
|
||||||
* Get the index and distance to the nearest cluster center
|
* Get the index and distance to the nearest cluster center
|
||||||
*
|
*
|
||||||
* @param PointInterface $point Point to get the cluster for
|
* @param Point $point Point to get the cluster for
|
||||||
* @param PointInterface[] $clusterCenters All cluster centers
|
* @param Point[] $clusterCenters All cluster centers
|
||||||
*
|
*
|
||||||
* @return array [index, distance]
|
* @return array [index, distance]
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private function nearestClusterCenter(PointInterface $point, array $clusterCenters) : array
|
private function nearestClusterCenter(Point $point, array $clusterCenters) : array
|
||||||
{
|
{
|
||||||
$index = $point->group;
|
$index = $point->group;
|
||||||
$dist = \PHP_FLOAT_MAX;
|
$dist = \PHP_FLOAT_MAX;
|
||||||
|
|
@ -196,43 +208,71 @@ final class Kmeans
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializae cluster centers
|
* Initialize cluster centers
|
||||||
*
|
*
|
||||||
* @param PointInterface[] $points Points to use for the cluster center initialization
|
* @param Point[] $points Points to use for the cluster center initialization
|
||||||
* @param int<0, max> $n Amount of clusters to use
|
* @param int<0, max> $n Amount of clusters to use
|
||||||
*
|
*
|
||||||
* @return PointInterface[]
|
* @return Point[]
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private function kpp(array $points, int $n) : array
|
private function kpp(array $points, int $n) : array
|
||||||
{
|
{
|
||||||
$clusters = [clone $points[\mt_rand(0, \count($points) - 1)]];
|
$clusters = [clone $points[\array_rand($points, 1)]];
|
||||||
$d = \array_fill(0, $n, 0.0);
|
|
||||||
|
$d = \array_fill(0, $n, 0.0);
|
||||||
|
|
||||||
for ($i = 1; $i < $n; ++$i) {
|
for ($i = 1; $i < $n; ++$i) {
|
||||||
$sum = 0;
|
$sum = 0;
|
||||||
|
|
||||||
foreach ($points as $key => $point) {
|
foreach ($points as $key => $point) {
|
||||||
$d[$key] = $this->nearestClusterCenter($point, \array_slice($clusters, 0, 5))[1];
|
$d[$key] = $this->nearestClusterCenter($point, $clusters)[1];
|
||||||
$sum += $d[$key];
|
$sum += $d[$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
$sum *= \mt_rand(0, \mt_getrandmax()) / \mt_getrandmax();
|
$sum *= \mt_rand(0, \mt_getrandmax()) / \mt_getrandmax();
|
||||||
|
|
||||||
|
$found = false;
|
||||||
foreach ($d as $key => $di) {
|
foreach ($d as $key => $di) {
|
||||||
$sum -= $di;
|
$sum -= $di;
|
||||||
|
|
||||||
if ($sum <= 0) {
|
// The in array check is important to avoid duplicate cluster centers
|
||||||
$clusters[$i] = clone $points[$key];
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($points as $point) {
|
foreach ($points as $point) {
|
||||||
$point->group = ($this->nearestClusterCenter($point, $clusters)[0]);
|
$point->group = $this->nearestClusterCenter($point, $clusters)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $clusters;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -25,8 +25,10 @@ use phpOMS\Math\Topology\MetricsND;
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
* @see ./clustering_overview.png
|
* @see ./clustering_overview.png
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
|
*
|
||||||
|
* @todo Implement noise points
|
||||||
*/
|
*/
|
||||||
final class MeanShift
|
final class MeanShift implements ClusteringInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Min distance for clustering
|
* Min distance for clustering
|
||||||
|
|
@ -59,7 +61,7 @@ final class MeanShift
|
||||||
/**
|
/**
|
||||||
* Points outside of any cluster
|
* Points outside of any cluster
|
||||||
*
|
*
|
||||||
* @var PointInterface[]
|
* @var Point[]
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private array $noisePoints = [];
|
private array $noisePoints = [];
|
||||||
|
|
@ -77,10 +79,10 @@ final class MeanShift
|
||||||
/**
|
/**
|
||||||
* Points of the cluster centers
|
* Points of the cluster centers
|
||||||
*
|
*
|
||||||
* @var PointInterface[]
|
* @var Point[]
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private $clusterCenters = [];
|
private array $clusterCenters = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Max distance to cluster to be still considered part of cluster
|
* Max distance to cluster to be still considered part of cluster
|
||||||
|
|
@ -100,9 +102,9 @@ final class MeanShift
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @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 (PointInterface $a, PointInterface $b) {
|
$this->metric = $metric ?? function (Point $a, Point $b) {
|
||||||
$aCoordinates = $a->coordinates;
|
$aCoordinates = $a->coordinates;
|
||||||
$bCoordinates = $b->coordinates;
|
$bCoordinates = $b->coordinates;
|
||||||
|
|
||||||
|
|
@ -117,7 +119,7 @@ final class MeanShift
|
||||||
/**
|
/**
|
||||||
* Generate the clusters of the points
|
* Generate the clusters of the points
|
||||||
*
|
*
|
||||||
* @param PointInterface[] $points Points to cluster
|
* @param Point[] $points Points to cluster
|
||||||
* @param array<int|float> $bandwidth Bandwidth(s)
|
* @param array<int|float> $bandwidth Bandwidth(s)
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
|
|
@ -126,8 +128,9 @@ final class MeanShift
|
||||||
*/
|
*/
|
||||||
public function generateClusters(array $points, array $bandwidth) : void
|
public function generateClusters(array $points, array $bandwidth) : void
|
||||||
{
|
{
|
||||||
$shiftPoints = $points;
|
$this->points = $points;
|
||||||
$maxMinDist = 1;
|
$shiftPoints = $points;
|
||||||
|
$maxMinDist = 1;
|
||||||
|
|
||||||
$stillShifting = \array_fill(0, \count($points), true);
|
$stillShifting = \array_fill(0, \count($points), true);
|
||||||
|
|
||||||
|
|
@ -167,15 +170,15 @@ final class MeanShift
|
||||||
/**
|
/**
|
||||||
* Perform shift on a point
|
* Perform shift on a point
|
||||||
*
|
*
|
||||||
* @param PointInterface $point Point to shift
|
* @param Point $point Point to shift
|
||||||
* @param PointInterface $points Array of all points
|
* @param Point $points Array of all points
|
||||||
* @param array<int|float> $bandwidth Bandwidth(s)
|
* @param array<int|float> $bandwidth Bandwidth(s)
|
||||||
*
|
*
|
||||||
* @return PointInterface
|
* @return Point
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private function shiftPoint(PointInterface $point, array $points, array $bandwidth) : PointInterface
|
private function shiftPoint(Point $point, array $points, array $bandwidth) : Point
|
||||||
{
|
{
|
||||||
$scaleFactor = 0.0;
|
$scaleFactor = 0.0;
|
||||||
|
|
||||||
|
|
@ -206,7 +209,7 @@ final class MeanShift
|
||||||
/**
|
/**
|
||||||
* Group points together into clusters
|
* Group points together into clusters
|
||||||
*
|
*
|
||||||
* @param PointInterface[] $points Array of points to assign to groups
|
* @param Point[] $points Array of points to assign to groups
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
|
|
@ -239,14 +242,14 @@ final class MeanShift
|
||||||
/**
|
/**
|
||||||
* Find the closest cluster/group of a point
|
* Find the closest cluster/group of a point
|
||||||
*
|
*
|
||||||
* @param PointInterface $point Point to find the cluster for
|
* @param Point $point Point to find the cluster for
|
||||||
* @param array<PointInterface[]> $groups Clusters
|
* @param array<Point[]> $groups Clusters
|
||||||
*
|
*
|
||||||
* @return int
|
* @return int
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private function findNearestGroup(PointInterface $point, array $groups) : int
|
private function findNearestGroup(Point $point, array $groups) : int
|
||||||
{
|
{
|
||||||
$nearestGroupIndex = -1;
|
$nearestGroupIndex = -1;
|
||||||
$index = 0;
|
$index = 0;
|
||||||
|
|
@ -269,14 +272,14 @@ final class MeanShift
|
||||||
/**
|
/**
|
||||||
* Find distance of point to best cluster/group
|
* Find distance of point to best cluster/group
|
||||||
*
|
*
|
||||||
* @param PointInterface $point Point to find the cluster for
|
* @param Point $point Point to find the cluster for
|
||||||
* @param PointInterface[] $group Clusters
|
* @param Point[] $group Clusters
|
||||||
*
|
*
|
||||||
* @return float Distance
|
* @return float Distance
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
private function distanceToGroup(PointInterface $point, array $group) : float
|
private function distanceToGroup(Point $point, array $group) : float
|
||||||
{
|
{
|
||||||
$minDistance = \PHP_FLOAT_MAX;
|
$minDistance = \PHP_FLOAT_MAX;
|
||||||
|
|
||||||
|
|
@ -292,18 +295,36 @@ final class MeanShift
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the cluster for a point
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @param PointInterface $point Point to find the cluster for
|
|
||||||
*
|
|
||||||
* @return null|PointInterface Cluster center point
|
|
||||||
*
|
|
||||||
* @since 1.0.0
|
|
||||||
*/
|
*/
|
||||||
public function cluster(PointInterface $point) : ?PointInterface
|
public function getCentroids() : array
|
||||||
|
{
|
||||||
|
return $this->clusterCenters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function cluster(Point $point) : ?Point
|
||||||
{
|
{
|
||||||
$clusterId = $this->findNearestGroup($point, $this->clusters);
|
$clusterId = $this->findNearestGroup($point, $this->clusters);
|
||||||
|
|
||||||
return $this->clusterCenters[$clusterId] ?? null;
|
return $this->clusterCenters[$clusterId] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getNoise() : array
|
||||||
|
{
|
||||||
|
return $this->noisePoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getClusters() : array
|
||||||
|
{
|
||||||
|
return $this->clusters;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -28,7 +28,7 @@ class Point implements PointInterface
|
||||||
* Coordinates of the point
|
* Coordinates of the point
|
||||||
*
|
*
|
||||||
* @var array<int, int|float>
|
* @var array<int, int|float>
|
||||||
* @sicne 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public array $coordinates = [];
|
public array $coordinates = [];
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@ class Point implements PointInterface
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function isEquals(PointInterface $point) : bool
|
public function isEquals(Point $point) : bool
|
||||||
{
|
{
|
||||||
return $this->name === $point->name && $this->coordinates === $point->coordinates;
|
return $this->name === $point->name && $this->coordinates === $point->coordinates;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -25,6 +25,10 @@ namespace phpOMS\Algorithm\Clustering;
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
|
*
|
||||||
|
* @property array<int, int|float> $coordinates
|
||||||
|
* @property string $name
|
||||||
|
* @property int $group
|
||||||
*/
|
*/
|
||||||
interface PointInterface
|
interface PointInterface
|
||||||
{
|
{
|
||||||
|
|
@ -63,11 +67,11 @@ interface PointInterface
|
||||||
/**
|
/**
|
||||||
* Check if two points are equal
|
* Check if two points are equal
|
||||||
*
|
*
|
||||||
* @param self $point Point to compare with
|
* @param Point $point Point to compare with
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public function isEquals(self $point) : bool;
|
public function isEquals(Point $point) : bool;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Clustering
|
* @package phpOMS\Algorithm\Clustering
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -25,6 +25,37 @@ namespace phpOMS\Algorithm\Clustering;
|
||||||
*
|
*
|
||||||
* @todo Implement
|
* @todo Implement
|
||||||
*/
|
*/
|
||||||
final class SpectralClustering
|
final class SpectralClustering 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 [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
<?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
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\CoinMatching
|
* @package phpOMS\Algorithm\CoinMatching
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\CoinMatching
|
* @package phpOMS\Algorithm\Frequency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
|
|
@ -12,14 +12,14 @@
|
||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace phpOMS\Algorithm\CoinMatching;
|
namespace phpOMS\Algorithm\Frequency;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apriori algorithm.
|
* Apriori algorithm.
|
||||||
*
|
*
|
||||||
* The algorithm cheks how often a set exists in a given set of sets.
|
* The algorithm checks how often a set exists in a given set of sets.
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\CoinMatching
|
* @package phpOMS\Algorithm\Frequency
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
|
|
@ -39,7 +39,7 @@ final class Apriori
|
||||||
/**
|
/**
|
||||||
* Generate all possible subsets
|
* Generate all possible subsets
|
||||||
*
|
*
|
||||||
* @param array $arr Array of eleements
|
* @param array $arr Array of elements
|
||||||
*
|
*
|
||||||
* @return array<array>
|
* @return array<array>
|
||||||
*
|
*
|
||||||
|
|
@ -70,13 +70,14 @@ final class Apriori
|
||||||
*
|
*
|
||||||
* The algorithm cheks 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.
|
||||||
*
|
*
|
||||||
* @param array<array> $sets Sets of a set (e.g. [[1,2,3,4], [1,2], [1]])
|
* @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)
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
public static function apriori(array $sets) : array
|
public static function apriori(array $sets, array $subset = []) : array
|
||||||
{
|
{
|
||||||
// Unique single items
|
// Unique single items
|
||||||
$totalSet = [];
|
$totalSet = [];
|
||||||
|
|
@ -90,6 +91,7 @@ final class Apriori
|
||||||
|
|
||||||
$totalSet = \array_unique($totalSet);
|
$totalSet = \array_unique($totalSet);
|
||||||
\sort($totalSet);
|
\sort($totalSet);
|
||||||
|
\sort($subset);
|
||||||
|
|
||||||
// Combinations of items
|
// Combinations of items
|
||||||
$combinations = self::generateSubsets($totalSet);
|
$combinations = self::generateSubsets($totalSet);
|
||||||
|
|
@ -98,10 +100,18 @@ final class Apriori
|
||||||
$table = [];
|
$table = [];
|
||||||
foreach ($combinations as &$c) {
|
foreach ($combinations as &$c) {
|
||||||
\sort($c);
|
\sort($c);
|
||||||
|
if (!empty($subset) && $c !== $subset) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$table[\implode(':', $c)] = 0;
|
$table[\implode(':', $c)] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($combinations as $combination) {
|
foreach ($combinations as $combination) {
|
||||||
|
if (!empty($subset) && $combination !== $subset) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($sets as $set) {
|
foreach ($sets as $set) {
|
||||||
foreach ($combination as $item) {
|
foreach ($combination as $item) {
|
||||||
if (!\in_array($item, $set)) {
|
if (!\in_array($item, $set)) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Graph;
|
* @package phpOMS\Algorithm\Graph;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -67,7 +67,7 @@ final class DependencyResolver
|
||||||
$unresolved[] = $dependency;
|
$unresolved[] = $dependency;
|
||||||
self::dependencyResolve($dependency, $items, $resolved, $unresolved);
|
self::dependencyResolve($dependency, $items, $resolved, $unresolved);
|
||||||
} else {
|
} else {
|
||||||
continue; // circular dependency
|
return; // circular dependency
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Graph
|
* @package phpOMS\Algorithm\Graph
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -21,9 +21,185 @@ namespace phpOMS\Algorithm\Graph;
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*
|
|
||||||
* @todo Implement
|
|
||||||
*/
|
*/
|
||||||
final class MarkovChain
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\JobScheduling
|
* @package phpOMS\Algorithm\JobScheduling
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -57,7 +57,7 @@ class Job implements JobInterface
|
||||||
public string $name = '';
|
public string $name = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cosntructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param float $value Value of the job
|
* @param float $value Value of the job
|
||||||
* @param \DateTime $start Start time of the job
|
* @param \DateTime $start Start time of the job
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\JobScheduling
|
* @package phpOMS\Algorithm\JobScheduling
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\JobScheduling
|
* @package phpOMS\Algorithm\JobScheduling
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -62,7 +62,7 @@ final class Weighted
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for a none-conflicting job that comes befor a defined job
|
* Search for a none-conflicting job that comes before a defined job
|
||||||
*
|
*
|
||||||
* @param JobInterface[] $jobs List of jobs
|
* @param JobInterface[] $jobs List of jobs
|
||||||
* @param int $pivot Job to find the previous job to
|
* @param int $pivot Job to find the previous job to
|
||||||
|
|
@ -130,7 +130,7 @@ final class Weighted
|
||||||
|
|
||||||
if ($l != -1) {
|
if ($l != -1) {
|
||||||
$value += $valueTable[$l];
|
$value += $valueTable[$l];
|
||||||
$jList = \array_merge($resultTable[$l], $jList);
|
$jList = \array_merge($resultTable[$l], $jList);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($value > $valueTable[$i - 1]) {
|
if ($value > $valueTable[$i - 1]) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling\Dependency
|
* @package phpOMS\Scheduling\Dependency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling\Dependency
|
* @package phpOMS\Scheduling\Dependency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling\Dependency
|
* @package phpOMS\Scheduling\Dependency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling\Dependency
|
* @package phpOMS\Scheduling\Dependency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling\Dependency
|
* @package phpOMS\Scheduling\Dependency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?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;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?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;
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling\Dependency
|
* @package phpOMS\Scheduling\Dependency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling\Dependency
|
* @package phpOMS\Scheduling\Dependency
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling
|
* @package phpOMS\Scheduling
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -24,32 +24,96 @@ namespace phpOMS\Scheduling;
|
||||||
*/
|
*/
|
||||||
class Job
|
class Job
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Id
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public int $id = 0;
|
public int $id = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time of the execution
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public int $executionTime = 0;
|
public int $executionTime = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Priority.
|
||||||
|
*
|
||||||
|
* @var float
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public float $priority = 0.0;
|
public float $priority = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value this job generates.
|
||||||
|
*
|
||||||
|
* @var float
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public float $value = 0.0;
|
public float $value = 0.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cost of executing this job.
|
||||||
|
*
|
||||||
|
* @var float
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public float $cost = 0.0;
|
public float $cost = 0.0;
|
||||||
|
|
||||||
/** How many iterations has this job been on hold in the queue */
|
/**
|
||||||
|
* How many iterations has this job been on hold in the queue.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public int $onhold = 0;
|
public int $onhold = 0;
|
||||||
|
|
||||||
/** How many iterations has this job been in process in the queue */
|
/**
|
||||||
|
* How many iterations has this job been in process in the queue.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public int $inprocessing = 0;
|
public int $inprocessing = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What is the deadline for this job?
|
||||||
|
*
|
||||||
|
* @param \DateTime
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public \DateTime $deadline;
|
public \DateTime $deadline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which steps must be taken during the job execution
|
||||||
|
*
|
||||||
|
* @var JobStep[]
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public array $steps = [];
|
public array $steps = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->deadline = new \DateTime('now');
|
$this->deadline = new \DateTime('now');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getProfit()
|
/**
|
||||||
|
* Get the profit of the job
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getProfit() : float
|
||||||
{
|
{
|
||||||
return $this->value - $this->cost;
|
return $this->value - $this->cost;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling
|
* @package phpOMS\Scheduling
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Scheduling
|
* @package phpOMS\Scheduling
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -24,8 +24,24 @@ namespace phpOMS\Scheduling;
|
||||||
*/
|
*/
|
||||||
final class ScheduleQueue
|
final class ScheduleQueue
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Queue
|
||||||
|
*
|
||||||
|
* @var Job[]
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
public array $queue = [];
|
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
|
public function get(int $size = 1, int $type = PriorityMode::FIFO) : array
|
||||||
{
|
{
|
||||||
$jobs = [];
|
$jobs = [];
|
||||||
|
|
@ -103,11 +119,33 @@ final class ScheduleQueue
|
||||||
return $jobs;
|
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
|
public function insert(int $id, Job $job) : void
|
||||||
{
|
{
|
||||||
$this->queue[$id] = $job;
|
$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
|
public function pop(int $size = 1, int $type = PriorityMode::FIFO) : array
|
||||||
{
|
{
|
||||||
$jobs = $this->get($size, $type);
|
$jobs = $this->get($size, $type);
|
||||||
|
|
@ -118,6 +156,15 @@ final class ScheduleQueue
|
||||||
return $jobs;
|
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
|
public function bumpHold(int $id = 0) : void
|
||||||
{
|
{
|
||||||
if ($id === 0) {
|
if ($id === 0) {
|
||||||
|
|
@ -129,6 +176,16 @@ 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
|
public function adjustPriority(int $id = 0, float $priority = 0.1) : void
|
||||||
{
|
{
|
||||||
if ($id === 0) {
|
if ($id === 0) {
|
||||||
|
|
@ -140,7 +197,16 @@ final class ScheduleQueue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function remove(string $id) : void
|
/**
|
||||||
|
* 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
|
||||||
{
|
{
|
||||||
unset($this->queue[$id]);
|
unset($this->queue[$id]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knapsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -106,7 +106,7 @@ class Backpack implements BackpackInterface
|
||||||
public function addItem(ItemInterface $item, int | float $quantity = 1) : void
|
public function addItem(ItemInterface $item, int | float $quantity = 1) : void
|
||||||
{
|
{
|
||||||
$this->items[] = ['item' => $item, 'quantity' => $quantity];
|
$this->items[] = ['item' => $item, 'quantity' => $quantity];
|
||||||
$this->value += $item->getValue() * $quantity;
|
$this->value += $item->getValue() * $quantity;
|
||||||
$this->cost += $item->getCost() * $quantity;
|
$this->cost += $item->getCost() * $quantity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knapsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knapsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knapsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knapsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -49,7 +49,7 @@ class Item implements ItemInterface
|
||||||
public string $name = '';
|
public string $name = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cosntructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param float $value Value of the item
|
* @param float $value Value of the item
|
||||||
* @param float $cost Cost of the item
|
* @param float $cost Cost of the item
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Knapsack
|
* @package phpOMS\Algorithm\Knapsack
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Maze
|
* @package phpOMS\Algorithm\Maze
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -81,7 +81,7 @@ class MazeGenerator
|
||||||
if (!empty($neighbors)) {
|
if (!empty($neighbors)) {
|
||||||
--$n;
|
--$n;
|
||||||
|
|
||||||
$next = $neighbors[\mt_rand(0, \count($neighbors) - 1)];
|
$next = $neighbors[\array_rand($neighbors, 1)];
|
||||||
$unvisited[$next[0] + 1][$next[1] + 1] = false;
|
$unvisited[$next[0] + 1][$next[1] + 1] = false;
|
||||||
|
|
||||||
if ($next[0] === $pos[0]) {
|
if ($next[0] === $pos[0]) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -80,9 +80,9 @@ class GeneticOptimization
|
||||||
*
|
*
|
||||||
* @example See unit test for example use case
|
* @example See unit test for example use case
|
||||||
*
|
*
|
||||||
* @param array<array> $population List of all elements with ther parameters (i.e. list of "objects" as arrays).
|
* @param array<array> $population List of all elements with their parameters (i.e. list of "objects" as arrays).
|
||||||
* The constraints are defined as array values.
|
* The constraints are defined as array values.
|
||||||
* @param \Closure $fitness Fitness function calculates score/feasability of solution
|
* @param \Closure $fitness Fitness function calculates score/feasibility of solution
|
||||||
* @param \Closure $mutate Mutation function to change the parameters of an "object"
|
* @param \Closure $mutate Mutation function to change the parameters of an "object"
|
||||||
* @param \Closure $crossover Crossover function to exchange parameter values between "objects".
|
* @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.
|
* Sometimes single parameters can be exchanged but sometimes interdependencies exist between parameters which is why this function is required.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -40,7 +40,7 @@ class SimulatedAnnealing
|
||||||
return $x;
|
return $x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// can be many things, e.g. swapping parameters, increasing/decrising, random generation
|
// can be many things, e.g. swapping parameters, increasing/decreasing, random generation
|
||||||
public static function neighbor(array $generation, $parameterCount)
|
public static function neighbor(array $generation, $parameterCount)
|
||||||
{
|
{
|
||||||
$newGeneration = $generation;
|
$newGeneration = $generation;
|
||||||
|
|
@ -57,17 +57,17 @@ class SimulatedAnnealing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Simulated Annealing algorithm
|
// Simulated Annealing algorithm
|
||||||
// @todo allow to create a solution space (currently all soluctions need to be in space)
|
// @todo allow to create a solution space (currently all solutions need to be in space)
|
||||||
// @todo: currently only replacing generations, not altering them
|
// @todo currently only replacing generations, not altering them
|
||||||
/**
|
/**
|
||||||
* Perform optimization
|
* Perform optimization
|
||||||
*
|
*
|
||||||
* @example See unit test for example use case
|
* @example See unit test for example use case
|
||||||
*
|
*
|
||||||
* @param array $space List of all elements with ther parameters (i.e. list of "objects" as arrays).
|
* @param array $space List of all elements with their parameters (i.e. list of "objects" as arrays).
|
||||||
* The constraints are defined as array values.
|
* The constraints are defined as array values.
|
||||||
* @param int $initialTemperature Starting temperature
|
* @param int $initialTemperature Starting temperature
|
||||||
* @param \Closure $costFunction Fitness function calculates score/feasability of solution
|
* @param \Closure $costFunction Fitness function calculates score/feasibility of solution
|
||||||
* @param \Closure $neighbor Neighbor function to find a new solution/neighbor
|
* @param \Closure $neighbor Neighbor function to find a new solution/neighbor
|
||||||
* @param float $coolingRate Rate at which cooling takes place
|
* @param float $coolingRate Rate at which cooling takes place
|
||||||
* @param int $iterations Number of iterations
|
* @param int $iterations Number of iterations
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Optimization
|
* @package phpOMS\Algorithm\Optimization
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -54,7 +54,7 @@ class Path
|
||||||
private array $expandedNodes = [];
|
private array $expandedNodes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cosntructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param Grid $grid Grid this path belongs to
|
* @param Grid $grid Grid this path belongs to
|
||||||
*
|
*
|
||||||
|
|
@ -152,7 +152,7 @@ class Path
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find nodes in bettween two nodes.
|
* Find nodes in between two nodes.
|
||||||
*
|
*
|
||||||
* The path may only contain the jump points or pivot points.
|
* The path may only contain the jump points or pivot points.
|
||||||
* In order to get every node it needs to be expanded.
|
* In order to get every node it needs to be expanded.
|
||||||
|
|
@ -190,7 +190,7 @@ class Path
|
||||||
|
|
||||||
if ($e2 > -$dy) {
|
if ($e2 > -$dy) {
|
||||||
$err -= $dy;
|
$err -= $dy;
|
||||||
$x0 += $sx;
|
$x0 += $sx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($e2 < $dx) {
|
if ($e2 < $dx) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\PathFinding
|
* @package phpOMS\Algorithm\PathFinding
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Rating
|
* @package phpOMS\Algorithm\Rating
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Rating
|
* @package phpOMS\Algorithm\Rating
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -74,4 +74,37 @@ final class Elo
|
||||||
'elo' => (int) \max($eloNew, $this->MIN_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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Rating
|
* @package phpOMS\Algorithm\Rating
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -102,7 +102,7 @@ final class Glicko1
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcualte the glicko-1 elo
|
* Calculate the glicko-1 elo
|
||||||
*
|
*
|
||||||
* @param int $elo Current player "elo"
|
* @param int $elo Current player "elo"
|
||||||
* @param int $rdOld Current player deviation (RD)
|
* @param int $rdOld Current player deviation (RD)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Rating
|
* @package phpOMS\Algorithm\Rating
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
@ -25,8 +25,6 @@ use phpOMS\Math\Solver\Root\Bisection;
|
||||||
* @see https://en.wikipedia.org/wiki/Glicko_rating_system
|
* @see https://en.wikipedia.org/wiki/Glicko_rating_system
|
||||||
* @see http://www.glicko.net/glicko/glicko2.pdf
|
* @see http://www.glicko.net/glicko/glicko2.pdf
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
*
|
|
||||||
* @todo: implement
|
|
||||||
*/
|
*/
|
||||||
final class Glicko2
|
final class Glicko2
|
||||||
{
|
{
|
||||||
|
|
@ -93,7 +91,7 @@ final class Glicko2
|
||||||
public int $MIN_RD = 50;
|
public int $MIN_RD = 50;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcualte the glicko-2 elo
|
* Calculate the glicko-2 elo
|
||||||
*
|
*
|
||||||
* @example $glicko->elo(1500, 200, 0.06, [1,0,0], [1400,1550,1700], [30,100,300]) // 1464, 151, 0.059
|
* @example $glicko->elo(1500, 200, 0.06, [1,0,0], [1400,1550,1700], [30,100,300]) // 1464, 151, 0.059
|
||||||
*
|
*
|
||||||
|
|
@ -121,7 +119,7 @@ final class Glicko2
|
||||||
|
|
||||||
// Step 0:
|
// Step 0:
|
||||||
$rdOld /= self::Q;
|
$rdOld /= self::Q;
|
||||||
$elo = ($elo - $this->DEFAULT_ELO) / self::Q;
|
$elo = ($elo - $this->DEFAULT_ELO) / self::Q;
|
||||||
|
|
||||||
foreach ($oElo as $idx => $value) {
|
foreach ($oElo as $idx => $value) {
|
||||||
$oElo[$idx] = ($value - $this->DEFAULT_ELO) / self::Q;
|
$oElo[$idx] = ($value - $this->DEFAULT_ELO) / self::Q;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Rating
|
* @package phpOMS\Algorithm\Rating
|
||||||
* @copyright Microsoft
|
* @copyright Microsoft
|
||||||
|
|
@ -22,25 +22,93 @@ use phpOMS\Math\Stochastic\Distribution\NormalDistribution;
|
||||||
* @package phpOMS\Algorithm\Rating
|
* @package phpOMS\Algorithm\Rating
|
||||||
* @license OMS License 2.0
|
* @license OMS License 2.0
|
||||||
* @link https://jingga.app
|
* @link https://jingga.app
|
||||||
* @since 1.0.0
|
|
||||||
* @see https://www.moserware.com/assets/computing-your-skill/The%20Math%20Behind%20TrueSkill.pdf
|
* @see https://www.moserware.com/assets/computing-your-skill/The%20Math%20Behind%20TrueSkill.pdf
|
||||||
|
* @since 1.0.0
|
||||||
*
|
*
|
||||||
* @todo implement https://github.com/sublee/trueskill/blob/master/trueskill/__init__.py
|
* @todo Implement https://github.com/sublee/trueskill/blob/master/trueskill/__init__.py
|
||||||
|
* https://github.com/Karaka-Management/phpOMS/issues/337
|
||||||
*/
|
*/
|
||||||
|
// phpcs:ignoreFile
|
||||||
class TrueSkill
|
class TrueSkill
|
||||||
{
|
{
|
||||||
public int $DEFAULT_MU = 25;
|
public const DEFAULT_MU = 25;
|
||||||
|
|
||||||
public float $DEFAULT_SIGMA = 25 / 3;
|
public const DEFAULT_SIGMA = 25 / 3;
|
||||||
|
|
||||||
public float $DEFAULT_BETA = 25 / 3 / 2;
|
public const DEFAULT_BETA = 25 / 3 / 2;
|
||||||
|
|
||||||
public float $DEFAULT_TAU = 25 / 3 / 100;
|
public const DEFAULT_TAU = 25 / 3 / 100;
|
||||||
|
|
||||||
public float $DEFAULT_DRAW_PROBABILITY = 0.1;
|
public const DEFAULT_DRAW_PROBABILITY = 0.1;
|
||||||
|
|
||||||
public function __construct()
|
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)
|
||||||
{
|
{
|
||||||
|
$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
|
// Draw margin = epsilon
|
||||||
|
|
|
||||||
28
Algorithm/Rating/TrueSkillFactoryGraph.php
Normal file
28
Algorithm/Rating/TrueSkillFactoryGraph.php
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
/**
|
/**
|
||||||
* Jingga
|
* Jingga
|
||||||
*
|
*
|
||||||
* PHP Version 8.1
|
* PHP Version 8.2
|
||||||
*
|
*
|
||||||
* @package phpOMS\Algorithm\Sort;
|
* @package phpOMS\Algorithm\Sort;
|
||||||
* @copyright Dennis Eichhorn
|
* @copyright Dennis Eichhorn
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user