diff --git a/Math/Statistic/Forecast/Regression/PolynomialRegression.php b/Math/Statistic/Forecast/Regression/PolynomialRegression.php new file mode 100644 index 000000000..06280b159 --- /dev/null +++ b/Math/Statistic/Forecast/Regression/PolynomialRegression.php @@ -0,0 +1,104 @@ + $x Obersved x values + * @param array $y Observed y values + * + * @return array [a => ?, b => ?, c => ?] + * + * @throws InvalidDimensionException throws this exception if the dimension of both arrays is not equal + * + * @since 1.0.0 + */ + public static function getRegression(array $x, array $y) : array + { + if (($n = \count($x)) !== \count($y)) { + throw new InvalidDimensionException(\count($x) . 'x' . \count($y)); + } + + $xm = Average::arithmeticMean($x); + $ym = Average::arithmeticMean($y); + + $r = \range(0, $n - 1); + + $xTemp = []; + foreach ($r as $e) { + $xTemp[] = $e * $e; + } + + $x2m = Average::arithmeticMean($xTemp); + + $xTemp = []; + foreach ($r as $e) { + $xTemp[] = $e * $e * $e; + } + + $x3m = Average::arithmeticMean($xTemp); + + $xTemp = []; + foreach ($r as $e) { + $xTemp[] = $e * $e * $e * $e; + } + + $x4m = Average::arithmeticMean($xTemp); + $xym = 0.0; + + for ($i = 0; $i < $n; ++$i) { + $xym += $x[$i] * $y[$i]; + } + + $xym /= $n; + + $x2ym = 0.0; + for ($i = 0; $i < $n; ++$i) { + $x2ym += $x[$i] * $x[$i] * $y[$i]; + } + + $x2ym /= $n; + + $sxx = $x2m - $xm * $xm; + $sxy = $xym - $xm * $ym; + $sxx2 = $x3m - $xm * $x2m; + $sx2x2 = $x4m - $x2m * $x2m; + $sx2y = $x2ym - $x2m * $ym; + + $b = ($sxy * $sx2x2 - $sx2y * $sxx2) / ($sxx * $sx2x2 - $sxx2 * $sxx2); + $c = ($sx2y * $sxx - $sxy * $sxx2) / ($sxx * $sx2x2 - $sxx2 * $sxx2); + $a = $ym - $b * $xm - $c * $x2m; + + return [ + 'a' => $a, + 'b' => $b, + 'c' => $c, + ]; + } +} diff --git a/tests/Math/Statistic/Forecast/Regression/PolynomialRegressionTest.php b/tests/Math/Statistic/Forecast/Regression/PolynomialRegressionTest.php new file mode 100644 index 000000000..d788a2fa7 --- /dev/null +++ b/tests/Math/Statistic/Forecast/Regression/PolynomialRegressionTest.php @@ -0,0 +1,49 @@ +reg = PolynomialRegression::getRegression($x, $y); + } + + public function testRegression() : void + { + self::assertEqualsWithDelta(['a' => 1, 'b' => 2, 'c' => 3], $this->reg, 0.2); + } + + public function testInvalidDimension() : void + { + self::expectException(\phpOMS\Math\Matrix\Exception\InvalidDimensionException::class); + + $x = [1,2, 3]; + $y = [1,2, 3, 4]; + + PolynomialRegression::getRegression($x, $y); + } +}