예제 #1
0
    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)
예제 #2
0
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