python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)
情况1:输出值可以是浮点数
算例1
书上的答案
该算例是一个带约束的目标问题
方法1 非线性规划 scipy.optimize.minimize
非线性规划原理就不讲解啦
针对算例1
求取一个函数的最小值。函数的参数可以是多个,但函数值只能是标量。
参数
- 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, optionalbounds 是参数的界限,只适用于L-BFGS-B, TNC 和 SLSQP,每个参数对应一个 (min, max),表示参数的上下限。如果只有一边界限,则另一边置为None。当约束是针对 x x x xx x xxxx 中的单个元素的上下限时,就可以用 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求解器的选项字典。所有的算法都接受以下的通用选项:maxiter : int。迭代的最大次数。disp : bool。如果是True则打印出收敛信息。
- callback : callable, optional
每次迭代之后调用的函数,参数为xk,表示当前的参数向量。
返回值
res:优化结果。
优化结果是OptimizeResult对象,重要属性如下:
fun 是最优值
x 是最优解
success 表示求解器是否成功退出。
message 描述了求解器退出的原因
from scipy.optimize import minimize
import numpy as np
#目标函数即min(FG1+FG2+FG3)
def fun(x):
return (4+0.3*x[0]+0.0007*x[0]*x[0]+3+0.32*x[1]+0.0004*x[1]*x[1]+3.5+0.3*x[2]+0.00045*x[2]*x[2])
def con():
# 约束条件 分为eq 和ineq
#eq表示 函数结果等于0 ; ineq 表示 表达式大于等于0
cons = ({'type': 'eq', 'fun': lambda x: x[0]+x[1]+x[2]-700})
#{'type': 'ineq', 'fun': lambda x: -x[2] + x2max}#如果有不等式约束
#cons= ([con1, con2, con3, con4, con5, con6, con7, con8]) #如果有多个约束,则最后返回结果是这个
return cons
#上下限约束
b1=(100,200)#
b2=(120,250)#
b3=(150,300)#
bnds = (b1,b2,b3)#边界约束
if __name__ == "__main__":
cons=con()#约束
# 设置x初始猜测值
x0 = np.array((150, 250, 20))
res = minimize(fun, x0, method='SLSQP', constraints=cons,bounds=bnds)
print('代价',res.fun)
print(res.success)
print('解',res.x)
方法2 粒子群pyswarm.pso
粒子群PSO优化算法学习笔记 及其python实现(附讲解如何使用python语言sko.PSO工具包)
pyswarm是一个支持带约束的粒子群优化包
sko.PSO中的pso仅支持带上下限的约束,不支持等式和不等式约束。
参数详解
pso(func, lb, ub, ieqcons=[], f_ieqcons=None, args=(), kwargs={},
swarmsize=100, omega=0.5, phip=0.5, phig=0.5, maxiter=100,
minstep=1e-8, minfunc=1e-8, debug=False)
- func : function要最小化的函数
- lb : array设计变量的下界
- ub : array设计变量的上界
- ieqcons : list在一个成功优化的问题中,长度为n的函数列表,使ieqconsj >= 0.0(默认值:[])
- f_ieqcons : function返回一个一维数组,其中每个元素都必须大于或等于成功优化的问题中的0.0。如果指定了f_ieqcons,则忽略ieqcons(默认值:None)
- args : tuple传递给目标函数和约束函数的附加参数(默认:空元组)
- kwargs : dict传递给目标函数和约束函数的附加关键字参数(默认值:空字典)
- swarmsize : int集群中的粒子数(默认值:100)
- omega : scalar粒子速度缩放因子(默认值:0.5)
- phip : scalar缩放因子搜索远离粒子最知名的位置(默认:0.5)
- phig : scalar从蜂群最知名的位置搜索的缩放因子(默认值:0.5)
- maxiter : int 最大迭代次数
- minstep : scalar在searc终止前,群最佳位置的最小步长(默认值:1e-8)
- minfunc : scalar在searchterminates之前群的最佳目标值的最小变化(默认值:1e-8)
- debug : boolean如果为True,则每次迭代都会显示进度语句(默认值:False)
返回值
- g : array群体最知名的位置(最优设计)
- f : scalarg点的目标值
from pyswarm import pso
def object_func(x):
return (4+0.3*x[0]+0.0007*x[0]*x[0]+3+0.32*x[1]+0.0004*x[1]*x[1]+3.5+0.3*x[2]+0.00045*x[2]*x[2])
#不等式约束
def cons1(x):
return [x[0]+x[1]+x[2]-700]
lb = [100, 120, 150]#
ub = [200, 250, 300]
xopt, fopt = pso(object_func,lb,ub,ieqcons=[cons1], maxiter=100,swarmsize=1000)
print(xopt)
print(fopt)
粒子群求得的值不一定是最优解
例子2
from pyswarm import pso
def object_func(x):
x1 = x[0]
x2 = x[1]
return x1**4 - 2*x2*x1**2 + x2**2 + x1**2 - 2*x1 + 5 # 求解最小值
def cons(x):
x1 = x[0]
x2 = x[1]
con1 = -(x1 + 0.25)**2 + 0.75*x2 # con1>=0
con2 = -x1+0.2 # con2>=0
return [-(x1 + 0.25)**2 + 0.75*x2,-x1+0.2]
lb = [-3, -1] # -3<x1<2, -1<x2<6
ub = [2, 6]
xopt, fopt = pso(object_func, lb, ub, f_ieqcons=cons)
print(xopt)
print(fopt)
方法3 遗传算法
使用工具from sko.GA import GA
参数详解
func, n_dim,size_pop=50, max_iter=200,prob_mut=0.001,
lb=-1, ub=1,constraint_eq=tuple(), constraint_ueq=tuple(),precision=1e-7
func : function .The func you want to do optimal
n_dim : int . number of variables of func
lb : array_like The lower bound of every variables of func
ub : array_like The upper bound of every vaiiables of func
constraint_eq : list .equal constraint
constraint_ueq : list . unequal constraint
precision : array_like. The precision of every vaiiables of func
size_pop : int .Size of population
max_iter : int. Max of iter
prob_mut : float .between 0 and Probability of mutation
Attributes
----------------------
Lind : array_like
The num of genes of every variable of func(segments)
generation_best_X : array_like. Size is max_iter.
Best X of every generation
generation_best_ranking : array_like. Size if max_iter.
Best ranking of every generation
def object_func(x):
return (4+0.3*x[0]+0.0007*x[0]*x[0]+3+0.32*x[1]+0.0004*x[1]*x[1]+3.5+0.3*x[2]+0.00045*x[2]*x[2])
#等式约束
def cons1(x):
return [x[0]+x[1]+x[2]-700]
cons=cons1
#导入包
from sko.GA import GA
ga = GA(func=object_func, n_dim=3, size_pop=200, max_iter=800, lb=[100, 120, 150], ub=[200, 250, 300],constraint_eq=[cons])
best_x, best_y = ga.run()
print('best_x:', best_x, '\n', 'best_y:', best_y)
同理很难找到最优解
方法4 差分进化算法
'''
min f(x1, x2, x3) = x1^2 + x2^2 + x3^2
s.t.
x1*x2 >= 1
x1*x2 <= 5
x2 + x3 = 1
0 <= x1, x2, x3 <= 5
'''
def obj_func(p):
x1, x2, x3 = p
return x1 ** 2 + x2 ** 2 + x3 ** 2
constraint_eq = [
lambda x: 1 - x[1] - x[2]
]
constraint_ueq = [
lambda x: 1 - x[0] * x[1],
lambda x: x[0] * x[1] - 5
]
from sko.DE import DE
de = DE(func=obj_func, n_dim=3, size_pop=50, max_iter=800, lb=[0, 0, 0], ub=[5, 5, 5],
constraint_eq=constraint_eq, constraint_ueq=constraint_ueq)
best_x, best_y = de.run()
print('best_x:', best_x, '\n', 'best_y:', best_y)
情况2:指定输出值为整数
方法1:遗传算法做整数规划**
在多维优化时,想让哪个变量限制为整数,就设定 precision 为 1即可。
例如,我想让我的自定义函数object_func 的第一个变量限制为整数,那么就设定 precision 的第一个数为1,例子如下
def object_func(x):
return (4+0.3*x[0]+0.0007*x[0]*x[0]+3+0.32*x[1]+0.0004*x[1]*x[1]+3.5+0.3*x[2]+0.00045*x[2]*x[2])
#等式约束
def cons1(x):
return [x[0]+x[1]+x[2]-700]
cons=cons1
#导入包
from sko.GA import GA
ga = GA(func=object_func, n_dim=3, size_pop=200, max_iter=800, lb=[100, 120, 150], ub=[200, 250, 300],constraint_eq=[cons], precision=[1, 1e-7, 1e-7])
best_x, best_y = ga.run()
print('best_x:', best_x, '\n', 'best_y:', best_y)
作者:电气-余登武。写作不容易,请点个赞再走。
本文地址:https://blog.csdn.net/kobeyu652453/article/details/113954067