PolynomialAxiomsTest.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. <?php
  2. namespace MathPHP\Tests\Expression;
  3. use MathPHP\Expression\Polynomial;
  4. /**
  5. * Tests of polynomial axioms
  6. * These tests don't test specific functions,
  7. * but rather polynomial axioms which in term make use of multiple functions.
  8. * If all the polynomial math is implemented properly, these tests should
  9. * all work out according to the axioms.
  10. *
  11. * Axioms tested:
  12. * - Commutativity
  13. * - a + b = b + a
  14. * - ab = bc
  15. * - Associativity
  16. * - a + (b + c) = (a + b) + c
  17. * - a(bc) = (ab)c
  18. * - Distributed Law
  19. * - a ✕ (b + c) = a ✕ b + a ✕ c
  20. * - a + (b ✕ c) = a ✕ c + b ✕ c
  21. * - Identity
  22. * - a + 0 = 0 + a = a
  23. * - a ✕ 0 = 0 ✕ a = 0
  24. * - Negate
  25. * - -a = a * -1
  26. * - Arithmetic
  27. * - Sum of two polynomials is a polynomial
  28. * - Product of two polynomials is a polynomial
  29. * - Derivative of a polynomial is a polynomial
  30. * - Integral of a polynomial is a polynomial
  31. */
  32. class PolynomialAxiomsTest extends \PHPUnit\Framework\TestCase
  33. {
  34. /**
  35. * @test Axiom: a + b = b + a
  36. * Commutativity of addition.
  37. * @dataProvider dataProviderForTwoPolynomials
  38. * @param array $a
  39. * @param array $b
  40. * @throws \Exception
  41. */
  42. public function testCommutativityOfAddition(array $a, array $b)
  43. {
  44. // Given
  45. $a = new Polynomial($a);
  46. $b = new Polynomial($b);
  47. // When
  48. $a+b = $a->add($b);
  49. $b+a = $b->add($a);
  50. // Then
  51. $this->assertEquals($a+b->getDegree(), $b+a->getDegree());
  52. $this->assertEquals($a+b->getCoefficients(), $b+a->getCoefficients());
  53. }
  54. /**
  55. * @test Axiom: ab = bc
  56. * Commutativity of multiplication.
  57. * @dataProvider dataProviderForTwoPolynomials
  58. * @param array $a
  59. * @param array $b
  60. * @throws \Exception
  61. */
  62. public function testCommutativityOfMultiplication(array $a, array $b)
  63. {
  64. // Given
  65. $a = new Polynomial($a);
  66. $b = new Polynomial($b);
  67. // When
  68. $ab = $a->multiply($b);
  69. $ba = $b->multiply($a);
  70. // Then
  71. $this->assertEquals($ab->getDegree(), $ba->getDegree());
  72. $this->assertEquals($ab->getCoefficients(), $ba->getCoefficients());
  73. }
  74. /**
  75. * @test Axiom: a + (b + c) = (a + b) + c
  76. * Associativity of addition.
  77. * @dataProvider dataProviderForThreePolynomials
  78. * @param array $a
  79. * @param array $b
  80. * @param array $c
  81. * @throws \Exception
  82. */
  83. public function testAssociativityOfAddition(array $a, array $b, array $c)
  84. {
  85. // Given
  86. $a = new Polynomial($a);
  87. $b = new Polynomial($b);
  88. $c = new Polynomial($c);
  89. // When
  90. $a + ⟮b + c⟯ = $a->add($b->add($c));
  91. $⟮a + b⟯ + c = ($a->add($b))->add($c);
  92. // Then
  93. $this->assertEquals($a + ⟮b + c⟯->getDegree(), $⟮a + b⟯ + c->getDegree());
  94. $this->assertEquals($a + ⟮b + c⟯->getCoefficients(), $⟮a + b⟯ + c->getCoefficients());
  95. }
  96. /**
  97. * @test Axiom: a(bc) = (ab)c
  98. * Associativity of multiplication.
  99. * @dataProvider dataProviderForThreePolynomials
  100. * @param array $a
  101. * @param array $b
  102. * @param array $c
  103. * @throws \Exception
  104. */
  105. public function testAssociativityOfMultiplication(array $a, array $b, array $c)
  106. {
  107. // Given
  108. $a = new Polynomial($a);
  109. $b = new Polynomial($b);
  110. $c = new Polynomial($c);
  111. // When
  112. $a⟮bc⟯ = $a->multiply($b->multiply($c));
  113. $⟮ab⟯c = ($a->multiply($b))->multiply($c);
  114. // Then
  115. $this->assertEquals($a⟮bc⟯->getDegree(), $⟮ab⟯c->getDegree());
  116. $this->assertEquals($a⟮bc⟯->getCoefficients(), $⟮ab⟯c->getCoefficients());
  117. }
  118. /**
  119. * @test Axiom: a ✕ (b + c) = a ✕ b + a ✕ c
  120. * Distributive law.
  121. * @dataProvider dataProviderForThreePolynomials
  122. * @param array $a
  123. * @param array $b
  124. * @param array $c
  125. * @throws \Exception
  126. */
  127. public function testDistributiveLaw1(array $a, array $b, array $c)
  128. {
  129. // Given
  130. $a = new Polynomial($a);
  131. $b = new Polynomial($b);
  132. $c = new Polynomial($c);
  133. // When
  134. $a⟮b + c⟯ = $a->multiply($b->add($c));
  135. $⟮ab⟯ + ⟮ac⟯ = ($a->multiply($b))->add($a->multiply($c));
  136. // Then
  137. $this->assertEquals($a⟮b + c⟯->getDegree(), $⟮ab⟯ + ⟮ac⟯->getDegree());
  138. $this->assertEquals($a⟮b + c⟯->getCoefficients(), $⟮ab⟯ + ⟮ac⟯->getCoefficients());
  139. }
  140. /**
  141. * @test Axiom: (a + b) ✕ c = a ✕ c + b ✕ c
  142. * Distributive law.
  143. * @dataProvider dataProviderForThreePolynomials
  144. * @param array $a
  145. * @param array $b
  146. * @param array $c
  147. * @throws \Exception
  148. */
  149. public function testDistributiveLaw2(array $a, array $b, array $c)
  150. {
  151. // Given
  152. $a = new Polynomial($a);
  153. $b = new Polynomial($b);
  154. $c = new Polynomial($c);
  155. // When
  156. $⟮a + b⟯c = ($a->add($b))->multiply($c);
  157. $⟮ac⟯ + ⟮bc⟯ = ($a->multiply($c))->add($b->multiply($c));
  158. // Then
  159. $this->assertEquals($⟮a + b⟯c->getDegree(), $⟮ac⟯ + ⟮bc⟯->getDegree());
  160. $this->assertEquals($⟮a + b⟯c->getCoefficients(), $⟮ac⟯ + ⟮bc⟯->getCoefficients());
  161. }
  162. /**
  163. * @test Axiom: a + 0 = 0 + a = a
  164. * Identity of addition.
  165. * @dataProvider dataProviderForOnePolynomial
  166. * @param array $a
  167. * @throws \Exception
  168. */
  169. public function testIdentityOfAddition(array $a)
  170. {
  171. // Given
  172. $a = new Polynomial($a);
  173. $zero = new Polynomial([0]);
  174. // When
  175. $a+0 = $a->add($zero);
  176. $zero+a = $zero->add($a);
  177. // Then
  178. $this->assertEquals($a->getDegree(), $a+0->getDegree());
  179. $this->assertEquals($a->getDegree(), $zero+a->getDegree());
  180. // And
  181. $this->assertEquals($a->getCoefficients(), $a+0->getCoefficients());
  182. $this->assertEquals($a->getCoefficients(), $zero+a->getCoefficients());
  183. }
  184. /**
  185. * @test Axiom: a ✕ 0 = 0 ✕ a = 0
  186. * Identity of multiplication.
  187. * @dataProvider dataProviderForOnePolynomial
  188. * @param array $a
  189. * @throws \Exception
  190. */
  191. public function testIdentityOfMultiplication(array $a)
  192. {
  193. // Given
  194. $a = new Polynomial($a);
  195. $zero = new Polynomial([0]);
  196. // When
  197. $a✕0 = $a->multiply($zero);
  198. $zero✕a = $zero->multiply($a);
  199. // Then
  200. $this->assertEquals($zero->getDegree(), $a✕0->getDegree());
  201. $this->assertEquals($zero->getDegree(), $zero✕a->getDegree());
  202. // And
  203. $this->assertEquals($zero->getCoefficients(), $a✕0->getCoefficients());
  204. $this->assertEquals($zero->getCoefficients(), $zero✕a->getCoefficients());
  205. }
  206. /**
  207. * @test Axiom: -a = a * -1
  208. * Negation is the same as multiplying by -1
  209. * @dataProvider dataProviderForOnePolynomial
  210. * @param array $a
  211. * @throws \Exception
  212. */
  213. public function testNegateSameAsMultiplyingByNegativeOne(array $a)
  214. {
  215. // Given
  216. $a = new Polynomial($a);
  217. // When
  218. $−a = $a->negate();
  219. $a⟮−1⟯ = $a->multiply(-1);
  220. // Then
  221. $this->assertEquals($−a->getDegree(), $a⟮−1⟯->getDegree());
  222. $this->assertEquals($−a->getCoefficients(), $a⟮−1⟯->getCoefficients());
  223. }
  224. /**
  225. * @test Axiom: Sum of two polynomials is a polynomial
  226. * @dataProvider dataProviderForTwoPolynomials
  227. * @param array $a
  228. * @param array $b
  229. * @throws \Exception
  230. */
  231. public function testArithmeticAdditionProperty(array $a, array $b)
  232. {
  233. // Given
  234. $a = new Polynomial($a);
  235. $b = new Polynomial($b);
  236. // When
  237. $a+b = $a->add($b);
  238. // Then
  239. $this->assertInstanceOf(Polynomial::class, $a+b);
  240. }
  241. /**
  242. * @test Axiom: Product of two polynomials is a polynomial
  243. * @dataProvider dataProviderForTwoPolynomials
  244. * @param array $a
  245. * @param array $b
  246. * @throws \Exception
  247. */
  248. public function testArithmeticMultiplicationProperty(array $a, array $b)
  249. {
  250. // Given
  251. $a = new Polynomial($a);
  252. $b = new Polynomial($b);
  253. // When
  254. $ab = $a->multiply($b);
  255. // Then
  256. $this->assertInstanceOf(Polynomial::class, $ab);
  257. }
  258. /**
  259. * @test Axiom: Derivative of a polynomials is a polynomial
  260. * @dataProvider dataProviderForOnePolynomial
  261. * @param array $a
  262. * @throws \Exception
  263. */
  264. public function testArithmeticDerivativeProperty(array $a)
  265. {
  266. // Given
  267. $a = new Polynomial($a);
  268. // When
  269. $derivative = $a->differentiate();
  270. // Then
  271. $this->assertInstanceOf(Polynomial::class, $derivative);
  272. }
  273. /**
  274. * @test Axiom: Integral of a polynomials is a polynomial
  275. * @dataProvider dataProviderForOnePolynomial
  276. * @param array $a
  277. * @throws \Exception
  278. */
  279. public function testArithmeteicIntegrationProperty(array $a)
  280. {
  281. // Given
  282. $a = new Polynomial($a);
  283. // When
  284. $derivative = $a->integrate();
  285. // Then
  286. $this->assertInstanceOf(Polynomial::class, $derivative);
  287. }
  288. public function dataProviderForOnePolynomial(): array
  289. {
  290. return [
  291. [
  292. [0],
  293. ],
  294. [
  295. [1],
  296. ],
  297. [
  298. [2],
  299. ],
  300. [
  301. [8],
  302. ],
  303. [
  304. [1, 5],
  305. ],
  306. [
  307. [4, 0],
  308. ],
  309. [
  310. [0, 3],
  311. ],
  312. [
  313. [12, 4],
  314. ],
  315. [
  316. [1, 2, 3],
  317. ],
  318. [
  319. [2, 3, 4],
  320. ],
  321. [
  322. [1, 1, 1],
  323. ],
  324. [
  325. [5, 3, 6],
  326. ],
  327. [
  328. [2, 7, 4],
  329. ],
  330. [
  331. [6, 0, 3],
  332. ],
  333. [
  334. [4, 5, 2, 6],
  335. ],
  336. [
  337. [3, 5, 2, 10],
  338. ],
  339. [
  340. [-4, 6, 7, -1],
  341. ],
  342. [
  343. [-2, -1, -4, -3],
  344. ],
  345. [
  346. [5, 3, 6],
  347. ],
  348. [
  349. [7, 6, 6],
  350. ],
  351. [
  352. [-6, -1],
  353. ],
  354. [
  355. [-5, -5, -1, 2, 4, 6, 5],
  356. ],
  357. [
  358. [10, 20, 30, 40],
  359. ],
  360. [
  361. [-5, 10, -15, 20, -55],
  362. ],
  363. [
  364. [0, 0, 0, 0, 5],
  365. ],
  366. [
  367. [2, 0, 0, 0, 4],
  368. ],
  369. [
  370. [-1, -2, -3, -4, -5, -6, -7, -8, -9],
  371. ],
  372. [
  373. [1, 2, 3, 4, 5, 6, 7, 8, 9],
  374. ],
  375. [
  376. [4, 54, 23, -34, 12, 73, -34, 2],
  377. ],
  378. ];
  379. }
  380. public function dataProviderForTwoPolynomials(): array
  381. {
  382. return [
  383. [
  384. [0],
  385. [0],
  386. ],
  387. [
  388. [1],
  389. [1],
  390. ],
  391. [
  392. [0],
  393. [1],
  394. ],
  395. [
  396. [1],
  397. [0],
  398. ],
  399. [
  400. [2],
  401. [2],
  402. ],
  403. [
  404. [1],
  405. [2],
  406. ],
  407. [
  408. [4],
  409. [8],
  410. ],
  411. [
  412. [1, 5],
  413. [5, 4],
  414. ],
  415. [
  416. [4, 0],
  417. [5, 6],
  418. ],
  419. [
  420. [0, 3],
  421. [5, 5],
  422. ],
  423. [
  424. [12, 4],
  425. [5, 10],
  426. ],
  427. [
  428. [1, 2, 3],
  429. [1, 2, 3],
  430. ],
  431. [
  432. [1, 2, 3],
  433. [2, 3, 4],
  434. ],
  435. [
  436. [1, 1, 1],
  437. [2, 2, 2],
  438. ],
  439. [
  440. [5, 3, 6],
  441. [8, 7, 3],
  442. ],
  443. [
  444. [2, 7, 4],
  445. [5, 4, 7],
  446. ],
  447. [
  448. [6, 0, 3],
  449. [1, 1, 2],
  450. ],
  451. [
  452. [4, 5, 2, 6],
  453. [6, 5, 5, 4],
  454. ],
  455. [
  456. [3, 5, 2, 10],
  457. [2, -2, 5, 3],
  458. ],
  459. [
  460. [-4, 6, 7, -1],
  461. [5, 5, -5, -1],
  462. ],
  463. [
  464. [-2, -1, -4, -3],
  465. [-5, 5, -4, -3],
  466. ],
  467. [
  468. [1],
  469. [5, 3, 6],
  470. ],
  471. [
  472. [7, 6, 6],
  473. [3, 2],
  474. ],
  475. [
  476. [-3, 4, 5, 6],
  477. [-6, -1],
  478. ],
  479. [
  480. [5, 6, 7, 6, 5, 6],
  481. [-5, -5, -1, 2, 4, 6, 5],
  482. ],
  483. [
  484. [10, 20, 30, 40],
  485. [-4, 5, 6, -4, 3],
  486. ],
  487. [
  488. [4, 8, 12, 16, 20],
  489. [-5, 10, -15, 20, -55],
  490. ],
  491. [
  492. [0, 0, 0, 0, 5],
  493. [4, 3, 6, 7],
  494. ],
  495. [
  496. [2, 0, 0, 0, 4],
  497. [1, 1, 1, 1, 1],
  498. ],
  499. [
  500. [1, 2, 3, 4, 5, 6, 7, 8, 9],
  501. [-1, -2, -3, -4, -5, -6, -7, -8, -9],
  502. ],
  503. [
  504. [1, 2, 3, 4, 5, 6, 7, 8, 9],
  505. [2, 3, 4, 5, 6, 7, 8, 9, 10],
  506. ],
  507. [
  508. [34, 65, 34, 23, 62, 87, 34, 65],
  509. [4, 54, 23, -34, 12, 73, -34, 2],
  510. ],
  511. ];
  512. }
  513. public function dataProviderForThreePolynomials(): array
  514. {
  515. return [
  516. [
  517. [0],
  518. [0],
  519. [0],
  520. ],
  521. [
  522. [1],
  523. [1],
  524. [1],
  525. ],
  526. [
  527. [0],
  528. [1],
  529. [0],
  530. ],
  531. [
  532. [1],
  533. [0],
  534. [1],
  535. ],
  536. [
  537. [2],
  538. [2],
  539. [2],
  540. ],
  541. [
  542. [1],
  543. [2],
  544. [3],
  545. ],
  546. [
  547. [4],
  548. [8],
  549. [2],
  550. ],
  551. [
  552. [1, 5],
  553. [5, 4],
  554. [4, 3],
  555. ],
  556. [
  557. [4, 0],
  558. [5, 6],
  559. [6, 5],
  560. ],
  561. [
  562. [0, 3],
  563. [5, 5],
  564. [0, 0],
  565. ],
  566. [
  567. [12, 4],
  568. [5, 10],
  569. [2, 10],
  570. ],
  571. [
  572. [1, 2, 3],
  573. [1, 2, 3],
  574. [1, 2, 3],
  575. ],
  576. [
  577. [1, 2, 3],
  578. [2, 3, 4],
  579. [3, 4, 5],
  580. ],
  581. [
  582. [1, 1, 1],
  583. [2, 2, 2],
  584. [3, 3, 3],
  585. ],
  586. [
  587. [5, 3, 6],
  588. [8, 7, 3],
  589. [3, 2, 7],
  590. ],
  591. [
  592. [2, 7, 4],
  593. [5, 4, 7],
  594. [6, 5, 4],
  595. ],
  596. [
  597. [6, 0, 3],
  598. [1, 1, 2],
  599. [2, 3, 0],
  600. ],
  601. [
  602. [4, 5, 2, 6],
  603. [6, 5, 5, 4],
  604. [2, 2, 3, 3],
  605. ],
  606. [
  607. [3, 5, 2, 10],
  608. [2, -2, 5, 3],
  609. [-1, 3, 4, -1],
  610. ],
  611. [
  612. [-4, 6, 7, -1],
  613. [5, 5, -5, -1],
  614. [6, 5, -4, -3],
  615. ],
  616. [
  617. [-2, -1, -4, -3],
  618. [-5, 5, -4, -3],
  619. [1, -1, 1, -2],
  620. ],
  621. [
  622. [1],
  623. [5, 3, 6],
  624. [3, -2],
  625. ],
  626. [
  627. [7, 6, 6],
  628. [3, 2],
  629. [4],
  630. ],
  631. [
  632. [-3, 4, 5, 6],
  633. [-6, -1],
  634. [5, 6, 4],
  635. ],
  636. [
  637. [5, 6, 7, 6, 5, 6],
  638. [-5, -5, -1, 2, 4, 6, 5],
  639. [5, 5, 5, -6, -6, -4, 3],
  640. ],
  641. [
  642. [10, 20, 30, 40],
  643. [-4, 5, 6, -4, 3],
  644. [-3, -3, -2, 1, 5],
  645. ],
  646. [
  647. [4, 8, 12, 16, 20],
  648. [-5, 10, -15, 20, -55],
  649. [3, 6, 9, -12, -15],
  650. ],
  651. [
  652. [0, 0, 0, 0, 5],
  653. [4, 3, 6, 7],
  654. [6, 0, 0, 0, 0],
  655. ],
  656. [
  657. [2, 0, 0, 0, 4],
  658. [1, 1, 1, 1, 1],
  659. [2, 2, 2, -3, -2]
  660. ],
  661. [
  662. [1, 2, 3, 4, 5, 6, 7, 8, 9],
  663. [-1, -2, -3, -4, -5, -6, -7, -8, -9],
  664. [4, 3, 5, 6],
  665. ],
  666. [
  667. [1, 2, 3, 4, 5, 6, 7, 8, 9],
  668. [2, 3, 4, 5, 6, 7, 8, 9, 10],
  669. [3, 4, 5, 6, 7, 8, 9, 10, 11],
  670. ],
  671. [
  672. [34, 65, 34, 23, 62, 87, 34, 65],
  673. [4, 54, 23, -34, 12, 73, -34, 2],
  674. [34, 23, 12, 63, 24, -42, 12, 4],
  675. ],
  676. [
  677. [1, 2, 3, 4, 5, 6],
  678. [-1, -2, -3, -4, -6],
  679. [0, 0, 0, 0, 0, 0],
  680. ],
  681. ];
  682. }
  683. }