Python调用MATLAB实现fmincon函数
motivation:
1.要实现“符号几何规划”的功能,使用MATLAB自带的fmincon函数来实现
2.工程的代码是通过Python来完成的,需要Python调用MATLAB实现
思路:
1.使用Python直接生成约束条件,目标函数,初始值等函数
2.使用Python来调取MATLAB接口,执行MATLAB的.m文件
3.MATLAB的.m文件中,将输出结果写入txt文档
4.Python读取txt文档结果
1.MATLAB部分
首先,简要介绍下MATLAB中自带的fmincon函数。fmincon函数是用来解决“非线性约束规划”,本文需要用到的是它解决“符合几何规划”的能力。【几何规划】的定义是,目标函数和约束条件均为系数为正的多项式,而【符号几何规划】在此基础上拓展,允许符号为负。
fmincon函数的约束形式如下:
其中,c(x)表示非线性多项式的不等式约束部分,注意,不等式需要严格按照“小于等于0”的格式(可以进行一些简单的不等式变换,写成右边为0的形式),ceq(x)表示非线性多项式的等式约束部分,形式同上。(b和beq是线性约束部分的参数,写成向量形式,A 和 Aeq 是线性约束部分的参数,写成矩阵形式,本文的问题场景不涉及“线性约束”条件)。lb和ub分别为x变量的上下限。在MATLAB中使用fmincon,传入参数如下:
x=fmincon( objfunction, x0, A, b, Aeq, beq, lb, ub, st)
在本文的问题背景下,目标函数的.m文件代码如下
newobj.m约束函数的.m文件的代码如下(这里简单设置了约束函数,当需要多个约束,只需要再添加即可,形式为c = [(),(),...,()]):
equationset.mfmincon函数还需要传入初始值(因为寻找的是局部最优解),根据具体情况来判断是否需要规定变量的上下边界。初始值传参的.m文件如下:
initialValue.m完成了三个函数.m文件,下面需要写脚本.m文件。其具体代码如下:
main.m首先,newobj.m和equationset.m需要和main.m在同一个目录下,“initial”方法是获取初始值x0,以及变量x的上下限。fmincon函数在输出时,不仅可以返回规划结果x,还能返回其他参数。此处本文用到exitflag参数,用来确定规划是否成功执行。exitflag的参数及含义如下:
1(简单来说就是,规划成功)
First-order optimality measure was less thanoptions.OptimalityTolerance, and maximum constraint violation was less thanoptions.ConstraintTolerance.
-2(未找到最优解,规划失败)
No feasible point was found.
其他参数含义详见http://cn.mathworks.com/help/optim/ug/fmincon.html 中的 output arguments 部分。
由于,我们需要将输出的结果保存到本地,所以在main.m的脚本文件中,加入写入txt的代码:
写入txt的代码将四个.m文件放在同一个目录下,在matlab中点击运行即可获得结果。下面,本文要做的工作是通过Python来运行main.m
2.Python部分
在Python端口,只需要使用MATLAB提供的Python API,即可实现Python运行MATLAB的脚本。
首先,在使用之前,需要安装MATLAB的API。安装过程非常简单(本文以在window 7环境下安装为例):
用管理员模式打开cmd:
cd “MATLAB安装路径\extern\engines\python”
python setup.py install
安装完成之后,即可在Python代码中:
import matlab.engine
之后,将main.m文件以及其他三个.m文件放置在.py文件的通过目录下,接下来只需要两行代码就能完成对于main.m脚本的调用
#首先初始化engine
eng= matlab.engine.start_matlab()
#之后直接访问脚本文件名
eng.main(nargout=0)
#最后,释放engine
eng.quit()
现在,到main.m中指定的生成txt文档的路径下,就能找到生成的两个txt文件,只需要使用Python来读取这两个txt中的数据即可。
2017.7.29更新
问题:
由于每次调用,MATLAB都会重新初始化,初始化的时间会消耗一些时间。
eng= matlab.engine.start_matlab()
由于实验场景要反复调用,执行MATLAB的脚本。所以尝试在for循环之外初始化,在for循环内执行MATLAB脚本,最后在for循环外退出eng。但是发现,MATLAB的脚本(脚本中有一个写入文件操作)只在第一次for循环的时候执行。只有在for循环中,执行开启eng,执行脚本和结束eng才能正常运行。
MATLAB脚本中的“写入文件”操作是自动执行的,相当于python中的f.flush(),但是仍然只在eng退出之后,才能重新开始一个脚本运行。查找官方文档未果...
参考文献:
http://cn.mathworks.com/help/optim/ug/fmincon.html(fmincon函数官方文档)
http://cn.mathworks.com/help/matlab/matlab-engine-for-python.html(Python调用MATLAB接口官方文档)