/**
  * Ralston and Rabinowitz method for calculate double root (twin root).
  *
  * @param callback $fxFunction Callback f(x) equation function or
  *                             object/method tuple.
  * @param callback $dxFunction Callback f'(x) equation function or
  *                             object/method tuple.
  * @param float $xR0 First initial guess.
  * @param float $xR1 Second initial guess.
  *
  * @return float|PEAR_Error Root value on success or PEAR_Error on failure.
  * @access public
  * @see Math_Numerical_RootFinding_Common::validateEqFunction()
  * @see Math_Numerical_RootFinding_Common::getEqResult()
  * @see Math_Numerical_RootFinding_Common::isDivergentRow()
  * @see Math_Numerical_RootFinding_Secant::compute()
  */
 function compute($fxFunction, $dxFunction, $xR0, $xR1)
 {
     // Validate f(x) equation function.
     $err = Math_Numerical_RootFinding_Common::validateEqFunction($fxFunction);
     if (PEAR::isError($err)) {
         return $err;
     }
     // Validate f'(x) equation function.
     $err = Math_Numerical_RootFinding_Common::validateEqFunction($dxFunction);
     if (PEAR::isError($err)) {
         return $err;
     }
     // Sets maximum iteration and tolerance from options.
     $maxIteration = $this->options['max_iteration'];
     $errTolerance = $this->options['err_tolerance'];
     // Sets variable for saving errors during iteration, for divergent
     // detection.
     $epsErrors = array();
     for ($i = 1; $i <= $maxIteration; $i++) {
         // Calculate f(x[i-1]) and f'(x[1]), where: x[i-1] = $xR0.
         $fxR0 = Math_Numerical_RootFinding_Common::getEqResult($fxFunction, $xR0);
         $dxR0 = Math_Numerical_RootFinding_Common::getEqResult($dxFunction, $xR0);
         // Calculate f(x[i]) and f'(x[1]), where: x[i] = $xR1.
         $fxR1 = Math_Numerical_RootFinding_Common::getEqResult($fxFunction, $xR1);
         $dxR1 = Math_Numerical_RootFinding_Common::getEqResult($dxFunction, $xR1);
         // Calculate f(x[i-1]) / f'(x[i-1], where x[i-1] = $xR0.
         $uxR0 = $fxR0 / $dxR0;
         // Calculate f(x[i]) / f'(x[i]), where x[i] = $xR1;
         $uxR1 = $fxR1 / $dxR1;
         // Avoid division by zero.
         if ($uxR0 - $uxR1 == 0) {
             return PEAR::raiseError('Iteration skipped division by zero');
         }
         // Ralston and Rabinowitz's formula.
         $xN = $xR1 - $uxR1 * ($xR0 - $xR1) / ($uxR0 - $uxR1);
         // xR is the root.
         if ($xN == 0) {
             $this->root = $xR;
             break;
         }
         // Compute error.
         $this->epsError = abs(($xN - $xR1) / $xN);
         $epsErrors[] = $this->epsError;
         // Detect for divergent rows.
         if ($this->isDivergentRows($epsErrors) && $this->options['divergent_skip']) {
             return PEAR::raiseError('Iteration skipped, divergent rows detected');
             break;
         }
         // Check for error tolerance, if lower than or equal with
         // $errTolerance it is the root.
         if ($this->epsError <= $errTolerance) {
             $this->root = $xR1;
             break;
         }
         // Swicth the values for next iteration x[i] -> x[i-1] and
         // x[i+1] -> x[i], where: x[i-1] = $xR0, x[i] = $xR1, and
         // x[i+1] = $xN.
         $xR0 = $xR1;
         $xR1 = $xN;
     }
     $this->iterationCount = $i;
     return $this->root;
 }
 /**
  * Netwon-Raphson method.
  *
  * @param callback $fxFunction  Callback f(x) equation function or object/method
  *                              tuple.
  * @param callback $dfxFunction Callback f'(x) equation function or object/method
  *                              tuple.
  * @param float    $xR          Initial guess.
  *
  * @return float|PEAR_Error Root value on success or PEAR_Error on failure.
  * @access public
  * @see Math_Numerical_RootFinding_Common::validateEqFunction()
  * @see Math_Numerical_RootFinding_Common::getEqResult()
  * @see Math_Numerical_RootFinding_Common::isDivergentRow()
  * @see Math_Numerical_RootFinding_NewtonRaphson2::compute()
  */
 public function compute($fxFunction, $dfxFunction, $xR)
 {
     // evaluate f(x) equation function before begin anything
     parent::validateEqFunction($fxFunction, $xR);
     // evaluate df(x) equation function before begin anything
     parent::validateEqFunction($dfxFunction, $xR);
     // Sets maximum iteration and tolerance from options.
     $maxIteration = $this->options['max_iteration'];
     $errTolerance = $this->options['err_tolerance'];
     // Sets variable for saving errors during iteration, for divergent
     // detection.
     $epsErrors = array();
     for ($i = 1; $i < $maxIteration; $i++) {
         // Calculate f(x[i]), where: x[i] = $xR.
         $fxR = parent::getEqResult($fxFunction, $xR);
         // Calculate f'(x[i]), where: x[i] = $xR.
         $dxR = parent::getEqResult($dfxFunction, $xR);
         // Avoid division by zero.
         if ($dxR == 0) {
             throw new \Exception('Iteration skipped, division by zero');
         }
         // Newton-Raphson's formula.
         $xN = $xR - $fxR / $dxR;
         // xR is the root.
         if ($xN == 0) {
             $this->root = $xR;
             break;
         }
         // Compute error.
         $this->epsError = abs(($xN - $xR) / $xN);
         $epsErrors[] = $this->epsError;
         // Detect for divergent rows.
         if ($this->isDivergentRows($epsErrors) && $this->options['divergent_skip']) {
             throw new \Exception('Iteration skipped, divergent rows detected');
             break;
         }
         // Check for error tolerance, if lower than or equal with
         // $errTolerance it is the root.
         if ($this->epsError <= $errTolerance) {
             $this->root = $xR;
             break;
         }
         // Switch x[i+1] -> x[i], where: x[i] = $xR and x[i+1] = $xN.
         $xR = $xN;
     }
     $this->iterationCount = $i;
     return $this->root;
 }
 /**
  * Bisection/Binary Chopping/Interval Halving/Bolzano method.
  *
  * @param callback $fxFunction Callback f(x) equation function or
  *                             object/method tuple.
  * @param float $xL Lower guess.
  * @param float $xU Upper guess.
  *
  * @return float|PEAR_Error Root value on success or PEAR_Error on failure.
  * @access public
  * @see Math_Numerical_RootFinding::validateEqFunction()
  * @see Math_Numerical_RootFinding::getEqResult()
  * @see Math_Numerical_RootFinding_Falseposition::compute()
  */
 function compute($fxFunction, $xL, $xU)
 {
     // Validate f(x) equation function.
     $err = Math_Numerical_RootFinding_Common::validateEqFunction($fxFunction);
     if (PEAR::isError($err)) {
         return $err;
     }
     // Sets first approximation $xR (Bisection's formula).
     $xR = ($xU + $xL) / 2;
     // Validate f(x) equation function.
     $err = Math_Numerical_RootFinding_Common::validateEqFunction($fxFunction);
     if (PEAR::isError($err)) {
         return $err;
     }
     // Sets maximum iteration and tolerance from options.
     $maxIteration = $this->options['max_iteration'];
     $errTolerance = $this->options['err_tolerance'];
     // Sets variable for saving errors during iteration, for divergent
     // detection.
     $epsErrors = array();
     for ($i = 0; $i < $maxIteration; $i++) {
         // Calculate f(x), where: x = xL and x = xR
         $fxL = Math_Numerical_RootFinding_Common::getEqResult($fxFunction, $xL);
         $fxR = Math_Numerical_RootFinding_Common::getEqResult($fxFunction, $xR);
         if ($fxL * $fxR < 0) {
             // Root is at first subinterval.
             $xU = $xR;
         } elseif ($fxL * $fxR > 0) {
             // Root is at second subinterval.
             $xL = $xR;
         } elseif ($fxL * $fxR == 0) {
             // $xR is the exact root.
             $this->root = $xR;
             break;
         }
         // Compute new approximation.
         $xN = ($xL + $xU) / 2;
         // Compute approximation error.
         $this->epsError = abs(($xN - $xR) / $xN);
         $epsErrors[] = $this->epsError;
         // Detect for divergent rows.
         if ($this->isDivergentRows($epsErrors) && $this->options['divergent_skip']) {
             return PEAR::raiseError('Iteration skipped, divergent rows detected');
             break;
         }
         // Check for error tolerance, if lower than or equal with
         // $errTolerance it is the root.
         if ($this->epsError <= $errTolerance) {
             $this->root = $xN;
             break;
         }
         // Switch xn -> xr, where xn = $xN and xr = $xR.
         $xR = $xN;
     }
     $this->iterationCount = $i;
     return $this->root;
 }
 /**
  * Fixed Point method.
  *
  * This method using g(x) (the modification of f(x), which g(x) = x).
  *
  * @param callback $gxFunction Callback g(x) equation function or object/method
  *                             tuple.
  * @param float    $xR         Initial guess.
  *
  * @return float|PEAR_Error Root value on success or PEAR_Error on failure.
  * @access public
  * @see Math_Numerical_RootFinding_Common::validateEqFunction()
  * @see Math_Numerical_RootFinding_Common::getEqResult()
  * @see Math_Numerical_RootFinding_Common::isDivergentRow()
  */
 public function compute($gxFunction, $xR)
 {
     // Validate g(x) equation function.
     parent::validateEqFunction($gxFunction, $xR);
     // Sets maximum iteration and tolerance from options.
     $maxIteration = $this->options['max_iteration'];
     $errTolerance = $this->options['err_tolerance'];
     // Sets variable for saving errors during iteration, for divergent
     // detection.
     $epsErrors = array();
     for ($i = 0; $i < $maxIteration; $i++) {
         // Calculate g(x[i]), where x[i] = $xR (Fixed Point's formula).
         $xN = parent::getEqResult($gxFunction, $xR);
         // xR is the root.
         if ($xN == 0) {
             $this->root = $xR;
             break;
         }
         // Compute error.
         $this->epsError = abs(($xN - $xR) / $xN);
         $epsErrors[] = $this->epsError;
         // Detect for divergent rows.
         if ($this->isDivergentRows($epsErrors) && $this->options['divergent_skip']) {
             throw new \Exception('Iteration skipped, divergent rows detected');
             break;
         }
         // Check for error tolerance, if lower than or equal with
         // $errTolerance it is the root.
         if ($this->epsError <= $errTolerance) {
             $this->root = $xR;
             break;
         }
         // Switch x[i+1] -> x[i], where: x[i] = $xR and x[i+1] = $xN.
         $xR = $xN;
     }
     $this->iterationCount = $i;
     return $this->root;
 }
