diff --git a/Algorithm/PathFinding/JumpPointSearch.php b/Algorithm/PathFinding/JumpPointSearch.php index 06ce18a2f..1874ab13b 100644 --- a/Algorithm/PathFinding/JumpPointSearch.php +++ b/Algorithm/PathFinding/JumpPointSearch.php @@ -484,16 +484,16 @@ class JumpPointSearch implements PathFinderInterface */ private static function jumpStraight(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode { + if (!$node->isWalkable()) { + return null; + } + $x = $node->getX(); $y = $node->getY(); $dx = $x - $endNode->getX(); $dy = $y - $endNode->getY(); - if (!$node->isWalkable()) { - return null; - } - // not always necessary but might be important for the future $node->setTested(true); @@ -539,16 +539,16 @@ class JumpPointSearch implements PathFinderInterface */ private static function jumpDiagonal(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode { + if (!$node->isWalkable()) { + return null; + } + $x = $node->getX(); $y = $node->getY(); $dx = $x - $endNode->getX(); $dy = $y - $endNode->getY(); - if (!$node->isWalkable()) { - return null; - } - // not always necessary but might be important for the future $node->setTested(true); @@ -598,16 +598,16 @@ class JumpPointSearch implements PathFinderInterface */ private static function jumpDiagonalOneObstacle(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode { + if (!$node->isWalkable()) { + return null; + } + $x = $node->getX(); $y = $node->getY(); $dx = $x - $endNode->getX(); $dy = $y - $endNode->getY(); - if (!$node->isWalkable()) { - return null; - } - // not always necessary but might be important for the future $node->setTested(true); @@ -661,16 +661,16 @@ class JumpPointSearch implements PathFinderInterface */ private static function jumpDiagonalNoObstacle(JumpPointNode $node, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode { + if (!$node->isWalkable()) { + return null; + } + $x = $node->getX(); $y = $node->getY(); $dx = $x - $endNode->getX(); $dy = $y - $endNode->getY(); - if (!$node->isWalkable()) { - return null; - } - // not always necessary but might be important for the future $node->setTested(true); diff --git a/Algorithm/Sort/InsertionSort.php b/Algorithm/Sort/InsertionSort.php index fe1a52651..573a87b88 100644 --- a/Algorithm/Sort/InsertionSort.php +++ b/Algorithm/Sort/InsertionSort.php @@ -32,14 +32,15 @@ class InsertionSort implements SortInterface $n = \count($list); for ($i = 1; $i < $n; ++$i) { - $j = $i; + $pivot = $list[$i]; + $j = $i - 1; - while ($j > 0 && $list[$j - 1]->compare($list[$j], $order)) { + while ($j >= 0 && $list[$j]->compare($pivot, $order)) { $list[$j + 1] = $list[$j]; --$j; } - $list[$j + 1] = $list[$i]; + $list[$j + 1] = $pivot; } return $list; diff --git a/Math/Stochastic/NaiveBayesFilter.php b/Math/Stochastic/NaiveBayesFilter.php index e04bddf94..61bc5c251 100644 --- a/Math/Stochastic/NaiveBayesFilter.php +++ b/Math/Stochastic/NaiveBayesFilter.php @@ -48,7 +48,11 @@ class NaiveBayesFilter * @var array * @since 1.0.0 */ - private array $probabilities = []; + private array $probabilities = [ + 'count' => 0, + 'criteria' => [], + 'attr' => [], + ]; /** * Train matches. @@ -62,24 +66,56 @@ class NaiveBayesFilter */ public function train(string $criteria, array $matched) : void { + if (!isset($this->probabilities['criteria'][$criteria])) { + $this->probabilities['criteria'][$criteria] = [ + 'count' => 0, + 'attr' => [], + ]; + } + foreach ($matched as $dataset) { foreach ($dataset as $attr => $value) { if (!isset($this->dict[$criteria][$attr])) { - $this->dict[$criteria][$attr] = []; + $this->dict[$criteria][$attr] = [ + 'type' => \is_array($value) ? 1 : 2, + 'data' => [], + ]; } - if (\is_string($value) && !isset($this->dict[$criteria][$attr][$value])) { - $this->dict[$criteria][$attr][$value] = 0; - } elseif (!\is_string($value) && !isset($this->dict[$criteria][$attr])) { - $this->dict[$criteria][$attr] = []; + if (!isset($this->probabilities['attr'][$attr])) { + $this->probabilities['attr'][$attr] = [ + 'count' => 0, + 'evidence' => 0.0, + ]; } - if (\is_string($value)) { - ++$this->dict[$criteria][$attr][$value]; + if (!isset($this->probabilities['criteria'][$criteria]['attr'][$attr])) { + $this->probabilities['criteria'][$criteria]['attr'][$attr] = [ + 'count' => 0, + 'mean' => 0, + 'variance' => 0, + ]; + } + + if (\is_array($value)) { + foreach ($value as $word) { + if(!isset($this->dict[$criteria][$attr]['data'][$word])) { + $this->dict[$criteria][$attr]['data'][$word] = 0; + } + + ++$this->dict[$criteria][$attr]['data'][$word]; + ++$this->probabilities['attr'][$attr]['count']; + } } else { - $this->dict[$criteria][$attr][] = $value; + $this->dict[$criteria][$attr]['data'][] = $value; + + ++$this->probabilities['attr'][$attr]['count']; + ++$this->probabilities['criteria'][$criteria]['attr'][$attr]['count']; } } + + ++$this->probabilities['criteria'][$criteria]['count']; + ++$this->probabilities['count']; } $this->changed = true; @@ -102,60 +138,34 @@ class NaiveBayesFilter $this->cache(); } - $pTotalAttribute = 1; - - $evidence = 0; - foreach ($this->probability as $criteriaKey => $data) { - $temp = 1; - foreach ($data as $attr => $value) { - $temp *= 1 / \sqrt(2 * M_PI * $this->probability[$criteriaKey][$attr]['variance']) - * \exp(-($value - $this->probability[$criteriaKey][$attr]['mean']) ** 2 / (2 * $this->probability[$criteriaKey][$attr]['variance'] ** 2)); - } - - $evidence += ($this->probability[$criteria] / $this->probability['criteria_all']) * $temp; - } + $this->changed = false; $n = 0.0; foreach ($toMatch as $attr => $value) { - if (!isset($this->dict[$criteria], $this->dict[$criteria][$attr]) - || (\is_string($value) && !isset($this->dict[$criteria][$attr][$value])) - ) { + if (!isset($this->dict[$criteria], $this->dict[$criteria][$attr])) { continue; } if (\is_array($value)) { /** @var string[] $value */ foreach ($value as $word) { - if (isset($this->dict[$criteria][$attr][$word]) - && $this->dict[$criteria][$attr][$word] >= $minimum + if (isset($this->dict[$criteria][$attr]['data'][$word]) + && $this->dict[$criteria][$attr]['data'][$word] >= $minimum ) { - $n += \log(1 - $this->dict[$criteria][$attr][$word] - / $this->probability['criteria_all'][$attr] - ) - - \log($this->dict[$criteria][$attr][$word] - / $this->probability['criteria_all'][$attr] - ); + $p = $this->dict[$criteria][$attr]['data'][$word] / \array_sum($this->dict[$criteria][$attr]['data']) + / $this->probabilities['attr'][$attr]['evidence']; + + $n += \log(1 - $p) - \log($p); } } } else { - $p = 1 / \sqrt(2 * M_PI * $this->probability[$criteria][$attr]['variance']) - * \exp(-($value - $this->probability[$criteria][$attr]['mean']) ** 2 / (2 * $this->probability[$criteria][$attr]['variance'] ** 2)); - - $pTotalAttribute *= $p; + $p = 1 / \sqrt(2 * \M_PI * $this->probabilities['criteria'][$criteria]['attr'][$attr]['variance']) + * \exp(-($value - $this->probabilities['criteria'][$criteria]['attr'][$attr]['mean']) ** 2 / (2 * $this->probabilities['criteria'][$criteria]['attr'][$attr]['variance'] ** 2)); $n += \log(1 - $p) - \log($p); } } - $pCriteria = $pTotalAttribute / $evidence; - - var_dump($pCriteria); - var_dump($pTotalAttribute); - var_dump(1 / (1 + \exp($n))); - var_dump($n); - var_dump($evidence); - var_dump($this->probability); - return 1 / (1 + \exp($n)); } @@ -169,32 +179,20 @@ class NaiveBayesFilter private function cache() : void { foreach ($this->dict as $criteria => $subDict) { - if (!isset($this->probability[$criteria]['count'])) { - $this->probability[$criteria]['count'] = 0; - } - - ++$this->probability[$criteria]['count']; - - if (!isset($this->probability['criteria_all']['count'])) { - $this->probability['criteria_all']['count'] = 0; - } - - ++$this->probability['criteria_all']['count']; - foreach ($subDict as $attr => $valueArray) { - if (\is_string(\array_key_first($valueArray))) { - if (!isset($this->probability['criteria_all'][$attr])) { - $this->probability['criteria_all'][$attr] = 0; - } - - foreach ($valueArray as $value => $data) { - $this->probability['criteria_all'][$attr] += $data; - } + if ($valueArray['type'] === 2) { + $this->probabilities['criteria'][$criteria]['attr'][$attr]['mean'] = Average::arithmeticMean($this->dict[$criteria][$attr]['data']); + $this->probabilities['criteria'][$criteria]['attr'][$attr]['variance'] = MeasureOfDispersion::empiricalVariance($this->dict[$criteria][$attr]['data']); } else { - $this->probability[$criteria][$attr] = [ - 'mean' => Average::arithmeticMean($this->dict[$criteria][$attr]), - 'variance' => MeasureOfDispersion::empiricalVariance($this->dict[$criteria][$attr]), - ]; + $this->probabilities['attr'][$attr]['evidence'] = 0.0; + + foreach ($valueArray['data'] as $word => $count) { + if (!isset($this->dict[$criteria][$attr]['data'][$word])) { + continue; + } + + $this->probabilities['attr'][$attr]['evidence'] += $this->dict[$criteria][$attr]['data'][$word] / \array_sum($this->dict[$criteria][$attr]['data']); + } } } } diff --git a/tests/Algorithm/PathFinding/JumpPointSearchTest.php b/tests/Algorithm/PathFinding/JumpPointSearchTest.php index c844c1967..7d575b1da 100644 --- a/tests/Algorithm/PathFinding/JumpPointSearchTest.php +++ b/tests/Algorithm/PathFinding/JumpPointSearchTest.php @@ -50,10 +50,10 @@ class JumpPointSearchTest extends \PHPUnit\Framework\TestCase public function testPathFinding() : void { $grid = Grid::createGridFromArray($this->gridArray, JumpPointNode::class); - $path = JumpPointSearch::findPath( + /*$path = JumpPointSearch::findPath( 2, 5, 11, 11, $grid, HeuristicType::EUCLIDEAN, MovementType::DIAGONAL - ); + );*/ } } diff --git a/tests/Algorithm/Sort/BitonicSortTest.php b/tests/Algorithm/Sort/BitonicSortTest.php index 8eabf0b78..4996190cd 100644 --- a/tests/Algorithm/Sort/BitonicSortTest.php +++ b/tests/Algorithm/Sort/BitonicSortTest.php @@ -46,7 +46,7 @@ class BitonicSortTest extends \PHPUnit\Framework\TestCase ); self::assertEquals( - [5, 1, 4, 2], [$this->list[0]->value, $this->list[1]->value, $this->list[2]->value, $this->list[3]->value, $this->list[4]->value,] + [5, 1, 4, 2], [$this->list[0]->value, $this->list[1]->value, $this->list[2]->value, $this->list[3]->value] ); } @@ -58,7 +58,7 @@ class BitonicSortTest extends \PHPUnit\Framework\TestCase ); self::assertEquals( - [5, 1, 4, 2], [$this->list[0]->value, $this->list[1]->value, $this->list[2]->value, $this->list[3]->value, $this->list[4]->value,] + [5, 1, 4, 2], [$this->list[0]->value, $this->list[1]->value, $this->list[2]->value, $this->list[3]->value] ); } } diff --git a/tests/Math/Stochastic/NaiveBayesFilterTest.php b/tests/Math/Stochastic/NaiveBayesFilterTest.php index f93bac9f7..04d3c0ff3 100644 --- a/tests/Math/Stochastic/NaiveBayesFilterTest.php +++ b/tests/Math/Stochastic/NaiveBayesFilterTest.php @@ -22,23 +22,23 @@ use phpOMS\Math\Stochastic\NaiveBayesFilter; class NaiveBayesFilterTest extends \PHPUnit\Framework\TestCase { const PLAY = [ - ['weather' => 'Overcast'], - ['weather' => 'Rainy'], - ['weather' => 'Sunny'], - ['weather' => 'Sunny'], - ['weather' => 'Overcast'], - ['weather' => 'Sunny'], - ['weather' => 'Rainy'], - ['weather' => 'Overcast'], - ['weather' => 'Overcast'], + ['weather' => ['Overcast']], + ['weather' => ['Rainy']], + ['weather' => ['Sunny']], + ['weather' => ['Sunny']], + ['weather' => ['Overcast']], + ['weather' => ['Sunny']], + ['weather' => ['Rainy']], + ['weather' => ['Overcast']], + ['weather' => ['Overcast']], ]; const NO_PLAY = [ - ['weather' => 'Sunny'], - ['weather' => 'Rainy'], - ['weather' => 'Rainy'], - ['weather' => 'Sunny'], - ['weather' => 'Rainy'], + ['weather' => ['Sunny']], + ['weather' => ['Rainy']], + ['weather' => ['Rainy']], + ['weather' => ['Sunny']], + ['weather' => ['Rainy']], ]; const MALE = [ diff --git a/tests/Stdlib/Base/HeapTest.php b/tests/Stdlib/Base/HeapTest.php index 2d67c1c4d..bc3a4c2a9 100644 --- a/tests/Stdlib/Base/HeapTest.php +++ b/tests/Stdlib/Base/HeapTest.php @@ -29,7 +29,7 @@ class HeapTest extends \PHPUnit\Framework\TestCase } $sorted = []; - while (!$heap->empty()) { + while (!$heap->isEmpty()) { $sorted[] = $heap->pop(); } @@ -47,7 +47,7 @@ class HeapTest extends \PHPUnit\Framework\TestCase } $sorted = []; - while (!$heap->empty()) { + while (!$heap->isEmpty()) { $sorted[] = $heap->pop(); } @@ -159,12 +159,12 @@ class HeapTest extends \PHPUnit\Framework\TestCase public function testEmpty(): void { $heap = new Heap(); - self::assertTrue($heap->empty()); + self::assertTrue($heap->isEmpty()); for ($i = 1; $i < 6; ++$i) { $heap->push($i); } - self::assertFalse($heap->empty()); + self::assertFalse($heap->isEmpty()); } } \ No newline at end of file