MATLAB用fmincon函数求非线性约束下的最优化问题
该实例皆为在MATLAB R2014a运行所得。
优化模型
我们要求解的最优化问题的形式如下:

其中
是一个向量,
是非等式约束,
是等式约束。
约束条件可以进一步细化为:
线性不等式约束:Ax≤b
线性等式约束:Aeqx=beq
非线性不等式约束:Cx≤0
非线性等式约束:Ceq x =0
x 的下界和上界:Lbnd≤x≤Ubnd
MATLAB最优化工具箱提供了一个fmincon函数,专门用于求解各种约束下的最优化问题。该函数的调用格式为:
[x,fval]=fmincon(fun,x0,A,b,Aeq,beq,Lbnd,Ubnd,NonF,options)
其中x、fval、filename、x0和option的含义分别为自变量、因变量、函数名、初值、优化参数。其余参数为约束条件,参数NonF为非线性约束函数的M文件名。如果某个约束不存在,则用空矩阵来表示。
例题
求解有约束最优化问题

首先编写目标函数M文件fop.m:
function f=fop(x)
f=0.4*x(2)+x(1)^2+x(2)^2-x(1)*x(2)+1/30*x(1)^3;
end
再设定约束条件,并调用fmincon函数求解此约束最优化问题:
x0=[0.5;0.5];
A=[-1,-0.5;-0.5,-1]; b=[-0.4;-0.5];
lb=0;0];
option=optimset;
option.LargeScale='off';
option.Display='off';
[x,f]=fmincon('fop',x0,A,b,[],[],lb,[],[],option)
输出结果为:
x =
0.34
0.33
f =
0.25
Python——使用scipy求解带约束的最优化问题
优化模型
我们要求解的最优化问题的形式如下:

其中
是一个向量,
是非等式约束,
是等式约束。
示例
在
,
的条件下,求解
的最小值。
from scipy.optimize import minimize
import numpy as np
e = 1e-10 # 非常接近0的值
fun = lambda x : (x[0] - 0.667) / (x[0] + x[1] + x[2] - 2) # 约束函数
cons = ({'type': 'eq', 'fun': lambda x: x[0] * x[1] * x[2] - 1}, # xyz=1
{'type': 'ineq', 'fun': lambda x: x[0] - e}, # x>=e,即 x > 0
{'type': 'ineq', 'fun': lambda x: x[1] - e},
{'type': 'ineq', 'fun': lambda x: x[2] - e}
)
x0 = np.array((1.0, 1.0, 1.0)) # 设置初始值
res = minimize(fun, x0, method='SLSQP', constraints=cons)
print('最小值:',res.fun)
print('最优解:',res.x)
print('迭代终止是否成功:', res.success)
print('迭代终止原因:', res.message)
123456789101112131415
输出:
最小值: -0.18814357989751096
最优解: [0.29250894 1.84897232 1.84897233]
迭代终止是否成功: True
迭代终止原因: Optimization terminated successfully.
1234
备注:
若是求一个函数的最大值,则改为求其相反数的最小值。
因为ineq的约束是表示非负,所以x>0 的条件可以写为 x-eps ≥ 0 ,其中e eeps是一个尽可能小的值。
其实,在本题中,可以直接让x>0,因为有约束 xyz=1,所以不必担心最后解为x=0。
函数介绍
scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)
求取一个函数的最小值。函数的参数可以是多个,但函数值只能是标量。
fun : callable;目标函数
x0 : ndarry;初始值
args : tuple, optional;额外的参数,传给目标函数和它的导数。
method : str or callable, optional;求解问题的算法名,下面选其一:
Nelder-Mead, Powell, CG, BFGS, Newton-CG, L-BFGS-B, TNC, COBYLA, SLSQP, dogleg, trust-ncg
默认是 BFGS, L-BFGS-B, SLSQP 之一,根据问题是否含有约束和界限自动选择。
jac : bool or callable, optional;目标函数的梯度矩阵。只适用于 CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg。如果jac是一个 Boolean 且为 True,则 fun 被认为是梯度与目标函数一起返回。如果是False,则梯度会被自动地计算。jac也可以是一个函数,返回目标函数的梯度,且参数必须与fun相同。
hess, hessp : callable, optional;目标函数的二阶导矩阵,或者二阶导矩阵乘以一个随机向量p。只适用于Newton-CG,dogleg, trust-ncg。hess和hessp只需要给出一个即可。如果提供了hess,则hessp会被忽略。如果两者都没有提供,则二阶导矩阵会被自动计算。
bounds : sequence, optional;bounds 是参数的界限,只适用于L-BFGS-B, TNC 和 SLSQP,每个参数对应一个 (min, max),表示参数的上下限。如果只有一边界限,则另一边置为None。当约束是针对 x xx 中的单个元素的上下限时,就可以用 bounds 参数来设置。
constraints : dict or sequence of dict, optional;约束定义,只适用于 COBYLA 和 SLSQP。每个约束定义为一个词典,键值对包括:
fun : callable。定义了约束函数。
type : str。约束类型: eq’ 表示等式约束(fun等于0),ineq 表示不等式约束(fun大于等于0)。COBYLA只支持不等式约束。
jac : callable, optional。fun 的梯度矩阵,只适用于SLSQP
args : sequence, optional。传递给fun和jac的额外参数。
tol : float, optional;迭代终止的允许误差。
options : dict, optional;求解器的选项字典。所有的算法都接受以下的通用选项:
callback : callable, optional;每次迭代之后调用的函数,参数为xk,表示当前的参数向量。
res:优化结果。优化结果是OptimizeResult对象,重要属性如下:
fun 是最优值。
x 是最优解。
success 表示求解器是否成功退出。
message 描述了求解器退出的原因。