繁体   English   中英

将 LP 从 Excel 转换为 Python Pulp

[英]Translating a LP from Excel to Python Pulp

我需要通过混合 7 种合金零件来生产 5000 公斤钢。 我需要降低成本,所以我需要挑选最好的零件。

结果必须尊重主要钢材特性,例如,碳含量必须在 2% 到 3% 之间,不多也不少。

Excel 线性求解器程序已经存在,并且源自一本专业书籍。

我正在尝试将其转换为 PULP 代码,现在。

我的问题是:如何创建铜、碳和锰约束? 有2个数组,所以我不知道该怎么做。

都是百分比,我不知道怎么做。 我的结果实际上是错误的,我留下了我为信息所做的错误约束。 好像我需要在某一时刻除以 5000,但我该怎么做?

让我尝试向您解释我无法理解的内容:

我需要 5000 公斤钢才能含有 0.60% 的铜,但我的铜合金零件含有 90% 和 96% 的铜。 你明白我的意思吗,为什么描述我的限制如此困难?

"" "
 Mining and metals

We make steel with raw materials, we want to reduce the cost of producing this steel
to make more money, but still respecting the minimum characteristics of quality steel

"" "

# Minimize the cost of metal alloys.
# Characteristics of the steel to be made

"" "Element      %Minimum %Max   %Real ( it is a var)
    Carbon       2         3     2.26
    Copper       0.4       0.6   0.60
    Manganese    1.2       1.65  1.20

 "" "
# Characteristics, stocks and purchase price of alloys
"" "

Alloy          C%   Cu%   Mn%     Stocks kg Price € / kg
Iron alloy     2.50 0.00  1.30    4000      1.20
Iron alloy     3.00 0.00  0.80    3000      1.50
Iron alloy     0.00 0.30  0.00    6000      0.90
Copper alloy   0.00 90.00 0.00    5000      1.30
Copper alloy   0.00 96.00 4.00    2000      1.45
Aluminum alloy 0.00 0.40  1.20    3000      1.20
Aluminum alloy 0.00 0.60  0.00   2,500      1.00

"" "

# Import the PuLP lib
from pulp import *

# Create the problem variable
prob = LpProblem ("MinimiserLpAlliage", LpMinimize)

# The 7 vars have a zero limit
x1 = LpVariable ("Iron alloy 1", 0)
x2 = LpVariable ("Iron alloy 2", 0)
x3 = LpVariable ("Iron alloy 3", 0)
x4 = LpVariable ("Copper alloy 1", 0)
x5 = LpVariable ("Copper alloy 2", 0)
x6 = LpVariable ("Aluminum alloy 1", 0)
x7 = LpVariable ("Aluminum alloy 2", 0)


# The objective function is to minimize the total cost of the alloys in EUROS for a given quantity in KGS
prob + = 1.20 * x1 + 1.50 * x2 + 0.90 * x3 + 1.30 * x4 + 1.45 * x5 + 1.20 * x6 + 1.00 * x7, "AlliageCost"

# Quantity constraint in KGS.
prob + = x1 + x2 + x3 + x4 + x5 + x6 + x7 == 5000, "RequestedQuantity"

# MIN constraints of% carbon, by alloy  // ITS NOT WHAT I NEED
prob + = x1> = 2.5, "MinCarboneRequirement1"
prob + = x2> = 3, "MinCarboneRequirement2"
prob + = x3> = 0, "MinCarboneRequirement3"
prob + = x4> = 0, "MinCarboneRequirement4"
prob + = x5> = 0, "MinCarboneRequirement5"
prob + = x6> = 0, "MinCarboneRequirement6"
prob + = x7> = 0, "MinCarboneRequirement7"

# MIN constraints of% copper, by alloy // ITS WRONG ITS NOT WHAT I NEED
prob + = x1> = 0, "MinCuivreRequirement1"
prob + = x2> = 0, "MinCuivreRequirement2"
prob + = x3> = 0.3, "MinCuivreRequirement3"
prob + = x4> = 90, "MinCuivreRequirement4"
prob + = x5> = 96, "MinCuivreRequirement5"
prob + = x6> = 0.4, "MinCuivreRequirement6"
prob + = x7> = 0.6, "MinCuivreRequirement7"

