欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)

程序员文章站 2022-05-04 10:59:17
python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)...

情况1:输出值可以是浮点数

算例1
python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)
书上的答案
python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)
该算例是一个带约束的目标问题

方法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)

python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)

方法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)

粒子群求得的值不一定是最优解
python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)

例子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 遗传算法

遗传算法原理及其python实现

使用工具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)

同理很难找到最优解
python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)

方法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)

python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)

python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)
作者:电气-余登武。写作不容易,请点个赞再走。python求解带约束目标优化问题(非线性规划,粒子群,遗传,差分进化)

本文地址:https://blog.****.net/kobeyu652453/article/details/113954067