MidpointRuleTest.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <?php
  2. namespace MathPHP\Tests\NumericalAnalysis\NumericalIntegration;
  3. use MathPHP\Expression\Polynomial;
  4. use MathPHP\NumericalAnalysis\NumericalIntegration\MidpointRule;
  5. class MidpointRuleTest extends \PHPUnit\Framework\TestCase
  6. {
  7. /**
  8. * @test approximate with endpoints: (0, 1) and (3, 16)
  9. * @throws \Exception
  10. *
  11. * f(x) = -x² + 2x + 1
  12. * Antiderivative F(x) = -(1/3)x³ + x² + x
  13. * Indefinite integral over [0, 3] = F(3) - F(0) = 3
  14. *
  15. * h₁, h₂, ... denotes the size on interval 1, 2, ...
  16. * ζ₁, ζ₂, ... denotes the max of the second derivative of f(x) on
  17. * interval 1, 2, ...
  18. * f'(x) = -2x + 2
  19. * f''(x) = -2
  20. * ζ = |f''(x)| = 2
  21. * Error = Sum(ζ₁h₁³ + ζ₂h₂³ + ...) = 2 * Sum(h₁³ + h₂³ + ...)
  22. *
  23. * Approximate with endpoints: (0, 1) and (3, 16)
  24. * Error = 2 * ((3 - 0)²) = 18
  25. */
  26. public function testApproximateEndpoints()
  27. {
  28. // Given
  29. $endpoints = [[0, 1], [3, -2]];
  30. $expected = 3;
  31. $tol = 18;
  32. // When
  33. $x = MidpointRule::approximate($endpoints);
  34. // Then
  35. $this->assertEqualsWithDelta($expected, $x, $tol);
  36. }
  37. /**
  38. * @test approximate with endpoints: endpoints and one interior point: (0, 1), (1, 4), and (3, 16)
  39. * @throws \Exception
  40. *
  41. * f(x) = -x² + 2x + 1
  42. * Antiderivative F(x) = -(1/3)x³ + x² + x
  43. * Indefinite integral over [0, 3] = F(3) - F(0) = 3
  44. *
  45. * h₁, h₂, ... denotes the size on interval 1, 2, ...
  46. * ζ₁, ζ₂, ... denotes the max of the second derivative of f(x) on
  47. * interval 1, 2, ...
  48. * f'(x) = -2x + 2
  49. * f''(x) = -2
  50. * ζ = |f''(x)| = 2
  51. * Error = Sum(ζ₁h₁³ + ζ₂h₂³ + ...) = 2 * Sum(h₁³ + h₂³ + ...)
  52. *
  53. * Approximate endpoints and one interior point: (0, 1), (1, 4), and (3, 16)
  54. * Error = 2 * ((3 - 0)²) = 18
  55. */
  56. public function testApproximateEndpointsOneInteriorPoint()
  57. {
  58. // Given
  59. $points = [[0, 1], [1, 2], [3, -2]];
  60. $expected = 3;
  61. $tol = 10;
  62. // When
  63. $x = MidpointRule::approximate($points);
  64. // Then
  65. $this->assertEqualsWithDelta($expected, $x, $tol);
  66. }
  67. /**
  68. * @test approximate with endpoints: endpoints and two interior points: (0, 1), (1, 4), (2, 9), and (3, 16)
  69. * @throws \Exception
  70. *
  71. * f(x) = -x² + 2x + 1
  72. * Antiderivative F(x) = -(1/3)x³ + x² + x
  73. * Indefinite integral over [0, 3] = F(3) - F(0) = 3
  74. *
  75. * h₁, h₂, ... denotes the size on interval 1, 2, ...
  76. * ζ₁, ζ₂, ... denotes the max of the second derivative of f(x) on
  77. * interval 1, 2, ...
  78. * f'(x) = -2x + 2
  79. * f''(x) = -2
  80. * ζ = |f''(x)| = 2
  81. * Error = Sum(ζ₁h₁³ + ζ₂h₂³ + ...) = 2 * Sum(h₁³ + h₂³ + ...)
  82. *
  83. * Approximate endpoints and two interior points: (0, 1), (1, 4), (2, 9), and (3, 16)
  84. * Error = 2 * ((1 - 0)² + (2 - 1)² + (3 - 2)²) = 6
  85. */
  86. public function testApproximateEndpointsTwoInteriorPoints()
  87. {
  88. // Given
  89. $points = [[0, 1], [1, 2], [2, 1], [3, -2]];
  90. $expected = 3;
  91. $tol = 6;
  92. // When
  93. $x = MidpointRule::approximate($points);
  94. // Then
  95. $this->assertEqualsWithDelta($expected, $x, $tol);
  96. }
  97. /**
  98. * @test approximate with endpoints: endpoints and two interior points: (0, 1), (1, 4), (2, 9), and (3, 16)
  99. * @throws \Exception
  100. *
  101. * f(x) = -x² + 2x + 1
  102. * Antiderivative F(x) = -(1/3)x³ + x² + x
  103. * Indefinite integral over [0, 3] = F(3) - F(0) = 3
  104. *
  105. * h₁, h₂, ... denotes the size on interval 1, 2, ...
  106. * ζ₁, ζ₂, ... denotes the max of the second derivative of f(x) on
  107. * interval 1, 2, ...
  108. * f'(x) = -2x + 2
  109. * f''(x) = -2
  110. * ζ = |f''(x)| = 2
  111. * Error = Sum(ζ₁h₁³ + ζ₂h₂³ + ...) = 2 * Sum(h₁³ + h₂³ + ...)
  112. *
  113. * Approximate endpoints and two interior points: (0, 1), (1, 4), (2, 9), and (3, 16)
  114. * Error = 2 * ((1 - 0)² + (2 - 1)² + (3 - 2)²) = 6
  115. */
  116. public function testApproximateEndpointsTwoInteriorPointsNotSorted()
  117. {
  118. // Given
  119. $points = [[1, 2], [3, -2], [0, 1], [2, 1]];
  120. $expected = 3;
  121. $tol = 6;
  122. // When
  123. $x = MidpointRule::approximate($points);
  124. // Then
  125. $this->assertEqualsWithDelta($expected, $x, $tol);
  126. }
  127. /**
  128. * @test approximate with callback
  129. * @throws \Exception
  130. *
  131. * f(x) = -x² + 2x + 1
  132. * Antiderivative F(x) = -(1/3)x³ + x² + x
  133. * Indefinite integral over [0, 3] = F(3) - F(0) = 3
  134. *
  135. * h₁, h₂, ... denotes the size on interval 1, 2, ...
  136. * ζ₁, ζ₂, ... denotes the max of the second derivative of f(x) on
  137. * interval 1, 2, ...
  138. * f'(x) = -2x + 2
  139. * f''(x) = -2
  140. * ζ = |f''(x)| = 2
  141. * Error = Sum(ζ₁h₁³ + ζ₂h₂³ + ...) = 2 * Sum(h₁³ + h₂³ + ...)
  142. *
  143. * Approximate with endpoints: (0, 1) and (3, 16)
  144. * Error = 2 * ((3 - 0)²) = 18
  145. */
  146. public function testApproximateUsingCallback()
  147. {
  148. // Given -x² + 2x + 1
  149. $func = function ($x) {
  150. return -$x ** 2 + 2 * $x + 1;
  151. };
  152. $start = 0;
  153. $end = 3;
  154. $n = 4;
  155. $tol = 6;
  156. $expected = 3;
  157. // When
  158. $x = MidpointRule::approximate($func, $start, $end, $n);
  159. // Then
  160. $this->assertEqualsWithDelta($expected, $x, $tol);
  161. }
  162. /**
  163. * @test approximate with polynomial
  164. * @throws \Exception
  165. *
  166. * f(x) = -x² + 2x + 1
  167. * Antiderivative F(x) = -(1/3)x³ + x² + x
  168. * Indefinite integral over [0, 3] = F(3) - F(0) = 3
  169. *
  170. * h₁, h₂, ... denotes the size on interval 1, 2, ...
  171. * ζ₁, ζ₂, ... denotes the max of the second derivative of f(x) on
  172. * interval 1, 2, ...
  173. * f'(x) = -2x + 2
  174. * f''(x) = -2
  175. * ζ = |f''(x)| = 2
  176. * Error = Sum(ζ₁h₁³ + ζ₂h₂³ + ...) = 2 * Sum(h₁³ + h₂³ + ...)
  177. *
  178. * Approximate with endpoints: (0, 1) and (3, 16)
  179. * Error = 2 * ((3 - 0)²) = 18
  180. */
  181. public function testApproximateUsingPolynomial()
  182. {
  183. // Given -x² + 2x + 1
  184. $polynomial = new Polynomial([-1, 2, 1]);
  185. $start = 0;
  186. $end = 3;
  187. $n = 4;
  188. $tol = 6;
  189. $expected = 3;
  190. // When
  191. $x = MidpointRule::approximate($polynomial, $start, $end, $n);
  192. // Then
  193. $this->assertEqualsWithDelta($expected, $x, $tol);
  194. }
  195. }