# MIN constraints of% of Manganese, by alloy // ITS WRONG ITS NOT WHAT I NEED
prob + = x1> = 1.3, "MinManganeseRequirement1"
prob + = x2> = 0.8, "MinManganeseRequirement2"
prob + = x3> = 0, "MinManganeseRequirement3"
prob + = x4> = 0, "MinManganeseRequirement4"
prob + = x5> = 4, "MinManganeseRequirement5"
prob + = x6> = 1.2, "MinManganeseRequirement6"
prob + = x7> = 0, "MinManganeseRequirement7"

# MAX constraints of% of Manganese, by alloy // ITS WRONG ITS NOT WHAT I NEED
prob + = x1 <= 1.3, "MaxManganeseRequirement1"
prob + = x2 <= 0.8, "MaxManganeseRequirement2"
prob + = x3 <= 0, "MaxManganeseRequirement3"
prob + = x4 <= 0, "MaxManganeseRequirement4"
prob + = x5 <= 4, "MaxManganeseRequirement5"
prob + = x6 <= 1.2, "MaxManganeseRequirement6"
prob + = x7 <= 0, "MaxManganeseRequirement7"


# 5. MAX constraints from available stock, by alloy // I THINK IT IS OK
prob + = x1 <= 4000, "MaxStock"
prob + = x2 <= 3000, "MaxStock1"
prob + = x3 <= 6000, "MaxStock2"
prob + = x4 <= 5000, "MaxStock3"
prob + = x5 <= 2000, "MaxStock4"
prob + = x6 <= 3000, "MaxStock5"
prob + = x7 <= 2500, "MaxStock6"



# The problem data is written to an .lp file
prob.writeLP ( "WhiskasModel.lp")

# We use the solver
prob.solve ()

# The status of the solution
print ("Status:", LpStatus [prob.status])

# We magnify and display the optimums of each var
for v in prob.variables ():
    print (v.name, "=", v.varValue)

# The result of the objective function is here
print ("Total", value (prob.objective))

这是答案,但当然,这是错误的,因为我不知道如何做约束:

Status: Optimal
Aluminum_alloy_1 = 1.2
Aluminum_alloy_2 = 0.6
Copper_alloy_1 = 90.0
Alloy_of_copper_2 = 96.0
Alloy_of_fer_1 = 2.5
Alloy_of_fer_2 = 3.0
Iron_alloy_3 = 4806.7
Total 4,591.76,999,999,999,995

编辑你好! 这是我的代码的改进版本 2,对不起,它是法语,但我打赌你能明白我的意思,它仍然不起作用,想......但更接近我需要的:

Mining and metals

