php/Math   
Recreational Mathematics   
   home  |  build01  |  build02  |  site news  |  contact
 Math Notes
 Math Programming [19]
 Regression [3]
 Data Mining [17]
 Notation [6]
 Linear Algebra [8]
 Stats & Prob [14]
 Math Cognition [5]
 Space & Physics [6]
 Formulas [5]
 Fun & Games [2]
 Haskell [1]
 Bayes Theory [1]
 Site News [1]
 Math Projects [4]
 Polynomials [1]
 Calculus [9]
 Number Theory [3]
 Optimization [2]

 Math Links
 Andrew Gelman
 Chance Wiki
 Daniel Lemire
 Jay Pipes
 KD Knuggets
 Social Stats
 MySQL Performance
 Damien François
 Hunch.net
 Matthew Hurst
 JMLR
 JSS
 Hal Daume III
 Math Notes >> Permanent Link

Variations on Simpson's rule [Regression
Posted on May 8, 2007 @ 10:29:09 PM by Paul Meagher

Understanding Simpson's rule can be difficult if you are laboring under the assumption that there is only one version of it. In fact, there are at least 4 basic versions of Simpson's rule: quadratic, cubic, adaptive, and composite. I implemented each of these variants as methods in a class file called Math_Integration_Simpson.php.

<?php
/**
* @package  Math_Integration
* @filepath Math/Integration/Simpson.php
*
* A numerical intergration class implementing 4 variants of 
* Simpson's rule. 
*
* Rule of thumb:

* If the function is smooth, Simpson's rule is better.
* If the function has abrupt changes, then Trapezoid is better.
*
* @author   Paul Meagher
* @version  0.1
* @license  LGPL
* @modified May 10, 2007
*
* @see http://math.fullerton.edu/mathews/n2003/NewtonCotesMod.html
* @see http://en.wikipedia.org/wiki/Adaptive_Simpson's_method
* @see http://www.cs.queensu.ca/~daver/271/Notes.pdf
*/
class Math_Integration_Simpson {
      
  
/**   
  * Approximation of f by a quadratic polynomial (i.e., uses three 
  * weighted points). x0 as a, x2 as b and x1 as 1/2 distance 
  * between a and b.  This is the most basic form of Simpson's 
  * rule and a favorite among textbook authors - also known as 
  * Simpson's one-third rule.    
  */
  
public function quadratic($f$a$b) {
    
$c = ($a+$b)/2.0;
    
$h abs($b-$a)/6.0;
    return 
$h*($f->valueAt($a) + 4.0*$f->valueAt($c) + $f->valueAt($b));
  }
  
  
/**    
  * Approximation f by a cubic polynomial (i.e., uses four 
  * weighted points). x0 as a, x3 as b and x1 and x2 as 1/3 and 
  * 2/3 distances between a and b.  Also known as Simpson's 
  * three-eights rule.
  */
  
public function cubic($f$a$b) { 
   
$h abs($b-$a)*(1.0/3.0);
   
$c $a $h;
   
$d $b $h;
   return (
3.0*$h/8.0)*($f->valueAt($a) + 3.0*$f->valueAt($c)+ 3.0*$f->valueAt($d)+ $f->valueAt($b));
  }

  
/**
  * Recursive implementation of adaptive Simpson's rule.
  */
  
private function recursive($f$a$b$eps$sum) {
    
$c     = ($a+$b)/2.0;
    
$left  $this->quadratic($f$a$c);
    
$right $this->quadratic($f$c$b);
    if (
abs($left $right $sum) <= (15 $eps))
      return 
$left $right + ($left $right $sum)/15;
    return 
$this->recursive($f$a$c$eps/2$left) + $this->recursive($f$c$b$eps/2$right);
  }

  
/**
  * Calculate integral of f from a to b using adaptive Simpson's rule 
  * with max error of eps.
  */
  
public function adaptive($f$a$b$eps=0.000001) {
    return 
$this->recursive($f$a$b$eps$this->quadratic($f$a$b));
  }

  
/**
  * Calculate integral of f from a to b using a piecewise approach. This 
  * form is commonly used to estimate the integral with $n used to control
  * the accuracy of the estimate.
  */  
  
public function composite($f$a$b$n=10) {
    
$h  = ($b-$a)/(2.0*$n);    
    
$s1 = ($f->valueAt($a)+ $f->valueAt($b));
    for(
$i=1$i<2*$n$i=$i+2
      
$s2 $s2 $f->valueAt($a $i*$h);
    for(
$i=2$i<2*$n$i=$i+2
      
$s3 $s3 $f->valueAt($a $i*$h);
    return (
$h/3.0)*($s14.0*$s2 2.0*$s3);
  }

}
?>

The following simpson_methods.php script executes each of the methods defined in this class.

<?php

include "Math/Integration/Simpson.php";

class 
{
  function 
valueAt($x) {
    return 
4.0/(1.0+$x*$x);
  }
  function 
toString() {
    return 
"4.0/(1.0+x^2)";
  }
  function 
toHTML() {
    return 
"4.0/(1.0+x<sup>2</sup>)";
  }
}

$f = new F;
$a 0;
$b 1;

$simpson = new Math_Integration_Simpson;

$quadratic $simpson->quadratic($f$a$b);
$cubic     $simpson->cubic($f$a$b);
$adaptive  $simpson->adaptive($f$a$b);
$composite $simpson->composite($f$a$b);

echo 
"quadratic method: $quadratic <br />";
echo 
"cubic method: $cubic <br />";
echo 
"adaptive method: $adaptive <br />";
echo 
"composite method: $composite <br />";

?>

Each method in the script generates a π estimate:

quadratic method: 3.13333333333 
cubic method: 3.13846153846 
adaptive method: 3.14159265371 
composite method: 3.14159265297 

The method producing the output closest to an exact π value of 3.1415926535 is the adaptive method, beating out the composite method by a tiny margin.

Other classes that might be found in a Math_Integration package include:

  • Math_Integration_Trapezoid.php
  • Math_Integration_Gaussian.php (i.e., gaussian quadrature)
  • Math_Integration_Romberg.php

All would have basic, adaptive, and composite variants.

Exercises

1. Play around with the $eps parameter in the adaptive Simpson's rule and the $n parameter in the composite Simpson's rule. Can the composite method be made to out perform the adaptive method in computing π?

2. Apply these methods to a variety of other functions and note any differences.

3. Implement a Math_Integration_Trapezoid.php class that contains a basic, adaptive, and composite implementation of the trapezoid method of integration.

4. Compare the relative performance of Simpson's rule to the Trapezoid method of integration on functions that are smooth or contain abrupt changes.

5. How do Lagrange polynomials relate to Simpson's rule?

6. How do the Newton-Cotes formulas relate to Simpson's rule and other methods of integration?

Permalink 

No comments entered ...

 Archive 
 

php/Math Project
© 2007. All rights reserved.