123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- <?php
- namespace MathPHP\Tests\LinearAlgebra\Reduction;
- use MathPHP\LinearAlgebra\MatrixFactory;
- use MathPHP\LinearAlgebra\NumericMatrix;
- use MathPHP\LinearAlgebra\Reduction;
- use MathPHP\Tests;
- class RowEchelonFormTest extends \PHPUnit\Framework\TestCase
- {
- use Tests\LinearAlgebra\Fixture\MatrixDataProvider;
- /**
- * @test isRef on ref matrix should return true
- * @dataProvider dataProviderForNonsingularMatrix
- * @param $A
- * @throws \Exception
- */
- public function testRefIsRef(array $A)
- {
- // Given
- $A = MatrixFactory::create($A);
- // When
- $ref = $A->ref();
- // Then
- $this->assertTrue($ref->isRef());
- }
- /**
- * @test ref lazy load is the same as the computed and returned value.
- * @throws \Exception
- */
- public function testRefAlreadyComputed()
- {
- // Given
- $A = new NumericMatrix([
- [ 4, 1, 2, -3],
- [-3, 3, -1, 4],
- [-1, 2, 5, 1],
- [ 5, 4, 3, -1],
- ]);
- // When
- $ref1 = $A->ref(); // computes ref
- $ref2 = $A->ref(); // simply gets already-computed ref
- // Then
- $this->assertEquals($ref1, $ref2);
- }
- /**
- * @test rowReductionToEchelonForm method of ref
- * @dataProvider dataProviderForRowReductionToEchelonForm
- * @param array $A
- * @param array $R
- * @throws \Exception
- */
- public function testRowReductionToEchelonForm(array $A, array $R)
- {
- // Given
- $A = MatrixFactory::create($A);
- $R = MatrixFactory::create($R);
- // When
- [$ref, $swaps] = Reduction\RowEchelonForm::rowReductionToEchelonForm($A);
- $ref = MatrixFactory::create($ref);
- // Then
- $this->assertEqualsWithDelta($R->getMatrix(), $ref->getMatrix(), 0.000001);
- $this->assertTrue($ref->isRef());
- }
- /**
- * @return array
- */
- public function dataProviderForRowReductionToEchelonForm(): array
- {
- return [
- [
- [
- [1, 2, 0],
- [-1, 1, 1],
- [1, 2, 3],
- ],
- [
- [1, 2, 0],
- [0, 1, 1 / 3],
- [0, 0, 1],
- ],
- ],
- [
- [
- [0, 2, 0],
- [-1, 1, 1],
- [1, 2, 3],
- ],
- [
- [1, -1, -1],
- [0, 1, 0],
- [0, 0, 1],
- ],
- ],
- [
- [
- [0, 2, 0],
- [0, 1, 1],
- [1, 2, 3],
- ],
- [
- [1, 2, 3],
- [0, 1, 1],
- [0, 0, 1],
- ],
- ],
- [
- [
- [1, 2, 0],
- [0, 1, 1],
- [0, 2, 3],
- ],
- [
- [1, 2, 0],
- [0, 1, 1],
- [0, 0, 1],
- ],
- ],
- [
- [
- [2, 5, 4],
- [2, 4, 6],
- [8, 7, 5],
- [6, 4, 5],
- [6, 2, 3],
- ],
- [
- [1, 5 / 2, 2],
- [0, 1, -2],
- [0, 0, 1],
- [0, 0, 0],
- [0, 0, 0],
- ],
- ],
- [
- [
- [1, 0, -2, 1, 0],
- [0, -1, -3, 1, 3],
- [-2, -1, 1, -1, 3],
- [0, 3, 9, 0, -12],
- ],
- [
- [1, 0, -2, 1, 0],
- [0, 1, 3, -1, -3],
- [0, 0, 0, 1, -1],
- [0, 0, 0, 0, 0],
- ],
- ],
- [
- [
- [5, 4, 8],
- [7, 7, 5],
- [6, 2, 4],
- ],
- [
- [1, 4 / 5, 8 / 5],
- [0, 1, -31 / 7],
- [0, 0, 1],
- ],
- ],
- [
- [
- [2, 0, -1, 0, 0],
- [1, 0, 0, -1, 0],
- [3, 0, 0, -2, -1],
- [0, 1, 0, 0, -2],
- [0, 1, -1, 0, 0]
- ],
- [
- [1, 0, -1 / 2, 0, 0],
- [0, 1, 0, 0, -2],
- [0, 0, 1, -4 / 3, -2 / 3],
- [0, 0, 0, 1, -1],
- [0, 0, 0, 0, 0],
- ],
- ],
- [
- [
- [2, -1, 4, 3, 2, 3, 4, 4],
- [-1, 2, 3, 2, 1, 2, 3, 3],
- [4, 3, 2, 1, 2, 3, 4, 4],
- [2, 1, 2, 1, 2, 1, 2, 2],
- [3, 2, 3, 2, 1, 2, 3, 3],
- [3, 2, 3, 2, 1, 2, 1, 2],
- [4, 3, 4, 3, 2, 1, 2, 2],
- [4, 3, 4, 3, 2, 2, 2, 2],
- ],
- [
- [1, -1 / 2, 2, 3 / 2, 1, 3 / 2, 2, 2],
- [0, 1, 10 / 3, 7 / 3, 4 / 3, 7 / 3, 10 / 3, 10 / 3],
- [0, 0, 1, 25 / 34, 13 / 34, 11 / 17, 31 / 34, 31 / 34],
- [0, 0, 0, 1, -11 / 5, 18 / 5, 13 / 5, 13 / 5],
- [0, 0, 0, 0, 1, 2, 2, 2],
- [0, 0, 0, 0, 0, 1, 1, 1],
- [0, 0, 0, 0, 0, 0, 1, 1 / 2],
- [0, 0, 0, 0, 0, 0, 0, 1],
- ],
- ],
- [
- [
- [0]
- ],
- [
- [0],
- ],
- ],
- [
- [
- [1]
- ],
- [
- [1],
- ],
- ],
- [
- [
- [5]
- ],
- [
- [1],
- ],
- ],
- [
- [
- [0, 0],
- [0, 0]
- ],
- [
- [0, 0],
- [0, 0],
- ],
- ],
- [
- [
- [0, 0],
- [0, 1]
- ],
- [
- [0, 1],
- [0, 0],
- ],
- ],
- [
- [
- [1, 0],
- [0, 0]
- ],
- [
- [1, 0],
- [0, 0],
- ],
- ],
- [
- [
- [0, 0],
- [1, 0]
- ],
- [
- [1, 0],
- [0, 0],
- ],
- ],
- [
- [
- [0, 0],
- [1, 1]
- ],
- [
- [1, 1],
- [0, 0],
- ],
- ],
- [
- [
- [0, 1],
- [0, 1]
- ],
- [
- [0, 1],
- [0, 0],
- ],
- ],
- [
- [
- [1, 0],
- [1, 0]
- ],
- [
- [1, 0],
- [0, 0],
- ],
- ],
- [
- [
- [1, 1],
- [1, 1]
- ],
- [
- [1, 1],
- [0, 0],
- ],
- ],
- [
- [
- [2, 6],
- [1, 3]
- ],
- [
- [1, 3],
- [0, 0],
- ],
- ],
- [
- [
- [3, 6],
- [1, 2]
- ],
- [
- [1, 2],
- [0, 0],
- ],
- ],
- [
- [
- [1, 2],
- [1, 2]
- ],
- [
- [1, 2],
- [0, 0],
- ],
- ],
- [
- [
- [1, 2, 3],
- [2, 3, 4],
- [3, 4, 5],
- ],
- [
- [1, 2, 3],
- [0, 1, 2],
- [0, 0, 0],
- ],
- ],
- [
- [
- [1, 2, 1],
- [-2, -3, 1],
- [3, 5, 0],
- ],
- [
- [1, 2, 1],
- [0, 1, 3],
- [0, 0, 0],
- ],
- ],
- [
- [
- [1, -1, 2],
- [2, 1, 1],
- [1, 1, 0],
- ],
- [
- [1, -1, 2],
- [0, 1, -1],
- [0, 0, 0],
- ],
- ],
- [
- [
- [1, 0, 1],
- [0, 1, -1],
- [0, 0, 0],
- ],
- [
- [1, 0, 1],
- [0, 1, -1],
- [0, 0, 0],
- ],
- ],
- [
- [
- [1, 2, 3],
- [1, 3, 1],
- [3, 4, 7],
- ],
- [
- [1, 2, 3],
- [0, 1, -2],
- [0, 0, 1],
- ],
- ],
- [
- [
- [1, 0, 0],
- [-2, 0, 0],
- [4, 6, 1],
- ],
- [
- [1, 0, 0],
- [0, 1, 1 / 6],
- [0, 0, 0],
- ],
- ],
- [
- [
- [1, 1, 4, 1, 2],
- [0, 1, 2, 1, 1],
- [0, 0, 0, 1, 2],
- [1, -1, 0, 0, 2],
- [2, 1, 6, 0, 1],
- ],
- [
- [1, 1, 4, 1, 2],
- [0, 1, 2, 1, 1],
- [0, 0, 0, 1, 2],
- [0, 0, 0, 0, 0],
- [0, 0, 0, 0, 0],
- ],
- ],
- // This is an interesting case because of the minuscule values that are for all intents and purposes zero.
- // If the minuscule zero-like values are not handled properly, the zero value will be used as a pivot,
- // instead of being interchanged with a non-zero row.
- [
- [
- [0, 1, 4, 2, 3, 3, 4, 4],
- [1, 0, 3, 1, 2, 2, 3, 3],
- [4, 3, 0, 2, 3, 3, 4, 4],
- [3, 2, 1, 1, 2, 2, 3, 3],
- [2, 1, 2, 0, 1, 1, 2, 2],
- [3, 2, 3, 1, 2, 0, 1, 2],
- [4, 3, 4, 2, 3, 1, 0, 2],
- [4, 3, 4, 2, 3, 2, 2, 0],
- ],
- [
- [1, 0, 3, 1, 2, 2, 3, 3],
- [0, 1, 4, 2, 3, 3, 4, 4],
- [0, 0, 1, 1 / 3, 7 / 12, 7 / 12, 5 / 6, 5 / 6],
- [0, 0, 0, 1, 1, 1, 1, 1],
- [0, 0, 0, 0, 1, 5, 6, 4],
- [0, 0, 0, 0, 0, 1, 0, 0],
- [0, 0, 0, 0, 0, 0, 1, -1],
- [0, 0, 0, 0, 0, 0, 0, 0],
- ],
- ],
- ];
- }
- }
|