diff --git a/Algorithm/JobScheduling/Weighted.php b/Algorithm/JobScheduling/Weighted.php index 673ed5ffa..58a9254c2 100644 --- a/Algorithm/JobScheduling/Weighted.php +++ b/Algorithm/JobScheduling/Weighted.php @@ -42,10 +42,6 @@ final class Weighted * * @return int * - * @todo Orange-Management/phpOMS#243 - * [JobScheduling] Implement sortByEnd test coverage - * All 3 if cases are not covered. Implement the tests! - * * @since 1.0.0 */ private static function sortByEnd(JobInterface $j1, JobInterface $j2) : int @@ -59,7 +55,7 @@ final class Weighted } if ($j1->getEnd() !== null && $j2->getEnd() === null) { - return -1; + return -1; // @todo: Implement test case } return $j1->getEnd()->getTimestamp() <=> $j2->getEnd()->getTimestamp(); diff --git a/Application/ApplicationManager.php b/Application/ApplicationManager.php index 6bc2b6328..9c86e6938 100644 --- a/Application/ApplicationManager.php +++ b/Application/ApplicationManager.php @@ -92,9 +92,6 @@ final class ApplicationManager * * @return bool * - * @todo Orange-Management/phpOMS#245 - * [ApplicationManager] Implement test for invalid source and invalid destination - * * @since 1.0.0 */ public function install(string $source, string $destination, string $theme = 'Default') : bool diff --git a/Math/Statistic/Average.php b/Math/Statistic/Average.php index 4c1f7170e..358c9c972 100644 --- a/Math/Statistic/Average.php +++ b/Math/Statistic/Average.php @@ -173,6 +173,7 @@ final class Average * Example: ([1, 2, 2, 3, 4, 4, 2]) * * @param array $values Values + * @param int $offset Offset for outlier * * @return float * @@ -180,14 +181,19 @@ final class Average * * @since 1.0.0 */ - public static function arithmeticMean(array $values) : float + public static function arithmeticMean(array $values, int $offset = 0) : float { $count = \count($values); - - if ($count === 0) { + if ($count <= $offset * 2) { throw new ZeroDivisionException(); } + if ($offset > 0) { + \sort($values); + $values = \array_slice($values, $offset, -$offset); + $count -= $offset * 2; + } + return \array_sum($values) / $count; } @@ -197,13 +203,19 @@ final class Average * Example: ([1, 2, 2, 3, 4, 4, 2]) * * @param array $values Values + * @param int $offset Offset for outlier * * @return float * * @since 1.0.0 */ - public static function mode(array $values) : float + public static function mode(array $values, int $offset = 0) : float { + if ($offset > 0) { + \sort($values); + $values = \array_slice($values, $offset, -$offset); + } + $count = \array_count_values($values); $best = \max($count); @@ -216,14 +228,20 @@ final class Average * Example: ([1, 2, 2, 3, 4, 4, 2]) * * @param array $values Values + * @param int $offset Offset for outlier * * @return float * * @since 1.0.0 */ - public static function median(array $values) : float + public static function median(array $values, int $offset = 0) : float { \sort($values); + + if ($offset > 0) { + $values = \array_slice($values, $offset, -$offset); + } + $count = \count($values); $middleval = (int) \floor(($count - 1) / 2); @@ -255,11 +273,16 @@ final class Average public static function geometricMean(array $values, int $offset = 0) : float { $count = \count($values); - - if ($count === 0) { + if ($count <= $offset * 2) { throw new ZeroDivisionException(); } + if ($offset > 0) { + \sort($values); + $values = \array_slice($values, $offset, -$offset); + $count -= $offset * 2; + } + return \pow(\array_product($values), 1 / $count); } @@ -279,23 +302,18 @@ final class Average */ public static function harmonicMean(array $values, int $offset = 0) : float { - \sort($values); - - if ($offset > 0) { - /** - * @todo Orange-Management/phpOMS#175 - * Create unit test. - */ - $values = \array_slice($values, $offset, -$offset); - } - $count = \count($values); - $sum = 0.0; - - if ($count === 0) { + if ($count <= $offset * 2) { throw new ZeroDivisionException(); } + if ($offset > 0) { + \sort($values); + $values = \array_slice($values, $offset, -$offset); + $count -= $offset * 2; + } + + $sum = 0.0; foreach ($values as $value) { if ($value === 0) { throw new ZeroDivisionException(); @@ -319,19 +337,29 @@ final class Average * * @since 1.0.0 */ - public static function angleMean($angles, int $offset = 0) : float + public static function angleMean(array $angles, int $offset = 0) : float { - $y = 0; - $x = 0; - $size = \count($angles); + $count = \count($angles); + if ($count <= $offset * 2) { + throw new ZeroDivisionException(); + } - for ($i = 0; $i < $size; ++$i) { + if ($offset > 0) { + \sort($angles); + $angles = \array_slice($angles, $offset, -$offset); + $count -= $offset * 2; + } + + $y = 0; + $x = 0; + + for ($i = 0; $i < $count; ++$i) { $x += \cos(\deg2rad($angles[$i])); $y += \sin(\deg2rad($angles[$i])); } - $x /= $size; - $y /= $size; + $x /= $count; + $y /= $count; return \rad2deg(\atan2($y, $x)); } @@ -350,14 +378,15 @@ final class Average */ public static function angleMean2(array $angles, int $offset = 0) : float { - \sort($angles); + $count = \count($angles); + if ($count <= $offset * 2) { + throw new ZeroDivisionException(); + } if ($offset > 0) { - /** - * @todo Orange-Management/phpOMS#176 - * Create unit test. - */ + \sort($angles); $angles = \array_slice($angles, $offset, -$offset); + $count -= $offset * 2; } $sins = 0.0; @@ -368,8 +397,8 @@ final class Average $coss += \cos(\deg2rad($a)); } - $avgsin = $sins / (0.0 + \count($angles)); - $avgcos = $coss / (0.0 + \count($angles)); + $avgsin = $sins / (0.0 + $count); + $avgcos = $coss / (0.0 + $count); $avgang = \rad2deg(\atan2($avgsin, $avgcos)); while ($avgang < 0.0) { diff --git a/tests/Math/Matrix/EigenvalueDecompositionTest.php b/tests/Math/Matrix/EigenvalueDecompositionTest.php index b7c92567c..5a27a63ed 100644 --- a/tests/Math/Matrix/EigenvalueDecompositionTest.php +++ b/tests/Math/Matrix/EigenvalueDecompositionTest.php @@ -294,4 +294,76 @@ class EigenvalueDecompositionTest extends \PHPUnit\Framework\TestCase self::assertEqualsWithDelta([-2.5510, 3.27552, 3.27552], $eig->getRealEigenvalues()->toArray(), 0.1); self::assertEqualsWithDelta([0.0, 4.7940, -4.7940], $eig->getImagEigenvalues()->toArray(), 0.1); } + + public function testComplexDivision3() : void + { + $A = new Matrix(); + $A->setMatrix([ + [9, 4, 5, 1], + [-1, 15, -2, 13], + [-14, 7, 15, -13], + [13, -16, -2, 19] + ]); + + $eig = new EigenvalueDecomposition($A); + + self::assertEqualsWithDelta([ + [17.7766, 14.8641, 0.0, 0.0], + [-14.8641, 17.7766, 0.0, 0.0], + [0.0, 0.0, 11.22336, 5.6595], + [0.0, 0.0, -5.6595, 11.22336] + ], $eig->getD()->toArray(), 0.1); + + self::assertEqualsWithDelta([17.7766, 17.7766, 11.2233, 11.2233], $eig->getRealEigenvalues()->toArray(), 0.1); + self::assertEqualsWithDelta([14.8641, -14.8641, 5.6595, -5.6595], $eig->getImagEigenvalues()->toArray(), 0.1); + } + + public function testComplexDivision4() : void + { + $A = new Matrix(); + $A->setMatrix([ + [5, 14, 5, -6], + [13, 12, -4, -3], + [13, 10, 8, 17], + [5, -6, 3, 16] + ]); + + $eig = new EigenvalueDecomposition($A); + + self::assertEqualsWithDelta([ + [22.6519, 3.96406, 0.0, 0.0], + [-3.96406, 22.6519, 0.0, 0.0], + [0.0, 0.0, -2.1519, 3.39498], + [0.0, 0.0, -3.39498, -2.1519] + ], $eig->getD()->toArray(), 0.1); + + self::assertEqualsWithDelta([22.6519, 22.6519, -2.1519, -2.1519], $eig->getRealEigenvalues()->toArray(), 0.1); + self::assertEqualsWithDelta([3.96406, -3.96406, 3.39498, -3.39498], $eig->getImagEigenvalues()->toArray(), 0.1); + } } +/* + Test case finder + $c = 0; + try { + do { + $array = []; + for ($i = 0; $i < 4; ++$i) { + $array[] = []; + for ($j = 0; $j < 4; ++$j) { + $div = \mt_rand(-20, 20); + + $array[$i][] = \mt_rand(-20, 20); + } + } + + $A = new Matrix(); + $A->setMatrix($array); + + $eig = new EigenvalueDecomposition($A); + ++$c; + } while (true); + } catch (\Throwable $t) { + var_dump($c); + var_dump($array); + } +*/ diff --git a/tests/Math/Statistic/AverageTest.php b/tests/Math/Statistic/AverageTest.php index e58b5ffa6..b980da1ca 100644 --- a/tests/Math/Statistic/AverageTest.php +++ b/tests/Math/Statistic/AverageTest.php @@ -39,9 +39,11 @@ class AverageTest extends \PHPUnit\Framework\TestCase public function testAngleMean() : void { self::assertEqualsWithDelta(-90, Average::angleMean([90.0, 180.0, 270.0, 360.0]), 0.01); + self::assertEqualsWithDelta(-90, Average::angleMean([90.0, 45.0, 180.0, 270.0, 360.0, 360.0], 1), 0.01); self::assertEqualsWithDelta(9.999999999999977, Average::angleMean([370.0]), 0.01); self::assertEqualsWithDelta(270, Average::angleMean2([90.0, 180.0, 270.0, 360.0]), 0.01); + self::assertEqualsWithDelta(270, Average::angleMean2([90.0, 45.0, 180.0, 270.0, 360.0, 360.0], 1), 0.01); self::assertEqualsWithDelta(9.999999999999977, Average::angleMean2([370.0]), 0.01); } @@ -52,6 +54,7 @@ class AverageTest extends \PHPUnit\Framework\TestCase public function testArithmeticMean() : void { self::assertEqualsWithDelta(4, Average::arithmeticMean([1, 2, 3, 4, 5, 6, 7]), 0.01); + self::assertEqualsWithDelta(4, Average::arithmeticMean([1, 2, -4, -6, 8, 9, 3, 4, 5, 6, 7], 2), 0.01); } /** @@ -73,6 +76,7 @@ class AverageTest extends \PHPUnit\Framework\TestCase public function testGeometricMean() : void { self::assertEqualsWithDelta(3.3800151591413, Average::geometricMean([1, 2, 3, 4, 5, 6, 7]), 0.01); + self::assertEqualsWithDelta(3.3800151591413, Average::geometricMean([1, 2, -4, -6, 8, 9, 3, 4, 5, 6, 7],2), 0.01); } /** @@ -82,6 +86,7 @@ class AverageTest extends \PHPUnit\Framework\TestCase public function testHarmonicMean() : void { self::assertEqualsWithDelta(2.6997245179063, Average::harmonicMean([1, 2, 3, 4, 5, 6, 7]), 0.01); + self::assertEqualsWithDelta(2.6997245179063, Average::harmonicMean([1, 2, -4, -6, 8, 9, 3, 4, 5, 6, 7], 2), 0.01); } /** @@ -170,6 +175,20 @@ class AverageTest extends \PHPUnit\Framework\TestCase Average::geometricMean([]); } + public function testInvalidAngleMean() : void + { + $this->expectException(\phpOMS\Math\Exception\ZeroDivisionException::class); + + Average::angleMean([]); + } + + public function testInvalidAngleMean2() : void + { + $this->expectException(\phpOMS\Math\Exception\ZeroDivisionException::class); + + Average::angleMean2([]); + } + /** * @testdox A dataset with a 0 element throws a ZeroDivisionException * @group framework @@ -188,6 +207,7 @@ class AverageTest extends \PHPUnit\Framework\TestCase public function testMode() : void { self::assertEqualsWithDelta(2, Average::mode([1, 2, 2, 3, 4, 4, 2]), 0.01); + self::assertEqualsWithDelta(2, Average::mode([1, 2, 2, -1, -5, 3, 4, 4, 5, 9, 2], 2), 0.01); } /** @@ -197,6 +217,7 @@ class AverageTest extends \PHPUnit\Framework\TestCase public function testMedian() : void { self::assertEqualsWithDelta(4, Average::median([1, 2, 3, 4, 5, 6, 7]), 0.01); + self::assertEqualsWithDelta(4, Average::median([1, 2, -4, -6, 8, 9, 3, 4, 5, 6, 7], 2), 0.01); self::assertEqualsWithDelta(3.5, Average::median([1, 2, 3, 4, 5, 6]), 0.01); } }