def test_bfgs_madsen(self): from ch import SumOfSquares import scipy.optimize obj = Ch(lambda x: SumOfSquares(Madsen(x=x))) def errfunc(x): obj.x = Ch(x) return obj.r def gradfunc(x): obj.x = Ch(x) return obj.dr_wrt(obj.x).ravel() x0 = np.array((3., 1.)) # Optimize with built-in bfgs. # Note: with 8 iters, this actually requires 14 gradient evaluations. # This can be verified by setting "disp" to 1. #tm = time.time() x1 = scipy.optimize.fmin_bfgs(errfunc, x0, fprime=gradfunc, maxiter=8, disp=0) #print 'forward: took %.es' % (time.time() - tm,) self.assertTrue(obj.r / 2. < 0.386599528247) # Optimize with chumpy's minimize (which uses scipy's bfgs). obj.x = x0 minimize(fun=obj, x0=[obj.x], method='bfgs', options={'maxiter': 8}) self.assertTrue(obj.r / 2. < 0.386599528247)
def minimize(fun, x0, method='dogleg', bounds=None, constraints=(), tol=None, callback=None, options=None): if method == 'dogleg': if options is None: options = {} return minimize_dogleg(fun, free_variables=x0, on_step=callback, **options) if isinstance(fun, list) or isinstance(fun, tuple): fun = ch.concatenate([f.ravel() for f in fun]) if isinstance(fun, dict): fun = ch.concatenate([f.ravel() for f in fun.values()]) obj = fun free_variables = x0 from ch import SumOfSquares hessp = None hess = None if obj.size == 1: obj_scalar = obj else: obj_scalar = SumOfSquares(obj) def hessp(vs, p, obj, obj_scalar, free_variables): changevars(vs, obj, obj_scalar, free_variables) if not hasattr(hessp, 'vs'): hessp.vs = vs * 0 + 1e16 if np.max(np.abs(vs - hessp.vs)) > 0: J = ns_jacfunc(vs, obj, obj_scalar, free_variables) hessp.J = J hessp.H = 2. * J.T.dot(J) hessp.vs = vs return np.array(hessp.H.dot(p)).ravel() #return 2*np.array(hessp.J.T.dot(hessp.J.dot(p))).ravel() if method.lower() != 'newton-cg': def hess(vs, obj, obj_scalar, free_variables): changevars(vs, obj, obj_scalar, free_variables) if not hasattr(hessp, 'vs'): hessp.vs = vs * 0 + 1e16 if np.max(np.abs(vs - hessp.vs)) > 0: J = ns_jacfunc(vs, obj, obj_scalar, free_variables) hessp.H = 2. * J.T.dot(J) return hessp.H def changevars(vs, obj, obj_scalar, free_variables): cur = 0 changed = False for idx, freevar in enumerate(free_variables): sz = freevar.r.size newvals = vs[cur:cur + sz].copy().reshape( free_variables[idx].shape) if np.max(np.abs(newvals - free_variables[idx]).ravel()) > 0: free_variables[idx][:] = newvals changed = True cur += sz methods_without_callback = ('anneal', 'powell', 'cobyla', 'slsqp') if callback is not None and changed and method.lower( ) in methods_without_callback: callback(None) return changed def residuals(vs, obj, obj_scalar, free_variables): changevars(vs, obj, obj_scalar, free_variables) residuals = obj_scalar.r.ravel()[0] return residuals def scalar_jacfunc(vs, obj, obj_scalar, free_variables): if not hasattr(scalar_jacfunc, 'vs'): scalar_jacfunc.vs = vs * 0 + 1e16 if np.max(np.abs(vs - scalar_jacfunc.vs)) == 0: return scalar_jacfunc.J changevars(vs, obj, obj_scalar, free_variables) if True: # faster, at least on some problems result = np.concatenate([ np.array(obj_scalar.lop(wrt, np.array([[1]]))).ravel() for wrt in free_variables ]) else: jacs = [obj_scalar.dr_wrt(wrt) for wrt in free_variables] for idx, jac in enumerate(jacs): if sp.issparse(jac): jacs[idx] = jacs[idx].todense() result = np.concatenate([jac.ravel() for jac in jacs]) scalar_jacfunc.J = result scalar_jacfunc.vs = vs return result.ravel() def ns_jacfunc(vs, obj, obj_scalar, free_variables): if not hasattr(ns_jacfunc, 'vs'): ns_jacfunc.vs = vs * 0 + 1e16 if np.max(np.abs(vs - ns_jacfunc.vs)) == 0: return ns_jacfunc.J changevars(vs, obj, obj_scalar, free_variables) jacs = [obj.dr_wrt(wrt) for wrt in free_variables] result = hstack(jacs) ns_jacfunc.J = result ns_jacfunc.vs = vs return result x1 = scipy.optimize.minimize(method=method, fun=residuals, callback=callback, x0=np.concatenate([ free_variable.r.ravel() for free_variable in free_variables ]), jac=scalar_jacfunc, hessp=hessp, hess=hess, args=(obj, obj_scalar, free_variables), bounds=bounds, constraints=constraints, tol=tol, options=options).x changevars(x1, obj, obj_scalar, free_variables) return free_variables