Exemplo n.º 1
0
def minimize_scipy_generic(rf_np, method, bounds = None, **kwargs):
    ''' Interface to the generic minimize method in scipy '''

    try:
        from scipy.optimize import minimize as scipy_minimize
    except ImportError:
        print "**************** Deprecated warning *****************"
        print "You have an unusable installation of scipy. This version is not supported by dolfin-adjoint."

        try:
            import scipy
            print "Version: %s\tFile: %s" % (scipy.__version__, scipy.__file__)
        except:
            pass

        raise

    if method in ["Newton-CG"]:
        forget = None
    else:
        forget = False

    project = kwargs.pop("project", False)

    m = [p.data() for p in rf_np.controls]
    m_global = rf_np.obj_to_array(m)
    J = rf_np.__call__
    dJ = lambda m: rf_np.derivative(m, forget=forget, project=project)
    H = rf_np.hessian

    if not "options" in kwargs:
        kwargs["options"] = {}
    if rank(rf_np.rf.mpi_comm()) != 0:
        # Shut up all processors except the first one.
        kwargs["options"]["disp"] = False
    else:
        # Print out progress information by default
        if not "disp" in kwargs["options"]:
            kwargs["options"]["disp"] = True

    # Make the default SLSLQP options more verbose
    if method == "SLSQP" and "iprint" not in kwargs["options"]:
        kwargs["options"]["iprint"] = 2

    # For gradient-based methods add the derivative function to the argument list
    if method not in ["COBYLA", "Nelder-Mead", "Anneal", "Powell"]:
        kwargs["jac"] = dJ

    # For Hessian-based methods add the Hessian action function to the argument list
    if method in ["Newton-CG"]:
        kwargs["hessp"] = H

    if "constraints" in kwargs:
        from constraints import canonicalise, InequalityConstraint, EqualityConstraint
        constraints = canonicalise(kwargs["constraints"])
        scipy_c = []
        for c in constraints:
            if isinstance(c, InequalityConstraint):
                typestr = "ineq"
            elif isinstance(c, EqualityConstraint):
                typestr = "eq"
            else:
                raise Exception, "Unknown constraint class"

            def jac(x):
                out = c.jacobian(x)
                return [gather(y) for y in out]

            scipy_c.append(dict(type=typestr, fun=c.function, jac=jac))
        kwargs["constraints"] = scipy_c

    if method=="basinhopping":
        try:
            from scipy.optimize import basinhopping
        except ImportError:
            print "**************** Outdated scipy version warning *****************"
            print "The basin hopping optimisation algorithm requires scipy >= 0.12."
            raise ImportError

        del kwargs["options"]
        del kwargs["jac"]
        kwargs["minimizer_kwargs"]["jac"]=dJ

        if "bounds" in kwargs["minimizer_kwargs"]:
            kwargs["minimizer_kwargs"]["bounds"] = \
                serialise_bounds(rf_np, kwargs["minimizer_kwargs"]["bounds"])

        res = basinhopping(J, m_global, **kwargs)

    elif bounds != None:
        bounds = serialise_bounds(rf_np, bounds)
        res = scipy_minimize(J, m_global, method=method, bounds=bounds, **kwargs)
    else:
        res = scipy_minimize(J, m_global, method=method, **kwargs)

    rf_np.set_controls(np.array(res["x"]))
    m = [p.data() for p in rf_np.controls]
    return m