def find_root (   self,
  lower_bracket,
  upper_bracket,
  start,
  value,
  trace = False 
)

solve f(x)==value very efficiently, with explicit knowledge of derivatives of the function find_root solves by iterated inverse quadratic extrapolation for a solution to f(x)=y. It includes checks against bad convergence, so it should never be able to fail. Unlike typical secant method or fancier Brent's method finders, this does not depend in any strong wasy on the brackets, unless the finder has to resort to successive approximations to close in on a root. Often, it is possible to make the brackets equal to the domain of the function, if there is any clue as to where the root lies, as given by the parameter start.

Parameters:
lower_bracket the lower bound which is ever permitted in the search.
upper_bracket the upper bound. Note that the function have opposite signs at these two points
start an initial guess for where to start the search
value the target value of the function
trace print debugging info to sys.stderr if True

Definition at line 157 of file C2Functions.py.

00157                                                                                 : 
00158         "solve f(x)==value very efficiently, with explicit knowledge of derivatives of the function"
00159         # can use local f(x)=a*x**2 + b*x + c 
00160         # and solve quadratic to find root, then iterate
00161 
00162         ftol=(5e-16*abs(value)+2e-308);
00163         xtol=(5e-16*(abs(upper_bracket)+abs(lower_bracket))+2e-308);
00164 
00165         root=start  #start looking in the middle
00166         cupper, yp, ypp=self.value_with_derivatives(upper_bracket)
00167         cupper -= value
00168         if abs(cupper) < ftol: return upper_bracket
00169         clower, yp, ypp=self.value_with_derivatives(lower_bracket)
00170         clower -= value
00171         if abs(clower) < ftol: return lower_bracket;
00172 
00173         if cupper*clower >0:
00174             # argh, no sign change in here!
00175             raise C2Exception("unbracketed root in find_root at xlower=%g, xupper=%g, bailing" %
00176                     (lower_bracket, upper_bracket))
00177 
00178         delta=upper_bracket-lower_bracket   #first error step
00179         c, b, ypp=self.value_with_derivatives(root) # compute initial values
00180         c -= value
00181         
00182         while abs(delta) > xtol: # can allow quite small steps, since we have exact derivatives!
00183             a=ypp/2 #second derivative is 2*a
00184             disc=b*b-4*a*c
00185             if disc >= 0:
00186                 if b>=0:
00187                     q=-0.5*(b+math.sqrt(disc))
00188                 else:
00189                     q=-0.5*(b-math.sqrt(disc))
00190 
00191                 if q*q > abs(a*c):
00192                     delta=c/q   #since x1=q/a, x2=c/q, x1/x2=q^2/ac, this picks smaller step
00193                 else: delta=q/a
00194                 root+=delta;
00195 
00196             if disc < 0 or root<=lower_bracket or root>=upper_bracket or abs(delta) >= 0.5*(upper_bracket-lower_bracket):   
00197                 #if we jump out of the bracket, or if the step is not smaller than half the bracket, bisect
00198                 root=0.5*(lower_bracket+upper_bracket)  
00199                 delta=upper_bracket-lower_bracket
00200 
00201             c, b, ypp=self.value_with_derivatives(root) #get local curvature and value
00202             c -= value
00203 
00204             if trace: 
00205                 import sys
00206                 print >> sys.stderr, "find_root x, dx, c, b, a", ( (5*"%10.4g ") % 
00207                     (root, delta, c, b, ypp/2) )
00208                 
00209             if abs(c) < ftol or abs(c) < xtol*abs(b):   
00210                 return root #got it close enough
00211 
00212             # now, close in bracket on whichever side this still brackets
00213             if c*clower < 0.0:
00214                 cupper=c
00215                 upper_bracket=root
00216             else:
00217                 clower=c
00218                 lower_bracket=root
00219 
00220         return root
00221 


Generated on Wed Nov 21 10:18:31 2007 for analysis by  doxygen 1.5.4