Search code examples
pythonjythonmathematical-optimizationjython-2.5

Constrained minimization of multivariate function using Jython


I have a python program running under Jython (to use a third party Java API), inside which I would like to calculate a constrained minimization of a multivariate function.

Scipy has a module for this that works perfectly (scipy.optimize) but unfortunately you cannot use scipy within Jython. Does anyone know of a good library/any other way to do this in Jython? If I could just run this under Jython, I'd be all set:

def func(x, sign=1.0):
    """ Objective function -- minimize this """
    return sign*(2*x[0]*x[1] + 2*x[0] - x[0]**2 - 2*x[1]**2)

def func_deriv(x, sign=1.0):
    """ Derivative of objective function """
    dfdx0 = sign*(-2*x[0] + 2*x[1] + 2)
    dfdx1 = sign*(2*x[0] - 4*x[1])
    return np.array([ dfdx0, dfdx1 ])

cons = ({'type': 'eq',
         'fun' : lambda x: np.array([x[0]**3 - x[1]]),
         'jac' : lambda x: np.array([3.0*(x[0]**2.0), -1.0])}, #partial derivative of fun
        {'type': 'ineq',
         'fun' : lambda x: np.array([x[1] - 1]),
         'jac' : lambda x: np.array([0.0, 1.0])})   #partial derivative of fun

res = minimize(func, [-1.0,1.0], args=(-1.0,), jac=func_deriv, 
               method='SLSQP', constraints=cons, options={'disp': True})

Thanks! -Michael


Solution

  • This may not be the most optimal solution to your particular use case as you already have your application in Jython but JPype (link) allows a CPython program to talk to a program running on JVM, I haven't tried it my self but found a hello world example here.

    Basically you make your Java class, compile it into a jar and then in CPython do

    import jpype
    import os.path
    
    jarpath = os.path.join(os.path.abspath('.'), 'build/jar')
    jpype.startJVM(jpype.getDefaultJVMPath(), "-Djava.ext.dirs=%s" % jarpath)
    
    # get the class
    hello_world = jpype.JClass('com.stackoverflow.HelloWorld')
    t = hello_world()  # create an instance of the class
    t.helloWorld("Say hello")  # try to call one of the class methods
    jpype.shutdownJVM()
    

    I realise though that inverts your application logic. The other option would be to use subprocess and serialise the inputs/outputs.

    UPDATE

    I came across a similar problem recently and decided to give JPype a go and can now say that it's well worth using, although there are some issues installing it at least on OSX, see help here (some of the JVM paths need to be altered in setup.py).