In the manufacture of steel with permeable materials, sur wants to reduce the cost of producing this steel
to earn more money but still respecting the important characteristics of quality steel



    # Characteristics of the steel to be made



    """ Elément     % minimal   % Max   
    Carbone             2         3 
    Cuivre              0.4      0.6    
    Manganèse           1.2      1.65 

     """
    # Characteristics, stocks and purchase price of alloys at KILO
    """ 
    Alliage             C %     Cu %    Mn %    Stocks kg   Prix €/kg
    Alliage de fer 1    2,50    0,00    1,30    4000        1,20
    Alliage de fer 2    3,00    0,00    0,80    3000        1,50
    Alliage de fer 3    0,00    0,30    0,00    6000        0,90
    Alliage de cuivre 1 0,00    90,00   0,00    5000        1,30
    Alliage de cuivre 2 0,00    96,00   4,00    2000        1,45
    Alliage d'alu 1     0,00    0,40    1,20    3000        1,20
    Alliage d'alu 2     0,00    0,60    0,00    2500        1,00 
    """

    # Importer la lib PuLP 
    from pulp import *

    #Créer la variable du problème
    prob = LpProblem("MinimiserLpAlliage",LpMinimize)

    # The 7 vars have a zero limit, these decision variables are expressed in KILOS
    x1 = LpVariable("Alliage de fer 1",0)
    x2 = LpVariable("Alliage de fer 2",0)
    x3 = LpVariable("Alliage de fer 3",0)
    x4 = LpVariable("Alliage de cuivre 1",0)
    x5 = LpVariable("Alliage de cuivre 2",0)
    x6 = LpVariable("Alliage d'alu 1",0)
    x7 = LpVariable("Alliage d'alu 2",0)


    # The objective function is to minimize the total cost of the alloys in EUROS


    prob += 1.20 * x1 + 1.50 * x2 + 0.90 * x3 + 1.30 * x4 + 1.45 * x5 + 1.20 * x6 + 1.00 * x7, "CoutAlliages"

    # Quantity constraint in KGS.
    prob += x1 + x2 + x3 + x4 + x5 + x6 + x7 == 5000, "QuantitéDemandée"

    # Carbon stress.
    prob += (2.50 * x1  + 3.00 * x2 + x3 + x4 + x5 + x6 + x7 ) / 5000 <= 3,"carBmax"
    prob += (2.50 * x1  + 3.00 * x2 + x3 + x4 + x5 + x6 + x7 ) / 5000 >= 2,"carBmin"

    # Constraint cu  .
    prob += (x1 + x2 + 0.30 * x3 +  90 * x4  +  96 * x5 + 0.40 * x6 + 0.60 * x7) / 5000 <= 0.6,"cuBmax"
    prob += (x1 + x2 + 0.30 * x3 +  90 * x4  +  96 * x5 + 0.40 * x6 + 0.60 * x7) / 5000 >= 0.4,"cuBmin"

    # Constraint Manganèse.
    prob += (1.30 * x1 + 0.80 * x2 + x3 + x4  + 4 *  x5  + 1.20 * x6 + x7 ) / 5000 <= 1.65,"mgBmax"
    prob += (1.30 * x1 + 0.80 * x2 + x3 + x4  + 4 *  x5  + 1.20 * x6 + x7 ) / 5000 >= 1.2,"mgBmin"

    # 5. MAX constraints from available stock, by alloy
    prob += x1 <= 4000 , "MaxStock"
    prob += x2 <= 3000 , "MaxStock1"  
    prob += x3 <= 6000  , "MaxStock2"  
    prob += x4 <= 5000 , "MaxStock3"   
    prob += x5 <= 2000 , "MaxStock4" 
    prob += x6 <= 3000  , "MaxStock5"
    prob += x7 <= 2500  , "MaxStock6"


    # The problem data is written to an .lp file
    prob.writeLP("acier.lp")

    # On utilise le solveur
    prob.solve()

    # The status of the solution
    print ("Status:", LpStatus[prob.status])

    # We magnify and display the optimums of each var
    for v in prob.variables():
        print (v.name, "=", v.varValue)

    # The result of the objective function is here
    print ("Total payable in euros", value(prob.objective))

    """ Status: Infeasible
    Alliage_d'alu_1 = 0.0
    Alliage_d'alu_2 = 0.0
    Alliage_de_cuivre_1 = 0.0
    Alliage_de_cuivre_2 = 0.0
    Alliage_de_fer_1 = 0.0
    Alliage_de_fer_2 = 0.0
    Alliage_de_fer_3 = 10000.0
    Total à payer en euros 9000.0 """
 The book says the result with the excel solver is : iron_1 : 4000 kgs iron_2 : 0 kgs iron_3 : 397.76kgs cu_1 : 0 kgs cu_2 : 27.61kgs al_1 : 574.62kgs al_2 : 0kgs Cost in euros 5887.57 Steel contains 2% carb, 0.6 % cu, 1.2 %

Excel 选项卡: excel图片

求解器图片: 求解器图片

您的部分问题在于您如何理解/应用百分比。 我的建议是尽早将百分比 [0-100] 转换为小数 [0-1.0]。

在 excel 中,当单元格显示50%时,单元格的数值实际上是0.5 以这种方式处理百分比意味着您不必一直除以 100,并且可以将一个百分比与另一个百分比相乘,这一切都正常。

下面的代码做你想要的:

"""
 Mining and metals

We make steel with raw materials, we want to reduce the cost of producing this steel
to make more money, but still respecting the minimum characteristics of quality steel

"""

# Minimize the cost of metal alloys.
# Characteristics of the steel to be made

"""Element      %Minimum  %Max   %Real (it is a var)
   Carbon       2         3      2.26
   Copper       0.4       0.6    0.60
   Manganese    1.2       1.65   1.20

"""

# Characteristics, stocks and purchase price of alloys
"""
Alloy          C%   Cu%   Mn%     Stocks kg Price € / kg
Iron alloy     2.50 0.00  1.30    4000      1.20
Iron alloy     3.00 0.00  0.80    3000      1.50
Iron alloy     0.00 0.30  0.00    6000      0.90
Copper alloy   0.00 90.00 0.00    5000      1.30
Copper alloy   0.00 96.00 4.00    2000      1.45
Aluminum alloy 0.00 0.40  1.20    3000      1.20
Aluminum alloy 0.00 0.60  0.00    2500      1.00
"""

