pythonoptimizationscipymystic

Supplying a vector of inequalities/constraints to mystic


I am trying to supply constraints to a a function minimisation that I have hitherto been performing successfully with an unconstrained algorithm available via scipy (scipy.optimize.fmin_l_bfgs_b()).

Reading up (see, e.g, Python constrained non-linear optimization), I discovered a minimisation packed called mystic that seems to be what I need. My situation is as follows. I have a function of 3N variables (representing xyz position coordinates of N nodes), and I want to supply a list of constraints such that z/x = const. for each node. This makes for a total of N constraints. How do I do define/supply these constraints most efficiently for mystic()? Can the same constraint object be used with scipy.optimize.slsqp() as well? Since my constraints are linear, this should be a viable option too.

I tried the following, but it crashed my computer:

import mystic.symbolic as ms
ieqns = ''
for p in range(N):
    ieqns += 'x'+str(p+2) +'/x'+str(p) +" <= 2"

cf = ms.generate_constraint(ms.generate_solvers(ms.simplify(ieqns)))
pf = ms.generate_penalty(ms.generate_conditions(ieqns), k=1e12)

Solution

  • I'm the mystic author. I believe what you are looking to do is something like this:

    >>> import mystic.symbolic as ms
    >>> ieqns = ''
    >>> for p in range(10):
    ...   ieqns += 'x{0} <= 2*x{1}\n'.format(p+2,p)
    ... 
    >>> cf = ms.generate_constraint(ms.generate_solvers(ieqns))
    >>>
    >>> # test that it applies the constraints
    >>> cf([1.,3.,5.,7.,9.,11.,13.,15.,17.,19.,21.,23.,25.])
    [1.0, 3.0, 2.0, 6.0, 4.0, 11.0, 8.0, 15.0, 16.0, 19.0, 21.0, 23.0, 25.0]
    

    Then we can minimize while applying the constraints (however, in the following case the constraints are basically irrelevant):

    >>> # get an objective
    >>> import mystic.models as mm
    >>> rosen = mm.dejong.Rosenbrock(12).function
    >>> 
    >>> # get an optimizer
    >>> import mystic.solvers as my
    >>> result = my.diffev2(rosen, x0=bounds, bounds=bounds, constrints=cf, npop=40, disp=False, full_output=True, gtol=100)
    >>>
    >>> # get the solution 
    >>> result[0]
    array([0.99997179, 1.00005506, 1.00012367, 0.99998539, 0.99984306,
           0.99981495, 0.999951  , 0.99996505, 0.99971107, 0.99925239,
           0.99846259, 0.99692293])
    >>> # and the final 'cost'
    >>> result[1]
    2.2385442425350018e-05
    >>>