Files
2025-12-12 10:13:38 -08:00

98 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Shared\Trend;
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
use PhpOffice\PhpSpreadsheet\Shared\Trend\Trend;
use PHPUnit\Framework\TestCase;
class BestFitTest extends TestCase
{
private const LBF_PRECISION = 1.0E-4;
public function testBestFit(): void
{
$xValues = [45, 55, 47, 75, 90, 100, 100, 95, 88, 50, 45, 58];
$yValues = [15, 25, 17, 30, 41, 47, 50, 46, 37, 22, 20, 26];
$maxGoodness = -1000.0;
$maxType = '';
$type = Trend::TREND_LINEAR;
$result = Trend::calculate($type, $yValues, $xValues);
$goodness = $result->getGoodnessOfFit();
if ($maxGoodness < $goodness) {
$maxGoodness = $goodness;
$maxType = $type;
}
self::assertEqualsWithDelta(0.9628, $goodness, self::LBF_PRECISION);
$type = Trend::TREND_EXPONENTIAL;
$result = Trend::calculate($type, $yValues, $xValues);
$goodness = $result->getGoodnessOfFit();
if ($maxGoodness < $goodness) {
$maxGoodness = $goodness;
$maxType = $type;
}
self::assertEqualsWithDelta(0.9952, $goodness, self::LBF_PRECISION);
$type = Trend::TREND_LOGARITHMIC;
$result = Trend::calculate($type, $yValues, $xValues);
$goodness = $result->getGoodnessOfFit();
if ($maxGoodness < $goodness) {
$maxGoodness = $goodness;
$maxType = $type;
}
self::assertEqualsWithDelta(-0.0724, $goodness, self::LBF_PRECISION);
self::assertEqualsWithDelta(0.3116, $result->getValueOfXForY(2.1), self::LBF_PRECISION);
$equation = $result->getEquation();
$match = preg_match('/^Y = 0[.]01765\d+ [*] log[(]2.1205\d+ [*] X[)]$/', $equation);
self::assertSame(1, $match, $equation);
$type = Trend::TREND_POWER;
$result = Trend::calculate($type, $yValues, $xValues);
$goodness = $result->getGoodnessOfFit();
if ($maxGoodness < $goodness) {
$maxGoodness = $goodness;
$maxType = $type;
}
self::assertEqualsWithDelta(0.9946, $goodness, self::LBF_PRECISION);
self::assertEqualsWithDelta(28.0886, $result->getValueOfXForY(10.0), self::LBF_PRECISION);
$equation = $result->getEquation();
$match = preg_match('/^Y = 0[.]1705\d+ [*] X\^1[.]2207\d+$/', $equation);
self::assertSame(1, $match, $equation);
self::assertEqualsWithDelta(0.1705, $result->getIntersect(4), self::LBF_PRECISION);
$type = Trend::TREND_BEST_FIT_NO_POLY;
$result = Trend::calculate($type, $yValues, $xValues);
$goodness = $result->getGoodnessOfFit();
self::assertSame($maxGoodness, $goodness);
self::assertSame(lcfirst($maxType), $result->getBestFitType());
try {
$type = Trend::TREND_BEST_FIT;
Trend::calculate($type, $yValues, [0, 1, 2]);
self::fail('should have failed - mismatched number of elements');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('Number of elements', $e->getMessage());
}
try {
$type = Trend::TREND_BEST_FIT;
Trend::calculate($type, $yValues, $xValues);
self::fail('should have failed - TREND_BEST_FIT includes polynomials which are not implemented yet');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('not yet implemented', $e->getMessage());
}
try {
$type = 'unknown';
Trend::calculate($type, $yValues, $xValues);
self::fail('should have failed - invalid trend type');
} catch (SpreadsheetException $e) {
self::assertStringContainsString('Unknown trend type', $e->getMessage());
}
}
}