MatrixRowOperationsTest.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. <?php
  2. namespace MathPHP\Tests\LinearAlgebra\Matrix\Numeric;
  3. use MathPHP\LinearAlgebra\MatrixFactory;
  4. use MathPHP\Exception;
  5. use MathPHP\LinearAlgebra\Vector;
  6. class MatrixRowOperationsTest extends \PHPUnit\Framework\TestCase
  7. {
  8. /**
  9. * @test rowMultiply
  10. * @dataProvider dataProviderForRowMultiply
  11. * @param array $A
  12. * @param int $mᵢ
  13. * @param float $k
  14. * @param array $expectedMatrix
  15. * @throws \Exception
  16. */
  17. public function testRowMultiply(array $A, int $mᵢ, float $k, array $expectedMatrix)
  18. {
  19. // Given
  20. $A = MatrixFactory::create($A);
  21. $expectedMatrix = MatrixFactory::create($expectedMatrix);
  22. // When
  23. $R = $A->rowMultiply($mᵢ, $k);
  24. // Then
  25. $this->assertEqualsWithDelta($expectedMatrix, $R, 0.00001);
  26. }
  27. /**
  28. * @return array
  29. */
  30. public function dataProviderForRowMultiply(): array
  31. {
  32. return [
  33. [
  34. [
  35. [1, 2, 3],
  36. [2, 3, 4],
  37. [3, 4, 5],
  38. ], 0, 5,
  39. [
  40. [5, 10, 15],
  41. [2, 3, 4],
  42. [3, 4, 5],
  43. ]
  44. ],
  45. [
  46. [
  47. [1, 2, 3],
  48. [2, 3, 4],
  49. [3, 4, 5],
  50. ], 1, 4,
  51. [
  52. [1, 2, 3],
  53. [8, 12, 16],
  54. [3, 4, 5],
  55. ]
  56. ],
  57. [
  58. [
  59. [1, 2, 3],
  60. [2, 3, 4],
  61. [3, 4, 5],
  62. ], 2, 8,
  63. [
  64. [1, 2, 3],
  65. [2, 3, 4],
  66. [24, 32, 40],
  67. ]
  68. ],
  69. [
  70. [
  71. [1, 2, 3],
  72. [2, 3, 4],
  73. [3, 4, 5],
  74. ], 0, 2.3,
  75. [
  76. [2.3, 4.6, 6.9],
  77. [2, 3, 4],
  78. [3, 4, 5],
  79. ]
  80. ],
  81. [
  82. [
  83. [1, 2, 3],
  84. [2, 3, 4],
  85. [3, 4, 5],
  86. ], 0, 0,
  87. [
  88. [0, 0, 0],
  89. [2, 3, 4],
  90. [3, 4, 5],
  91. ]
  92. ],
  93. ];
  94. }
  95. /**
  96. * @test rowMultiply on a row greater than m
  97. * @throws \Exception
  98. */
  99. public function testRowMultiplyExceptionRowGreaterThanM()
  100. {
  101. // Given
  102. $A = MatrixFactory::create([
  103. [1, 2, 3],
  104. [2, 3, 4],
  105. [3, 4, 5],
  106. ]);
  107. // Then
  108. $this->expectException(Exception\MatrixException::class);
  109. // When
  110. $A->rowMultiply(4, 5);
  111. }
  112. /**
  113. * @test rowDivide
  114. * @dataProvider dataProviderForRowDivide
  115. * @param array $A
  116. * @param int $mᵢ
  117. * @param float $k
  118. * @param array $expectedMatrix
  119. * @throws \Exception
  120. */
  121. public function testRowDivide(array $A, int $mᵢ, float $k, array $expectedMatrix)
  122. {
  123. // Given
  124. $A = MatrixFactory::create($A);
  125. $expectedMatrix = MatrixFactory::create($expectedMatrix);
  126. // When
  127. $R = $A->rowDivide($mᵢ, $k);
  128. // Then
  129. $this->assertEqualsWithDelta($expectedMatrix, $R, 0.00001);
  130. }
  131. /**
  132. * @return array
  133. */
  134. public function dataProviderForRowDivide(): array
  135. {
  136. return [
  137. [
  138. [
  139. [2, 4, 8],
  140. [2, 3, 4],
  141. [3, 4, 5],
  142. ], 0, 2,
  143. [
  144. [1, 2, 4],
  145. [2, 3, 4],
  146. [3, 4, 5],
  147. ]
  148. ],
  149. [
  150. [
  151. [2, 4, 8],
  152. [2, 3, 4],
  153. [3, 4, 5],
  154. ], 0, 2.1,
  155. [
  156. [0.952380952380952, 1.904761904761905, 3.80952380952381],
  157. [2, 3, 4],
  158. [3, 4, 5],
  159. ]
  160. ],
  161. ];
  162. }
  163. /**
  164. * @test rowDivide row greater than M
  165. * @throws \Exception
  166. */
  167. public function testRowDivideExceptionRowGreaterThanM()
  168. {
  169. // Given
  170. $A = MatrixFactory::create([
  171. [1, 2, 3],
  172. [2, 3, 4],
  173. [3, 4, 5],
  174. ]);
  175. // Then
  176. $this->expectException(Exception\MatrixException::class);
  177. // When
  178. $A->rowDivide(4, 5);
  179. }
  180. /**
  181. * @test rowDivide K is zero
  182. * @throws \Exception
  183. */
  184. public function testRowDivideExceptionKIsZero()
  185. {
  186. // Given
  187. $A = MatrixFactory::create([
  188. [1, 2, 3],
  189. [2, 3, 4],
  190. [3, 4, 5],
  191. ]);
  192. // Then
  193. $this->expectException(Exception\BadParameterException::class);
  194. // When
  195. $A->rowDivide(2, 0);
  196. }
  197. /**
  198. * @test rowAdd
  199. * @dataProvider dataProviderForRowAdd
  200. * @param array $A
  201. * @param int $mᵢ
  202. * @param int $mⱼ
  203. * @param float $k
  204. * @param array $expectedMatrix
  205. * @throws \Exception
  206. */
  207. public function testRowAdd(array $A, int $mᵢ, int $mⱼ, float $k, array $expectedMatrix)
  208. {
  209. // Given
  210. $A = MatrixFactory::create($A);
  211. $expectedMatrix = MatrixFactory::create($expectedMatrix);
  212. // When
  213. $R = $A->rowAdd($mᵢ, $mⱼ, $k);
  214. // Then
  215. $this->assertEquals($expectedMatrix, $R);
  216. }
  217. /**
  218. * @return array
  219. */
  220. public function dataProviderForRowAdd(): array
  221. {
  222. return [
  223. [
  224. [
  225. [1, 2, 3],
  226. [2, 3, 4],
  227. [3, 4, 5],
  228. ], 0, 1, 2,
  229. [
  230. [1, 2, 3],
  231. [4, 7, 10],
  232. [3, 4, 5],
  233. ]
  234. ],
  235. [
  236. [
  237. [1, 2, 3],
  238. [2, 3, 4],
  239. [3, 4, 5],
  240. ], 1, 2, 3,
  241. [
  242. [1, 2, 3],
  243. [2, 3, 4],
  244. [9, 13, 17],
  245. ]
  246. ],
  247. [
  248. [
  249. [1, 2, 3],
  250. [2, 3, 4],
  251. [3, 4, 5],
  252. ], 0, 2, 4,
  253. [
  254. [1, 2, 3],
  255. [2, 3, 4],
  256. [7, 12, 17],
  257. ]
  258. ],
  259. [
  260. [
  261. [1, 2, 3],
  262. [2, 3, 4],
  263. [3, 4, 5],
  264. ], 0, 1, 2.1,
  265. [
  266. [1, 2, 3],
  267. [4.1, 7.2, 10.3],
  268. [3, 4, 5],
  269. ]
  270. ],
  271. ];
  272. }
  273. /**
  274. * @test rowAdd row greater than m
  275. * @throws \Exception
  276. */
  277. public function testRowAddExceptionRowGreaterThanM()
  278. {
  279. // Given
  280. $A = MatrixFactory::create([
  281. [1, 2, 3],
  282. [2, 3, 4],
  283. [3, 4, 5],
  284. ]);
  285. // Then
  286. $this->expectException(Exception\MatrixException::class);
  287. // When
  288. $A->rowAdd(4, 5, 2);
  289. }
  290. /**
  291. * @test rowAdd k is zero
  292. * @throws \Exception
  293. */
  294. public function testRowAddExceptionKIsZero()
  295. {
  296. // Given
  297. $A = MatrixFactory::create([
  298. [1, 2, 3],
  299. [2, 3, 4],
  300. [3, 4, 5],
  301. ]);
  302. // Then
  303. $this->expectException(Exception\BadParameterException::class);
  304. // When
  305. $A->rowAdd(1, 2, 0);
  306. }
  307. /**
  308. * @test rowAddScalar
  309. * @dataProvider dataProviderForRowAddScalar
  310. * @param array $A
  311. * @param int $mᵢ
  312. * @param float $k
  313. * @param array $expectedMatrix
  314. * @throws \Exception
  315. */
  316. public function testRowAddScalar(array $A, int $mᵢ, float $k, array $expectedMatrix)
  317. {
  318. // Given
  319. $A = MatrixFactory::create($A);
  320. $expectedMatrix = MatrixFactory::create($expectedMatrix);
  321. // When
  322. $R = $A->rowAddScalar($mᵢ, $k);
  323. // Then
  324. $this->assertEquals($expectedMatrix, $R);
  325. }
  326. /**
  327. * @return array
  328. */
  329. public function dataProviderForRowAddScalar(): array
  330. {
  331. return [
  332. [
  333. [
  334. [1, 2, 3],
  335. [2, 3, 4],
  336. [3, 4, 5],
  337. ], 0, 5,
  338. [
  339. [6, 7, 8],
  340. [2, 3, 4],
  341. [3, 4, 5],
  342. ],
  343. ],
  344. [
  345. [
  346. [1, 2, 3],
  347. [2, 3, 4],
  348. [3, 4, 5],
  349. ], 0, 5.3,
  350. [
  351. [6.3, 7.3, 8.3],
  352. [2, 3, 4],
  353. [3, 4, 5],
  354. ],
  355. ],
  356. ];
  357. }
  358. /**
  359. * @test rowAddScalar row greater than m
  360. * @throws \Exception
  361. */
  362. public function testRowAddScalarExceptionRowGreaterThanM()
  363. {
  364. // Given
  365. $A = MatrixFactory::create([
  366. [1, 2, 3],
  367. [2, 3, 4],
  368. [3, 4, 5],
  369. ]);
  370. // Then
  371. $this->expectException(Exception\MatrixException::class);
  372. // Then
  373. $A->rowAddScalar(4, 5);
  374. }
  375. /**
  376. * @test rowAddVector
  377. * @dataProvider dataProviderForRowAddVector
  378. * @param array $A
  379. * @param int $mᵢ
  380. * @param array $vector
  381. * @param array $expectedMatrix
  382. * @throws \Exception
  383. */
  384. public function testRowAddVector(array $A, int $mᵢ, array $vector, array $expectedMatrix)
  385. {
  386. // Given
  387. $A = MatrixFactory::createNumeric($A);
  388. $V = new Vector($vector);
  389. $expectedMatrix = MatrixFactory::create($expectedMatrix);
  390. // When
  391. $R = $A->rowAddVector($mᵢ, $V);
  392. // Then
  393. $this->assertEquals($expectedMatrix, $R);
  394. }
  395. /**
  396. * @return array
  397. */
  398. public function dataProviderForRowAddVector(): array
  399. {
  400. return [
  401. [
  402. [
  403. [1],
  404. ], 0, [2],
  405. [
  406. [3],
  407. ]
  408. ],
  409. [
  410. [
  411. [1, 2],
  412. ], 0, [2, 5],
  413. [
  414. [3, 7],
  415. ]
  416. ],
  417. [
  418. [
  419. [1],
  420. [2],
  421. ], 0, [2],
  422. [
  423. [3],
  424. [2],
  425. ]
  426. ],
  427. [
  428. [
  429. [1],
  430. [2],
  431. ], 1, [2],
  432. [
  433. [1],
  434. [4],
  435. ]
  436. ],
  437. [
  438. [
  439. [1, 2],
  440. [4, 5],
  441. ], 0, [2, 4],
  442. [
  443. [3, 6],
  444. [4, 5],
  445. ]
  446. ],
  447. [
  448. [
  449. [1, 2],
  450. [4, 5],
  451. ], 1, [2, 4],
  452. [
  453. [1, 2],
  454. [6, 9],
  455. ]
  456. ],
  457. [
  458. [
  459. [1, 2, 3],
  460. [2, 3, 4],
  461. [3, 4, 5],
  462. ], 0, [1,2,3],
  463. [
  464. [2, 4, 6],
  465. [2, 3, 4],
  466. [3, 4, 5],
  467. ]
  468. ],
  469. [
  470. [
  471. [1, 2, 3],
  472. [2, 3, 4],
  473. [3, 4, 5],
  474. ], 2, [6,9,12],
  475. [
  476. [1, 2, 3],
  477. [2, 3, 4],
  478. [9, 13, 17],
  479. ]
  480. ],
  481. [
  482. [
  483. [1, 2, 3],
  484. [2, 3, 4],
  485. [3, 4, 5],
  486. ], 2, [4,8,12],
  487. [
  488. [1, 2, 3],
  489. [2, 3, 4],
  490. [7, 12, 17],
  491. ]
  492. ],
  493. [
  494. [
  495. [1, 2, 3],
  496. [2, 3, 4],
  497. [3, 4, 5],
  498. ], 1, [2.2,3.3,4.4],
  499. [
  500. [1, 2, 3],
  501. [4.2, 6.3, 8.4],
  502. [3, 4, 5],
  503. ]
  504. ],
  505. ];
  506. }
  507. /**
  508. * @test rowAddVector test row m exists
  509. * @throws \Exception
  510. */
  511. public function testRowAddVectorExceptionRowExists()
  512. {
  513. // Given
  514. $A = MatrixFactory::createNumeric([
  515. [1, 2, 3],
  516. [2, 3, 4],
  517. [3, 4, 5],
  518. ]);
  519. $b = new Vector([1,2,3]);
  520. // Then
  521. $this->expectException(Exception\MatrixException::class);
  522. // When
  523. $A->rowAddVector(4, $b);
  524. }
  525. /**
  526. * @test rowAddVector test vector->count() === matrix m
  527. * @throws \Exception
  528. */
  529. public function testRowAddVectorExceptionElementMismatch()
  530. {
  531. // Given
  532. $A = MatrixFactory::createNumeric([
  533. [1, 2, 3],
  534. [2, 3, 4],
  535. [3, 4, 5],
  536. ]);
  537. $b = new Vector([1,2,3,4]);
  538. // Then
  539. $this->expectException(Exception\BadParameterException::class);
  540. // When
  541. $A->rowAddVector(1, $b);
  542. }
  543. /**
  544. * @test rowSubtract
  545. * @dataProvider dataProviderForRowSubtract
  546. * @param array $A
  547. * @param int $mᵢ
  548. * @param int $mⱼ
  549. * @param float $k
  550. * @param array $expectedMatrix
  551. * @throws \Exception
  552. */
  553. public function testRowSubtract(array $A, int $mᵢ, int $mⱼ, float $k, array $expectedMatrix)
  554. {
  555. // Given
  556. $A = MatrixFactory::create($A);
  557. $expectedMatrix = MatrixFactory::create($expectedMatrix);
  558. // When
  559. $R = $A->rowSubtract($mᵢ, $mⱼ, $k);
  560. // Then
  561. $this->assertEqualsWithDelta($expectedMatrix, $R, 0.00001);
  562. }
  563. /**
  564. * @return array
  565. */
  566. public function dataProviderForRowSubtract(): array
  567. {
  568. return [
  569. [
  570. [
  571. [1, 2, 3],
  572. [2, 3, 4],
  573. [3, 4, 5],
  574. ], 0, 1, 2,
  575. [
  576. [1, 2, 3],
  577. [0, -1, -2],
  578. [3, 4, 5],
  579. ]
  580. ],
  581. [
  582. [
  583. [1, 2, 3],
  584. [2, 3, 4],
  585. [3, 4, 5],
  586. ], 1, 2, 3,
  587. [
  588. [1, 2, 3],
  589. [2, 3, 4],
  590. [-3, -5, -7],
  591. ]
  592. ],
  593. [
  594. [
  595. [1, 2, 3],
  596. [2, 3, 4],
  597. [3, 4, 5],
  598. ], 0, 2, 4,
  599. [
  600. [1, 2, 3],
  601. [2, 3, 4],
  602. [-1, -4, -7],
  603. ]
  604. ],
  605. [
  606. [
  607. [1, 2, 3],
  608. [2, 3, 4],
  609. [3, 4, 5],
  610. ], 0, 1, 2.6,
  611. [
  612. [1, 2, 3],
  613. [-0.6, -2.2, -3.8],
  614. [3, 4, 5],
  615. ]
  616. ],
  617. ];
  618. }
  619. /**
  620. * @test rowSubtract row greater than m
  621. * @throws \Exception
  622. */
  623. public function testRowSubtractExceptionRowGreaterThanM()
  624. {
  625. // Given
  626. $A = MatrixFactory::create([
  627. [1, 2, 3],
  628. [2, 3, 4],
  629. [3, 4, 5],
  630. ]);
  631. // Then
  632. $this->expectException(Exception\MatrixException::class);
  633. // When
  634. $A->rowSubtract(4, 5, 2);
  635. }
  636. /**
  637. * @test rowSubtractScalar
  638. * @dataProvider dataProviderForRowSubtractScalar
  639. * @param array $A
  640. * @param int $mᵢ
  641. * @param float $k
  642. * @param array $expectedMatrix
  643. * @throws \Exception
  644. */
  645. public function testRowSubtractScalar(array $A, int $mᵢ, float $k, array $expectedMatrix)
  646. {
  647. // Given
  648. $A = MatrixFactory::create($A);
  649. $expectedMatrix = MatrixFactory::create($expectedMatrix);
  650. // When
  651. $R = $A->rowSubtractScalar($mᵢ, $k);
  652. // Then
  653. $this->assertEqualsWithDelta($expectedMatrix, $R, 0.00001);
  654. }
  655. /**
  656. * @return array
  657. */
  658. public function dataProviderForRowSubtractScalar(): array
  659. {
  660. return [
  661. [
  662. [
  663. [6, 7, 8],
  664. [2, 3, 4],
  665. [3, 4, 5],
  666. ], 0, 5,
  667. [
  668. [1, 2, 3],
  669. [2, 3, 4],
  670. [3, 4, 5],
  671. ],
  672. ],
  673. [
  674. [
  675. [6, 7, 8],
  676. [2, 3, 4],
  677. [3, 4, 5],
  678. ], 0, 5.2,
  679. [
  680. [0.8, 1.8, 2.8],
  681. [2, 3, 4],
  682. [3, 4, 5],
  683. ],
  684. ],
  685. ];
  686. }
  687. /**
  688. * @test rowSubtractScalar row greater than m
  689. * @throws \Exception
  690. */
  691. public function testRowSubtractScalarExceptionRowGreaterThanM()
  692. {
  693. // Given
  694. $A = MatrixFactory::create([
  695. [1, 2, 3],
  696. [2, 3, 4],
  697. [3, 4, 5],
  698. ]);
  699. // Then
  700. $this->expectException(Exception\MatrixException::class);
  701. // When
  702. $A->rowSubtractScalar(4, 5);
  703. }
  704. }