RectangleMethodTest.php 6.7 KB

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