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 = [(),(),...,()]):

Python调用MATLAB实现fmincon函数_第1张图片
equationset.m

    fmincon函数还需要传入初始值(因为寻找的是局部最优解),根据具体情况来判断是否需要规定变量的上下边界。初始值传参的.m文件如下:

initialValue.m

    完成了三个函数.m文件,下面需要写脚本.m文件。其具体代码如下:

Python调用MATLAB实现fmincon函数_第2张图片
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的代码:

Python调用MATLAB实现fmincon函数_第3张图片
写入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接口官方文档)

你可能感兴趣的:(Python调用MATLAB实现fmincon函数)