def newton_solver(f, x0, lb=None, ub=None, infos=False, verbose=False, maxit=50, tol=1e-8, eps=1e-5, numdiff=False): '''Solves many independent systems f(x)=0 simultaneously using a simple gradient descent. :param f: objective function to be solved with values p x N . The second output argument represents the derivative with values in (p x p x N) :param x0: initial value ( p x N ) :return: solution x such that f(x) = 0 ''' precision = x0.dtype # default tolerance should depend on precision from dolo.numeric.serial_operations import serial_multiplication as stv, serial_solve err = 1 it = 0 while err > tol and it <= maxit: if not numdiff: [res, dres] = f(x0) else: res = f(x0) dres = numpy.zeros((res.shape[0], x0.shape[0], x0.shape[1]), dtype=precision) for i in range(x0.shape[0]): xi = x0.copy() xi[i, :] += eps resi = f(xi) dres[:, i, :] = (resi - res) / eps try: dx = -serial_solve(dres, res) except: dx = -serial_solve(dres, res, debug=True) x = x0 + dx err = abs(res).max() x0 = x it += 1 if not infos: return x else: return [x, it]
def newton_solver(f, x0, lb=None, ub=None, infos=False, verbose=False, maxit=50, tol=1e-8, eps=1e-5, numdiff=False): '''Solves many independent systems f(x)=0 simultaneously using a simple gradient descent. :param f: objective function to be solved with values p x N . The second output argument represents the derivative with values in (p x p x N) :param x0: initial value ( p x N ) :return: solution x such that f(x) = 0 ''' precision = x0.dtype # default tolerance should depend on precision from dolo.numeric.serial_operations import serial_multiplication as stv, serial_solve err = 1 it = 0 while err > tol and it <= maxit: if not numdiff: [res,dres] = f(x0) else: res = f(x0) dres = numpy.zeros( (res.shape[0], x0.shape[0], x0.shape[1]), dtype=precision ) for i in range(x0.shape[0]): xi = x0.copy() xi[i,:] += eps resi = f(xi) dres[:,i,:] = (resi - res)/eps try: dx = - serial_solve(dres,res) except: dx = - serial_solve(dres,res, debug=True) x = x0 + dx err = abs(res).max() x0 = x it += 1 if not infos: return x else: return [x, it]
def newton_solver(f, x0, lb=None, ub=None, infos=False, backsteps=10, maxit=10): '''Solves many independent systems f(x)=0 simultaneously using a simple gradient descent. :param f: objective function to be solved with values p x N . The second output argument represents the derivative with values in (p x p x N) :param x0: initial value ( p x N ) :return: solution x such that f(x) = 0 ''' from dolo.numeric.serial_operations import serial_multiplication as stv, serial_solve err = 1 tol = 1e-8 it = 0 while err > tol and it <= maxit: [res,dres] = f(x0) # res = f(x0) # dres = df(x0) fnorm = abs(res).max() # suboptimal dx = - serial_solve(dres,res) # x = x0 + dx for i in range(backsteps): xx = x0 + dx/(2**i) if not ub==None: xx = numpy.maximum(xx, lb) xx = numpy.minimum(xx, ub) new_res = f(xx)[0] new_fnorm = abs(new_res).max() if numpy.isfinite(new_fnorm) and new_fnorm < fnorm: # all right proceed to next iteration x = xx break if i == backsteps -1: if numpy.isfinite(new_fnorm): x = xx else: raise Exception('Non finite value found') err = abs(dx).max() x0 = x it += 1 # print (it <=maxit) # print(err) if not infos: return x else: return [x, it]
def ncpsolve(f, a, b, x, tol=None, infos=False, verbose=False, serial=False): ''' don't ask what ncpsolve can do for you... :param f: :param a: :param b: :param x: :param tol: :param serial: :return: ''' maxit = 100 if tol is None: tol = sqrt(finfo(float64).eps) maxsteps = 10 showiters = True it = 0 if verbose: headline = '|{0:^5} | {1:^12} | {2:^12} |'.format( 'k', ' backsteps', '||f(x)||') stars = '-' * len(headline) print(stars) print(headline) print(stars) while it < maxit: it += 1 [fval, fjac] = f(x) [ftmp, fjac] = smooth(x, a, b, fval, fjac, serial=serial) fnorm = norm(ftmp, ord=inf) if fnorm < tol: if verbose: print(stars) if infos: return [x, it] else: return x if serial: from dolo.numeric.serial_operations import serial_solve dx = -serial_solve(fjac, ftmp) else: dx = -solve(fjac, ftmp) fnormold = inf for backsteps in range(maxsteps): xnew = x + dx fnew = f(xnew)[0] # TODO: don't ask for derivatives fnew = smooth(xnew, a, b, fnew, serial=serial) fnormnew = norm(fnew, ord=inf) if fnormnew < fnorm: break if fnormold < fnormnew: dx = 2 * dx break fnormold = fnormnew dx = dx / 2 x = x + dx if verbose: print('|{0:5} | {2:12.3e} | {2:12.3e} |'.format( it, backsteps, fnormnew)) if verbose: print(stars) warnings.Warning('Failure to converge in ncpsolve') fval = f(x) return [x, fval]
def ncpsolve(f, a, b, x, tol=None, infos=False, verbose=False, serial=False): ''' don't ask what ncpsolve can do for you... :param f: :param a: :param b: :param x: :param tol: :param serial: :return: ''' maxit = 100 if tol is None: tol = sqrt( finfo( float64 ).eps ) maxsteps = 10 showiters = True it = 0 if verbose: headline = '|{0:^5} | {1:^12} | {2:^12} |'.format( 'k',' backsteps', '||f(x)||' ) stars = '-'*len(headline) print(stars) print(headline) print(stars) while it < maxit: it += 1 [fval, fjac] = f(x) [ftmp, fjac] = smooth(x, a, b, fval, fjac, serial=serial) fnorm = norm( ftmp, ord=inf) if fnorm < tol: if verbose: print(stars) if infos: return [x, it] else: return x if serial: from dolo.numeric.serial_operations import serial_solve dx = - serial_solve( fjac, ftmp ) else: dx = - solve( fjac, ftmp) fnormold = inf for backsteps in range(maxsteps): xnew = x + dx fnew = f(xnew)[0] # TODO: don't ask for derivatives fnew = smooth( xnew, a, b, fnew, serial=serial) fnormnew = norm(fnew, ord=inf) if fnormnew < fnorm: break if fnormold < fnormnew: dx = 2*dx break fnormold = fnormnew dx = dx/2 x = x + dx if verbose: print('|{0:5} | {2:12.3e} | {2:12.3e} |'.format( it, backsteps, fnormnew) ) if verbose: print(stars) warnings.Warning('Failure to converge in ncpsolve') fval = f(x) return [x,fval]