Example #5
0
 /**
  * Newton-Raphson method for calculate double root (twin root).
  *
  * @param callback $fxFunction Callback f(x) equation function or
  *                             object/method tuple.
  * @param callback $dfx1Function Callback f'(x) equation function or
  *                              object/method tuple.
  * @param callback $dfx2Function Callback f''(x) equation function or
  *                              object/method tuple.
  * @param float $xR Initial guess.
  *
  * @return float|PEAR_Error Root value on success or PEAR_Error on failure.
  * @access public
  * @see Math_Numerical_RootFinding_Common::validateEqFunction()
  * @see Math_Numerical_RootFinding_Common::getEqResult()
  * @see Math_Numerical_RootFinding_Common::isDivergentRow()
  * @see Math_Numerical_RootFinding_Newtonraphson::compute()
  */
 function compute($fxFunction, $dfx1Function, $dfx2Function, $xR)
 {
     // Validate f(x) equation function.
     $err = Math_Numerical_RootFinding_Common::validateEqFunction($fxFunction);
     if (PEAR::isError($err)) {
         return $err;
     }
     // Validate f'(x) equation function.
     $err = Math_Numerical_RootFinding_Common::validateEqFunction($dfx1Function);
     if (PEAR::isError($err)) {
         return $err;
     }
     // Validate f''(x) equation function.
     $err = Math_Numerical_RootFinding_Common::validateEqFunction($dfx2Function);
     if (PEAR::isError($err)) {
         return $err;
     }
     // Sets maximum iteration and tolerance from options.
     $maxIteration = $this->options['max_iteration'];
     $errTolerance = $this->options['err_tolerance'];
     // Sets variable for saving errors during iteration, for divergent
     // detection.
     $epsErrors = array();
     for ($i = 1; $i < $maxIteration; $i++) {
         // Calculate f(x[i]), where: x[i] = $xR.
         $fxR = Math_Numerical_RootFinding_Common::getEqResult($fxFunction, $xR);
         // Calculate f'(x[i]), where: x[i] = $xR.
         $d1xR = Math_Numerical_RootFinding_Common::getEqResult($dfx1Function, $xR);
         // Calculate f''(x[i]), where: x[i] = $xR.
         $d2xR = Math_Numerical_RootFinding_Common::getEqResult($dfx2Function, $xR);
         // Avoid division by zero.
         if (pow($d1xR, 2) - $fxR * $d2xR == 0) {
             return PEAR::raiseError('Iteration skipped, division by zero');
         }
         // Newton-Raphson's formula.
         $xN = $xR - $fxR * $d1xR / (pow($d1xR, 2) - $fxR * $d2xR);
         // xR is the root.
         if ($xN == 0) {
             $this->root = $xR;
             break;
         }
         // Compute error.
         $this->epsError = abs(($xN - $xR) / $xN);
         $epsErrors[] = $this->epsError;
         // Detect for divergent rows.
         if ($this->isDivergentRows($epsErrors) && $this->options['divergent_skip']) {
             return PEAR::raiseError('Iteration skipped, divergent rows detected');
             break;
         }
         // Check for error tolerance, if lower than or equal with
         // $errTolerance it is the root.
         if ($this->epsError <= $errTolerance) {
             $this->root = $xR;
             break;
         }
         // Switch x[i+1] -> x[i], where: x[i] = $xR and x[i+1] = $xN.
         $xR = $xN;
     }
     $this->iterationCount = $i;
     return $this->root;
 }
 /**
  * Secant method.
  *
  * @param callback $fxFunction Callback f(x) equation function or object/method
  *                             tuple.
  * @param float    $xR0        First initial guess.
  * @param float    $xR1        Second initial guess.
  *
  * @return float|PEAR_Error Root value on success or PEAR_Error on failure.
  * @access public
  * @see Math_Numerical_RootFinding_Common::validateEqFunction()
  * @see Math_Numerical_RootFinding_Common::getEqResult()
  * @see Math_Numerical_RootFinding_Common::isDivergentRow()
  * @see Math_Numerical_RootFinding_Ralstonrabinowitz::compute()
  */
 public function compute($fxFunction, $xR0, $xR1)
 {
     // Validate f(x) equation function.
     parent::validateEqFunction($fxFunction, $xR0);
     // Sets maximum iteration and tolerance from options.
     $maxIteration = $this->options['max_iteration'];
     $errTolerance = $this->options['err_tolerance'];
     // Sets variable for saving errors during iteration, for divergent
     // detection.
     $epsErrors = array();
     for ($i = 1; $i <= $maxIteration; $i++) {
         // Calculate f(x[i-1]), where: x[i-1] = $xR0.
         $fxR0 = parent::getEqResult($fxFunction, $xR0);
         // Calculate f(x[i]), where: x[i] = $xR1.
         $fxR1 = parent::getEqResult($fxFunction, $xR1);
         // Avoid division by zero.
         if ($fxR0 - $fxR1 == 0) {
             throw new \Exception('Iteration skipped division by zero');
         }
         // Secant's formula.
         $xN = $xR1 - $fxR1 * ($xR0 - $xR1) / ($fxR0 - $fxR1);
         // xR is the root.
         if ($xN == 0) {
             $this->root = $xR;
             break;
         }
         // Compute error.
         $this->epsError = abs(($xN - $xR1) / $xN);
         $epsErrors[] = $this->epsError;
         // Detect for divergent rows.
         if ($this->isDivergentRows($epsErrors) && $this->options['divergent_skip']) {
             throw new \Exception('Iteration skipped, divergent rows detected');
             break;
         }
         // Check for error tolerance, if lower than or equal with
         // $errTolerance it is the root.
         if ($this->epsError <= $errTolerance) {
             $this->root = $xR1;
             break;
         }
         // Swicth the values for next iteration x[i] -> x[i-1] and
         // x[i+1] -> x[i], where: x[i-1] = $xR0, x[i] = $xR1, and
         // x[i+1] = $xN.
         $xR0 = $xR1;
         $xR1 = $xN;
     }
     $this->iterationCount = $i;
     return $this->root;
 }
 /**
  * Validate equation function or object/method.
  *
  * Simple function to know the whether equation function or object/method
  * callback is working.
  *
  * @param string $eqFunction Equation function name or object method tuple.
  *
  * @return bool|PEAR_Error TRUE on success or PEAR_Error on failure.
  * @access public
  * @see getEqResult()
  * @static
  */
 function validateEqFunction($eqFunction)
 {
     $err = Math_Numerical_RootFinding_Common::getEqResult($eqFunction, 1);
     if (PEAR::isError($err)) {
         return $err;
     }
     return true;
 }
 /**
  * False Position/Regula Falsi method.
  *
  * @param callback $fxFunction Callback f(x) equation function or
  *                             object/method tuple.
  * @param float    $xL         Lower guess.
  * @param float    $xU         Upper guess.
  *
  * @return float|PEAR_Error Root value on success or PEAR_Error on failure.
  * @access public
  * @see Math_Numerical_RootFinding_Common::validateEqFunction()
  * @see Math_Numerical_RootFinding_Common::getEqResult()
  * @see Math_Numerical_RootFinding_Bisection::compute()
  */
 public function compute($fxFunction, $xL, $xU)
 {
     // Validate f(x) equation function.
     parent::validateEqFunction($fxFunction, $xL);
     // Sets maximum iteration and tolerance from options.
     $maxIteration = $this->options['max_iteration'];
     $errTolerance = $this->options['err_tolerance'];
     // Calculate first approximation $xR (False Position's formula).
     $fxL = parent::getEqResult($fxFunction, $xL);
     $fxU = parent::getEqResult($fxFunction, $xU);
     if ($fxL - $fxU == 0) {
         throw new \Exception('Iteration skipped, division by zero');
     }
     $xR = $xU - $fxU * ($xL - $xU) / ($fxL - $fxU);
     // Sets variable for saving errors during iteration, for divergent
     // detection.
     $epsErrors = array();
     for ($i = 0; $i < $maxIteration; $i++) {
         // Calculate f(xr), where: xr = $xR
         $fxR = parent::getEqResult($fxFunction, $xR);
         if ($fxL * $fxR < 0) {
             // Root is at first subinterval.
             $xU = $xR;
         } elseif ($fxL * $fxR > 0) {
             // Root is at second subinterval.
             $xL = $xR;
         } elseif ($fxL * $fxR == 0) {
             // $xR is the exact root.
             $this->root = $xR;
             break;
         }
         // Avoid division by zero.
         if ($fxL - $fxU == 0) {
             throw new \Exception('Iteration skipped, division by zero');
         }
         // Compute new approximation.
         $xN = $xU - $fxU * ($xL - $xU) / ($fxL - $fxU);
         // Compute approximation error.
         $this->epsError = abs(($xN - $xR) / $xN);
         $epsErrors[] = $this->epsError;
         // Detect for divergent rows.
         if ($this->isDivergentRows($epsErrors) && $this->options['divergent_skip']) {
             throw new \Exception('Iteration skipped, divergent rows detected');
             break;
         }
         // Check for error tolerance, if lower than or equal with
         // $errTolerance it is the root.
         if ($this->epsError <= $errTolerance) {
             $this->root = $xN;
             break;
         }
         // Calculate f(xl), where xl = $xL.
         $fxL = parent::getEqResult($fxFunction, $xL);
         // Calculate f(xu), where xu = $xU.
         $fxU = parent::getEqResult($fxFunction, $xU);
         // Switch xn -> xr, where xn = $xN and xr = $xR.
         $xR = $xN;
     }
     $this->iterationCount = $i;
     return $this->root;
 }