# Import the PuLP lib
from pulp import *

# Create the problem variable
prob = LpProblem ("MinimiserLpAlliage", LpMinimize)

# Problem Data
input_mats = ["iron_1", "iron_2", "iron_3",
              "cu_1", "cu_2",
              "al_1", "al_2"]

input_costs = {"iron_1": 1.20, "iron_2": 1.50, "iron_3": 0.90,
               "cu_1":   1.30, "cu_2": 1.45,
               "al_1":   1.20, "al_2":   1.00}

#                               C%     Cu%   Mn%
input_composition = {"iron_1": [0.025, 0.000,  0.013],
                     "iron_2": [0.030, 0.000,  0.008],
                     "iron_3": [0.000, 0.003,  0.000],
                     "cu_1":   [0.000, 0.900,  0.000],
                     "cu_2":   [0.000, 0.960,  0.040],
                     "al_1":   [0.000, 0.004,  0.012],
                     "al_2":   [0.000, 0.006,  0.000]}

input_stock = {"iron_1": 4000, "iron_2": 3000, "iron_3": 6000,
               "cu_1": 5000, "cu_2":  2000,
               "al_1": 3000, "al_2": 2500}

request_quantity = 5000

Carbon_min = 0.02
Carbon_max = 0.03

Cu_min = 0.004
Cu_max = 0.006

Mn_min = 0.012
Mn_max = 0.0165

# Problem variables - amount in kg of each input
x = LpVariable.dicts("input_mat", input_mats, 0)

# The objective function is to minimize the total cost of the alloys in EUROS for a given quantity in KGS
prob += lpSum([input_costs[i]*x[i] for i in input_mats]), "AlliageCost"

# Quantity constraint in KGS.
prob += lpSum([x[i] for i in input_mats]) == request_quantity, "RequestedQuantity"

# MIN/MAX constraint of carbon in resultant steel
prob += lpSum([x[i]*input_composition[i][0] for i in input_mats]) >= Carbon_min*request_quantity, "MinCarbon"
prob += lpSum([x[i]*input_composition[i][0] for i in input_mats]) <= Carbon_max*request_quantity, "MaxCarbon"

# MIN/MAX constraints of copper in resultant steel
prob += lpSum([x[i]*input_composition[i][1] for i in input_mats]) >= Cu_min*request_quantity, "MinCu"
prob += lpSum([x[i]*input_composition[i][1] for i in input_mats]) <= Cu_max*request_quantity, "MaxCu"

# MIN/MAX constraints of manganese in resultant steel
prob += lpSum([x[i]*input_composition[i][2] for i in input_mats]) >= Mn_min*request_quantity, "MinMn"
prob += lpSum([x[i]*input_composition[i][2] for i in input_mats]) <= Mn_max*request_quantity, "MaxMn"


# MAX constraints of available stock
for i in input_mats:
    prob += x[i] <= input_stock[i], ("MaxStock_" + i)

# Solve the problem
prob.solve()

# The status of the solution
print ("Status:", LpStatus [prob.status])

# Dislay the optimums of each var
for v in prob.variables ():
    print (v.name, "=", v.varValue)

# Display mat'l compositions
Carbon_value = sum([x[i].varValue*input_composition[i][0] for i in input_mats])/request_quantity
Cu_value = sum([x[i].varValue*input_composition[i][1] for i in input_mats])/request_quantity
Mn_value = sum([x[i].varValue*input_composition[i][2] for i in input_mats])/request_quantity

print ("Carbon content: " + str(Carbon_value))
print ("Copper content: " + str(Cu_value))
print ("Manganese content: " + str(Mn_value))

# The result of the objective function is here
print ("Total", value (prob.objective))

我从中得到:

Status: Optimal
input_mat_al_1 = 574.62426
input_mat_al_2 = 0.0
input_mat_cu_1 = 0.0
input_mat_cu_2 = 27.612723
input_mat_iron_1 = 4000.0
input_mat_iron_2 = 0.0
input_mat_iron_3 = 397.76302
Carbon content: 0.02
Copper content: 0.006000000036
Manganese content: 0.012000000008
Total 5887.57427835

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM