/** * 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; }
/** * 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; }