ObjectSquareMatrixTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?php
  2. namespace MathPHP\Tests\LinearAlgebra\Matrix\Object;
  3. use MathPHP\Expression\Polynomial;
  4. use MathPHP\LinearAlgebra\MatrixFactory;
  5. use MathPHP\LinearAlgebra\ObjectSquareMatrix;
  6. use MathPHP\LinearAlgebra\Vector;
  7. use MathPHP\Number\Complex;
  8. use MathPHP\Exception;
  9. use MathPHP\Number\ObjectArithmetic;
  10. class ObjectSquareMatrixTest extends \PHPUnit\Framework\TestCase
  11. {
  12. /**
  13. * @test The constructor throws the proper exceptions
  14. * @dataProvider dataProviderConstructorException
  15. * @param array $A
  16. * @param string $exception
  17. */
  18. public function testMatrixConstructorException(array $A, string $exception)
  19. {
  20. // Then
  21. $this->expectException($exception);
  22. // When
  23. $A = new ObjectSquareMatrix($A);
  24. }
  25. public function dataProviderConstructorException(): array
  26. {
  27. return [
  28. 'rows have different types' => [
  29. [[new \stdClass()]],
  30. Exception\IncorrectTypeException::class,
  31. ],
  32. 'columns have different types' => [
  33. [[new \stdClass(), new Polynomial([1, 2, 3])],
  34. [new \stdClass(), new Polynomial([1, 2, 3])]],
  35. Exception\IncorrectTypeException::class,
  36. ],
  37. 'not square' => [
  38. [
  39. [new Polynomial([1, 2]), new Polynomial([2, 1])],
  40. ],
  41. Exception\MatrixException::class,
  42. ],
  43. ];
  44. }
  45. /**
  46. * @test Addition throws the proper exceptions
  47. * @dataProvider dataProviderForArithmeticExceptions
  48. * @param array $A
  49. * @param ObjectArithmetic $B
  50. * @param string $exception
  51. */
  52. public function testMatrixAddException(array $A, ObjectArithmetic $B, string $exception)
  53. {
  54. // Given
  55. $A = new ObjectSquareMatrix($A);
  56. // Then
  57. $this->expectException($exception);
  58. // When
  59. $C = $A->add($B);
  60. }
  61. /**
  62. * @test Subtraction throws the proper exceptions
  63. * @dataProvider dataProviderForArithmeticExceptions
  64. * @param array $A
  65. * @param ObjectArithmetic $B
  66. * @param string $exception
  67. */
  68. public function testMatrixSubtractException(array $A, ObjectArithmetic $B, string $exception)
  69. {
  70. // Given
  71. $A = new ObjectSquareMatrix($A);
  72. // Then
  73. $this->expectException($exception);
  74. // When
  75. $C = $A->subtract($B);
  76. }
  77. /**
  78. * @test Multiplication throws the proper exceptions
  79. * @dataProvider dataProviderForArithmeticExceptions
  80. * @param array $A
  81. * @param ObjectArithmetic $B
  82. * @param string $exception
  83. */
  84. public function testMatrixMultiplyException(array $A, ObjectArithmetic $B, string $exception)
  85. {
  86. // Given
  87. $A = new ObjectSquareMatrix($A);
  88. // Then
  89. $this->expectException($exception);
  90. // When
  91. $C = $A->multiply($B);
  92. }
  93. public function dataProviderForArithmeticExceptions(): array
  94. {
  95. return[
  96. [ // Different Sizes
  97. [[new Polynomial([1, 2, 3]), new Polynomial([1, 2, 3])],
  98. [new Polynomial([1, 2, 3]), new Polynomial([1, 2, 3])]],
  99. MatrixFactory::create([[new Polynomial([1, 2, 3])]]),
  100. Exception\MatrixException::class,
  101. ],
  102. [ // Different Types
  103. [[new Polynomial([1, 2, 3])]],
  104. new ObjectSquareMatrix([[new Complex(1, 2)]]),
  105. Exception\IncorrectTypeException::class,
  106. ],
  107. [ // Not a Matrix
  108. [[new Polynomial([1, 2, 3])]],
  109. new Complex(1, 2),
  110. Exception\IncorrectTypeException::class,
  111. ],
  112. ];
  113. }
  114. /**
  115. * @test isEqual
  116. * @dataProvider dataProviderisEqual
  117. * @param array $A
  118. * @param array $B
  119. * @param bool $expected
  120. * @throws \Exception
  121. */
  122. public function testIsEqual(array $A, array $B, bool $expected)
  123. {
  124. // Given
  125. $A = MatrixFactory::create($A);
  126. $B = MatrixFactory::create($B);
  127. // When
  128. $comparison = $A->isEqual($B);
  129. // Then
  130. $this->assertEquals($expected, $comparison);
  131. }
  132. /**
  133. * @return array
  134. */
  135. public function dataProviderisEqual()
  136. {
  137. return [
  138. 'same' => [
  139. [[new Polynomial([1, 0])]],
  140. [[new Polynomial([1, 0])]],
  141. true,
  142. ],
  143. 'different types' => [
  144. [[new Polynomial([1, 0])]],
  145. [[1]],
  146. false,
  147. ],
  148. 'different contents' => [
  149. [[new Polynomial([1, 0])]],
  150. [[new Polynomial([1, 1])]],
  151. false,
  152. ],
  153. 'different shapes' => [
  154. [[new Polynomial([1, 0]), new Polynomial([1, 0])]],
  155. [[new Polynomial([1, 0])], [new Polynomial([1, 0])]],
  156. false,
  157. ],
  158. ];
  159. }
  160. /**
  161. * @test add
  162. * @dataProvider dataProviderAdd
  163. * @param array $A
  164. * @param array $B
  165. * @param array $expected
  166. * @throws \Exception
  167. */
  168. public function testAdd(array $A, array $B, array $expected)
  169. {
  170. // Given
  171. $A = new ObjectSquareMatrix($A);
  172. $B = new ObjectSquareMatrix($B);
  173. // And
  174. $expected = matrixFactory::create($expected);
  175. // When
  176. $sum = $A->add($B);
  177. // Then
  178. $this->assertEquals($expected, $sum);
  179. }
  180. /**
  181. * @return array
  182. */
  183. public function dataProviderAdd(): array
  184. {
  185. return [
  186. [
  187. [
  188. [new Polynomial([1, 0]), new Polynomial([0, 0])],
  189. [new Polynomial([0, 0]), new Polynomial([1, 0])],
  190. ],
  191. [
  192. [new Polynomial([1, 0]), new Polynomial([1, 1])],
  193. [new Polynomial([1, 1]), new Polynomial([1, 0])],
  194. ],
  195. [
  196. [new Polynomial([2, 0]), new Polynomial([1, 1])],
  197. [new Polynomial([1, 1]), new Polynomial([2, 0])],
  198. ],
  199. ],
  200. [
  201. [
  202. [new Polynomial([1, 0]), new Polynomial([1, 0])],
  203. [new Polynomial([1, 0]), new Polynomial([1, 0])],
  204. ],
  205. [
  206. [new Polynomial([1, 0]), new Polynomial([1, 1])],
  207. [new Polynomial([1, 1]), new Polynomial([1, 0])],
  208. ],
  209. [
  210. [new Polynomial([2, 0]), new Polynomial([2, 1])],
  211. [new Polynomial([2, 1]), new Polynomial([2, 0])],
  212. ],
  213. ],
  214. ];
  215. }
  216. /**
  217. * @test subtract
  218. * @dataProvider dataProviderSubtract
  219. * @param array $A
  220. * @param array $B
  221. * @param array $expected
  222. * @throws \Exception
  223. */
  224. public function testSubtract(array $A, array $B, array $expected)
  225. {
  226. // Given
  227. $A = new ObjectSquareMatrix($A);
  228. $B = new ObjectSquareMatrix($B);
  229. $expected = new ObjectSquareMatrix($expected);
  230. // When
  231. $difference = $A->subtract($B);
  232. // Then
  233. $this->assertEquals($expected, $difference);
  234. }
  235. /**
  236. * @return array
  237. */
  238. public function dataProviderSubtract(): array
  239. {
  240. return [
  241. [
  242. [
  243. [new Polynomial([1, 0]), new Polynomial([0, 0])],
  244. [new Polynomial([0, 0]), new Polynomial([1, 0])],
  245. ],
  246. [
  247. [new Polynomial([2, 1]), new Polynomial([2, 1])],
  248. [new Polynomial([1, -1]), new Polynomial([-1, 0])],
  249. ],
  250. [
  251. [new Polynomial([-1, -1]), new Polynomial([-2, -1])],
  252. [new Polynomial([-1, 1]), new Polynomial([2, 0])],
  253. ],
  254. ],
  255. [
  256. [
  257. [new Polynomial([1, 0]), new Polynomial([1, 0])],
  258. [new Polynomial([1, 0]), new Polynomial([1, 0])],
  259. ],
  260. [
  261. [new Polynomial([-2, 0]), new Polynomial([1, -1])],
  262. [new Polynomial([-2, 2]), new Polynomial([4, 4])],
  263. ],
  264. [
  265. [new Polynomial([3, 0]), new Polynomial([0, 1])],
  266. [new Polynomial([3, -2]), new Polynomial([-3, -4])],
  267. ],
  268. ],
  269. ];
  270. }
  271. /**
  272. * @test multiply
  273. * @dataProvider dataProviderMul
  274. * @param array $A
  275. * @param array $B
  276. * @param array $expected
  277. */
  278. public function testMul(array $A, array $B, array $expected)
  279. {
  280. // Given
  281. $A = new ObjectSquareMatrix($A);
  282. $B = new ObjectSquareMatrix($B);
  283. // And
  284. $expected = matrixFactory::create($expected);
  285. // When
  286. $sum = $A->multiply($B);
  287. // Then
  288. $this->assertEquals($expected, $sum);
  289. }
  290. /**
  291. * @return array
  292. */
  293. public function dataProviderMul(): array
  294. {
  295. return [
  296. [
  297. [
  298. [new Polynomial([1, 0]), new Polynomial([0, 0])],
  299. [new Polynomial([0, 0]), new Polynomial([1, 0])],
  300. ],
  301. [
  302. [new Polynomial([1, 0]), new Polynomial([1, 1])],
  303. [new Polynomial([1, 1]), new Polynomial([1, 0])],
  304. ],
  305. [
  306. [new Polynomial([1, 0, 0]), new Polynomial([1, 1, 0])],
  307. [new Polynomial([1, 1, 0]), new Polynomial([1, 0, 0])],
  308. ],
  309. ],
  310. [
  311. [
  312. [new Polynomial([1, 0]), new Polynomial([1, 0])],
  313. [new Polynomial([1, 0]), new Polynomial([1, 0])],
  314. ],
  315. [
  316. [new Polynomial([1, 0]), new Polynomial([1, 1])],
  317. [new Polynomial([1, 1]), new Polynomial([1, 0])],
  318. ],
  319. [
  320. [new Polynomial([2, 1, 0]), new Polynomial([2, 1, 0])],
  321. [new Polynomial([2, 1, 0]), new Polynomial([2, 1, 0])],
  322. ],
  323. ],
  324. ];
  325. }
  326. /**
  327. * @test Matrix can be multiplied by a vector
  328. * @dataProvider dataProviderMultiplyVector
  329. * @param array $A
  330. * @param array $B
  331. * @param array $expected
  332. */
  333. public function testMultiplyVector(array $A, array $B, array $expected)
  334. {
  335. // Given
  336. $A = new ObjectSquareMatrix($A);
  337. $B = new Vector($B);
  338. // When
  339. $sum = $A->multiply($B);
  340. // Then
  341. $expected = MatrixFactory::create($expected);
  342. $this->assertEquals($expected, $sum);
  343. }
  344. public function dataProviderMultiplyVector(): array
  345. {
  346. return [
  347. [
  348. [
  349. [new Polynomial([1, 0]), new Polynomial([0, 0])],
  350. [new Polynomial([0, 0]), new Polynomial([1, 0])],
  351. ],
  352. [new Polynomial([1, 0]), new Polynomial([1, 1])],
  353. [
  354. [new Polynomial([1, 0, 0])],
  355. [new Polynomial([1, 1, 0])],
  356. ],
  357. ],
  358. ];
  359. }
  360. /**
  361. * @test det
  362. * @dataProvider dataProviderDet
  363. * @param array $A
  364. * @param Polynomial $expected
  365. */
  366. public function testDet(array $A, Polynomial $expected)
  367. {
  368. // Given
  369. $A = new ObjectSquareMatrix($A);
  370. // When
  371. $det = $A->det();
  372. // Then
  373. $this->assertEquals($det, $expected);
  374. // And when
  375. $det = $A->det();
  376. // Then
  377. $this->assertEquals($expected, $det);
  378. }
  379. /**
  380. * @return array
  381. */
  382. public function dataProviderDet(): array
  383. {
  384. return [
  385. [
  386. [
  387. [new Polynomial([1, 0])],
  388. ],
  389. new Polynomial([1, 0]),
  390. ],
  391. [
  392. [
  393. [new Polynomial([1, 0]), new Polynomial([1, 0])],
  394. [new Polynomial([1, 0]), new Polynomial([0, 4])],
  395. ],
  396. new Polynomial([-1, 4, 0]),
  397. ],
  398. ];
  399. }
  400. }