在Python中使用PuLP进行多目标线性优化

在我的一些帖子中,我在R中使用lpSolve或FuzzyLP解决线性优化问题。我还使用Python中的PuLP和SciPy.optimize解决了此类问题。在所有这些情况下,问题仅具有一个目标功能。

在这篇文章中,我想提供一个使用PuLP模块解决多目标线性优化问题的Python编码示例。

多目标线性优化问题是具有多个目标函数的线性优化问题。线性规划的这一领域也称为多目标线性规划或多目标线性规划。

下面,我介绍了一个具有两个目标函数的示例性多目标线性优化问题:

假设在上述问题陈述中,两个目标函数代表两个不同的目标,例如服务水平和某些产品组合的利润率,我测试了两种解决此问题的方法。

第一种方法是解决一个目标,然后通过向第二个优化运行中添加一个附加约束将问题固定在第一个问题的最佳结果上,然后我将使第二个目标函数最大化(服从于保持最佳目标值到第一个子问题)。

第二种方法是将两个目标加在一起,即通过应用权重将它们合并为一个目标函数。通过采样权重并解决每个采样权重的组合问题,可以根据权重来审查最佳结果。

方法1:最大化一个目标,然后将其添加为约束并解决另一个目标

使用PuLP时,我首先将第一个目标最大化,然后将那个目标函数添加为原始问题的约束,并在所有约束(包括该附加约束)的约束下最大化第二个目标。

在数学语法中,我们首先要解决的问题可以表述为:

这是使用PuLP模块在Python中上述问题陈述的实现:

#  首先,导入PuLP 
import pulp

#  然后,进行问题的初始声明 
linearProblem = pulp.LpProblem(" 为第一目标最大化 ",pulp.LpMaximize)

#  使用PuLP的delcare优化变量 
x1 = pulp.LpVariable("x1",lowBound = 0) 
x2 = pulp.LpVariable("x2",lowBound = 0) 

#  在线性问题陈述中添加(第一个)目标函数 
linearProblem += 2*x1 + 3*x2 

#  增加问题的约束 
linearProblem += x1 + x2 <= 10
linearProblem += 2*x1 + x2 <= 15

#  使用默认求解器求解,最大化第一个目标 
solution = linearProblem.solve()

#  如果找到最优值,则输出信息,最大目标值是什么,最优点是什么 
print(str(pulp.LpStatus[solution])+" ; max value = "+str(pulp.value(linearProblem.objective))+
      " ; x1_opt = "+str(pulp.value(x1))+
      " ; x2_opt = "+str(pulp.value(x2)))
 最佳 ;  最大值  = 30.0 ; x1_opt = 0.0 ; x2_opt = 10.0

现在,我重新陈述原始问题,以使第二个目标函数在受到附加约束的情况下最大化。该附加约束要求第一个目标必须至少为30。使用数学语法,现在可以解决的问题如下:

这是上面的问题声明在Python中使用PuLP的实现:

#  重新建模问题陈述 
linearProblem = pulp.LpProblem(" 最大化第二个目标 ",pulp.LpMaximize)
linearProblem += 4*x1 - 2*x2
linearProblem += x1 + x2 <= 10
linearProblem += 2*x1 + x2 <= 15
linearProblem += 2*x1 + 3*x2 >= 30

#重构后查看问题陈述
linearProblem
 
最大化第二个目标 :
 最大化 
4*x1 + -2*x2 + 0
 受制于 
_C1: x1 + x2 <= 10

_C2: 2 x1 + x2 <= 15

_C3: 2 x1 + 3 x2 >= 30

 变数 
x1  连续 
x2  连续 

现在,我使用PuLP中的默认求解器解决此问题:

#  应用默认求解器 
solution = linearProblem.solve()

#  输出一个字符串,概述是否找到了最优解,如果找到了最优解,那么 
print(str(pulp.LpStatus[solution])+" ; max value = "+str(pulp.value(linearProblem.objective))+
      " ; x1_opt = "+str(pulp.value(x1))+
      " ; x2_opt = "+str(pulp.value(x2)))
 最佳 ;  最大值 = -19.999999999995993 ; x1_opt = 1.0018653e-12 ; x2_opt = 10.0

此方法表明x1 = 0和x2 = 10是最佳解决方案。最佳目标值对于目标1为30,对于目标2为-20。

方法2:使用采样的权重和具有定义步长的迭代组合目标

应用此方法时,我们将重新陈述原始问题,如下所示:

现在的问题是如何选择α。

在这种情况下,典型的方法是确定有效边界。在经济学中,例如被称为“最佳最优”。为了构建这样的方法,我以0.01的步长采样alpha。对于每个alpha值,我都会使用PuLP重新说明问题,然后加以解决。

我将结果存储在列表中,并使用matplotlib.pyplot可视化结果:

#  导入matplotlib.pyplot 
import matplotlib.pyplot as plt 

#  导入pandas和numpy以便能够以DataFrame格式存储数据 
import numpy as np
import pandas as pd

#  定义步长 
stepSize = 0.01

#  初始化空的DataFrame以存储优化结果 
solutionTable = pd.DataFrame(columns=["alpha","x1_opt","x2_opt","obj_value"])

#  使用stepSize迭代从0到1的alpha值,并将PuLP解决方案写入solutionTable 
for i in range(0,101,int(stepSize*100)):
        #  再次声明问题 
        linearProblem = pulp.LpProblem(" 多目标线性最大化 ",pulp.LpMaximize)
        #  在采样的alpha处添加目标函数 
        linearProblem += (i/100)*(2*x1+3*x2)+(1-i/100)*(4*x1-2*x2)
        #  添加约束 
        linearProblem += x1 + x2 <= 10
        linearProblem += 2*x1 + x2 <= 15
        #  解决这个问题 
        solution = linearProblem.solve()
        #  将解决方案写入DataFrame 
        solutionTable.loc[int(i/(stepSize*100))] = [i/100,
                                                     pulp.value(x1),
                                                     pulp.value(x2),
                                                     pulp.value(linearProblem.objective)]

#  使用matplotlib.pyplot可视化优化结果 
# --  设置图形大小 
plt.figure(figsize=(20,10))
# --  创建线图 
plt.plot(solutionTable["alpha"],solutionTable["obj_value"],color="red")
# --  添加轴标签 
plt.xlabel("alpha",size=20)
plt.ylabel("obj_value",size=20)
# --  添加剧情标题 
plt.title(" 最佳组合目标函数值作为alpha的函数 ",size=32)
# -- show plot
plt.show()

为了完成本文,我打印出优化结果DataFrame表的标题:

solutionTable.head()
alphax1_optx2_optobj_value
00.007.50.030.00
10.017.50.029.85
20.027.50.029.70
30.037.50.029.55
40.047.50.029.40

You May Also Like

Leave a Reply

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据