我有一个在Jython下运行的python程序(使用第三方Java API),我想在其中计算一个多变量函数的约束最小化。
Scipy有一个模块可以很好地工作(scipy.optimize
),但不幸的是,您不能在Jython中使用Scipy。有人知道Jython有一个好的图书馆吗?如果我能在Jython下运行这个,我就会做好准备:
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})
谢谢-Michael
这可能不是您特定用例的最佳解决方案,因为您已经在Jython中拥有应用程序,但JPype
(链接)允许CPython程序与JVM上运行的程序对话,我自己还没有尝试过,但在这里找到了一个hello-world示例。
基本上,您可以创建Java类,将其编译到一个jar中,然后在CPython中进行
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()
我意识到这会颠倒你的应用程序逻辑。另一种选择是使用subprocess
并串行化输入/输出。
更新
我最近遇到了一个类似的问题,决定试试JPype
,现在可以说它非常值得使用,尽管至少在OSX上安装它时存在一些问题,请参阅此处的帮助(setup.py
中的一些JVM路径需要更改)。
如果您的项目使用Jython,您可以使用Slsqp4j在JVM上本地执行求解,而不必完全编写SciPy代码。Slsqp4j是一个围绕SciPy中包含的SLSQP求解器的Java包装器。该api与SciPy的非常相似。它在这里主持:https://github.com/skew-opensource/slsqp4j
(披露:我是作者)