1 16 package org.apache.commons.math.analysis; 17 18 19 import org.apache.commons.math.ConvergenceException; 20 import org.apache.commons.math.FunctionEvaluationException; 21 22 30 public class BrentSolver extends UnivariateRealSolverImpl { 31 32 33 static final long serialVersionUID = 3350616277306882875L; 34 35 40 public BrentSolver(UnivariateRealFunction f) { 41 super(f, 100, 1E-6); 42 } 43 44 59 public double solve(double min, double max, double initial) 60 throws ConvergenceException, FunctionEvaluationException { 61 62 return solve(min, max); 63 } 64 65 81 public double solve(double min, double max) throws ConvergenceException, 82 FunctionEvaluationException { 83 84 clearResult(); 85 verifyInterval(min, max); 86 87 double x0 = min; 91 double x1 = max; 92 double y0; 93 double y1; 94 y0 = f.value(x0); 95 y1 = f.value(x1); 96 97 if (y0 * y1 >= 0) { 99 throw new IllegalArgumentException 100 ("Function values at endpoints do not have different signs." + 101 " Endpoints: [" + min + "," + max + "]" + 102 " Values: [" + y0 + "," + y1 + "]"); 103 } 104 105 double x2 = x0; 106 double y2 = y0; 107 double delta = x1 - x0; 108 double oldDelta = delta; 109 110 int i = 0; 111 while (i < maximalIterationCount) { 112 if (Math.abs(y2) < Math.abs(y1)) { 113 x0 = x1; 114 x1 = x2; 115 x2 = x0; 116 y0 = y1; 117 y1 = y2; 118 y2 = y0; 119 } 120 if (Math.abs(y1) <= functionValueAccuracy) { 121 setResult(x1, i); 125 return result; 126 } 127 double dx = (x2 - x1); 128 double tolerance = 129 Math.max(relativeAccuracy * Math.abs(x1), absoluteAccuracy); 130 if (Math.abs(dx) <= tolerance) { 131 setResult(x1, i); 132 return result; 133 } 134 if ((Math.abs(oldDelta) < tolerance) || 135 (Math.abs(y0) <= Math.abs(y1))) { 136 delta = 0.5 * dx; 138 oldDelta = delta; 139 } else { 140 double r3 = y1 / y0; 141 double p; 142 double p1; 143 if (x0 == x2) { 144 p = dx * r3; 146 p1 = 1.0 - r3; 147 } else { 148 double r1 = y0 / y2; 150 double r2 = y1 / y2; 151 p = r3 * (dx * r1 * (r1 - r2) - (x1 - x0) * (r2 - 1.0)); 152 p1 = (r1 - 1.0) * (r2 - 1.0) * (r3 - 1.0); 153 } 154 if (p > 0.0) { 155 p1 = -p1; 156 } else { 157 p = -p; 158 } 159 if (2.0 * p >= 1.5 * dx * p1 - Math.abs(tolerance * p1) || 160 p >= Math.abs(0.5 * oldDelta * p1)) { 161 delta = 0.5 * dx; 165 oldDelta = delta; 166 } else { 167 oldDelta = delta; 168 delta = p / p1; 169 } 170 } 171 x0 = x1; 173 y0 = y1; 174 if (Math.abs(delta) > tolerance) { 176 x1 = x1 + delta; 177 } else if (dx > 0.0) { 178 x1 = x1 + 0.5 * tolerance; 179 } else if (dx <= 0.0) { 180 x1 = x1 - 0.5 * tolerance; 181 } 182 y1 = f.value(x1); 183 if ((y1 > 0) == (y2 > 0)) { 184 x2 = x0; 185 y2 = y0; 186 delta = x1 - x0; 187 oldDelta = delta; 188 } 189 i++; 190 } 191 throw new ConvergenceException("Maximum number of iterations exceeded."); 192 } 193 } 194 | Popular Tags |