toBe([ [1.0, 4.0], [2.0, 5.0], [3.0, 6.0], ]); }); it('multiplies two compatible matrices', function () { $a = [[1.0, 2.0], [3.0, 4.0]]; $b = [[5.0, 6.0], [7.0, 8.0]]; // Hand-checked: [[19,22],[43,50]] expect(LinearAlgebra::multiply($a, $b))->toBe([ [19.0, 22.0], [43.0, 50.0], ]); }); it('multiplies a matrix by a vector', function () { $a = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]; $v = [1.0, 0.0, -1.0]; expect(LinearAlgebra::multiplyVector($a, $v))->toBe([-2.0, -2.0]); }); it('builds an identity matrix', function () { expect(LinearAlgebra::identity(3))->toBe([ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], ]); }); it('solves a 2x2 linear system', function () { // 2x + y = 5 // x + 3y = 10 → x=1, y=3 $A = [[2.0, 1.0], [1.0, 3.0]]; $b = [5.0, 10.0]; $x = LinearAlgebra::solve($A, $b); expect($x[0])->toBeGreaterThan(0.999)->toBeLessThan(1.001) ->and($x[1])->toBeGreaterThan(2.999)->toBeLessThan(3.001); }); it('solves a 3x3 linear system with partial pivoting', function () { // First pivot is 0 — only succeeds with partial pivoting. // det(A) = -4 (non-singular). Solution: x=2, y=1, z=3 → b = [5, 6, 13] $A = [[0.0, 2.0, 1.0], [1.0, 1.0, 1.0], [2.0, 0.0, 3.0]]; $b = [5.0, 6.0, 13.0]; $x = LinearAlgebra::solve($A, $b); expect($x[0])->toEqualWithDelta(2.0, 1e-9) ->and($x[1])->toEqualWithDelta(1.0, 1e-9) ->and($x[2])->toEqualWithDelta(3.0, 1e-9); }); it('ridgeSolve recovers a known signal under low lambda', function () { // y = 3x + noise. Lambda = 0.001 (effectively OLS). // X is single-feature. Expect coefficient ≈ 3. $X = [[1.0], [2.0], [3.0], [4.0], [5.0]]; $y = [3.0, 6.0, 9.0, 12.0, 15.0]; $beta = LinearAlgebra::ridgeSolve($X, $y, 0.001); expect($beta[0])->toEqualWithDelta(3.0, 1e-3); }); it('ridgeSolve shrinks coefficients toward zero with high lambda', function () { $X = [[1.0], [2.0], [3.0], [4.0], [5.0]]; $y = [3.0, 6.0, 9.0, 12.0, 15.0]; $betaLow = LinearAlgebra::ridgeSolve($X, $y, 0.001); $betaHigh = LinearAlgebra::ridgeSolve($X, $y, 1000.0); expect(abs($betaHigh[0]))->toBeLessThan(abs($betaLow[0])); }); it('rejects multiplication of incompatible matrices', function () { $a = [[1.0, 2.0]]; // 1x2 $b = [[1.0], [2.0], [3.0]]; // 3x1 LinearAlgebra::multiply($a, $b); })->throws(InvalidArgumentException::class); it('throws when solving a singular matrix', function () { $A = [[1.0, 2.0], [2.0, 4.0]]; // row 2 is 2× row 1 $b = [3.0, 6.0]; LinearAlgebra::solve($A, $b); })->throws(RuntimeException::class);