PuLP:规范化多个决策变量并分配权重

Posted

技术标签:

【中文标题】PuLP:规范化多个决策变量并分配权重【英文标题】:PuLP: Normalizing multiple decision variables and assigning weights 【发布时间】:2021-10-02 08:12:39 【问题描述】:

我有 4 组不同规模的决策变量。

dgp, dgm, (y_s1+y_s2), v

dgp, dgm, (y_s1+y_s2) 低于 1000 v 在 6000 到 16000 的范围内。 我想为目标函数中的 4 个变量中的每一个分配一定的权重,并考虑在添加权重之前将每个变量标准化为 0 到 1 之间。 你能告诉我应该怎么做吗?

from pulp import *

prob = LpProblem("SupplyAllocation", LpMinimize)

pairs = [(m, p) for m in month for p in part]

supply_s1 = LpVariable.dicts("supply_s1", (month, part), lowBound=0, cat='Continuous')
supply_s2 = LpVariable.dicts("supply_s2", (month, part), lowBound=0, cat='Continuous')
eoh = LpVariable.dicts("eoh", (month, part), lowBound=0, cat='Continuous')
v = LpVariable.dicts("cost", (part), lowBound=-100000, cat='Continuous')
w = LpVariable.dicts("w", (part), lowBound=-100000, cat='Continuous')
y_s1max = LpVariable.dicts("deltay_s1max", (part), lowBound=-100000, cat='Continuous')
y_s2max = LpVariable.dicts("deltay_s2max", (part), lowBound=-100000, cat='Continuous')
y_s1min = LpVariable.dicts("deltay_s1min", (part), lowBound=-100000, cat='Continuous')
y_s2min = LpVariable.dicts("deltay_s2min", (part), lowBound=-100000, cat='Continuous')
y_s1 = LpVariable.dicts("deltay_s1", (part), lowBound=-100000, cat='Continuous')
y_s2 = LpVariable.dicts("deltay_s2", (part), lowBound=-100000, cat='Continuous')
y_s = LpVariable.dicts("deltay_sall", (part), lowBound=-100000, cat='Continuous')
dgp = LpVariable.dicts("doigap_part", (part), lowBound=0, cat='Continuous')
dgm = LpVariable.dicts("doigap_mth", (month), lowBound=0, cat='Continuous')
z = LpVariable.dicts("z", (month, part), lowBound=0, cat='Continuous')
z1 = LpVariable.dicts("z1", (month, part), lowBound=-100000, cat='Continuous')
u1 = LpVariable.dicts("util_s1", (month, process), lowBound=-100000, cat='Continuous')
u2 = LpVariable.dicts("util_s2", (month, process), lowBound=-100000, cat='Continuous')
totcost = LpVariable("total_cost", lowBound = 0, cat='Continuous')
totgapp = LpVariable("total_gapp", lowBound = 0, cat='Continuous')
totgapm = LpVariable("total_gapm", lowBound = 0, cat='Continuous')
totrangep = LpVariable("total_rangep", lowBound = 0, cat='Continuous')
scalegapp = LpVariable("scalegapp", lowBound = 0, cat='Continuous')

prob += lpSum([dgp[p] for p in part])*1 + lpSum([dgm[m] for m in month])*1 + lpSum([y_s1[p]+y_s2[p] for p in part])*1 + lpSum([v[p] for p in part])*1


for p in part:
    for m in month:

        if month.index(m)==0:
            prob += eoh[m][p] == boh[part.index(p)] + supply_s1[m][p] + supply_s2[m][p] - demand[month.index(m)][part.index(p)]
        if month.index(m)>0:
            prob += eoh[m][p] == eoh[month[month.index(m)-1]][p] + supply_s1[m][p] + supply_s2[m][p] - demand[month.index(m)][part.index(p)]

        prob += z[m][p] >= - eoh[m][p] + target_eoh[month.index(m)][part.index(p)]
        prob += z[m][p] >=  eoh[m][p] - target_eoh[month.index(m)][part.index(p)]

        prob += dgp[p] >= z[m][p]
        prob += y_s1max[p] >= supply_s1[m][p]
        prob += y_s1min[p] <= supply_s1[m][p]
        prob += y_s2max[p] >= supply_s2[m][p]
        prob += y_s2min[p] <= supply_s2[m][p]
        
        prob += eoh[m][p] >= 0 
        
        prob += (supply_s2[m][p] * (alloc_max[month.index(m)][part.index(p)]/(1-alloc_max[month.index(m)][part.index(p)]))) - supply_s1[m][p] >= 0
        prob += supply_s1[m][p] -  (supply_s2[m][p] * (alloc_min[month.index(m)][part.index(p)]/(1-alloc_min[month.index(m)][part.index(p)]))) >= 0
        
        prob += (supply_s1[m][p] * (alloc_max[month.index(m)][part.index(p)]/(1-alloc_max[month.index(m)][part.index(p)]))) - supply_s2[m][p] >= 0
        prob += supply_s2[m][p] -  (supply_s1[m][p] * (alloc_min[month.index(m)][part.index(p)]/(1-alloc_min[month.index(m)][part.index(p)]))) >= 0
        
for p in part:
    prob += lpSum(supply_s1[m][p] + supply_s2[m][p] for m in month) >= tot_supply_min[part.index(p)]
    prob += v[p] == [supply_s1[m][p]*price_s1[part.index(p)] for m in month]+ [supply_s2[m][p]*price_s2[part.index(p)] for m in month]
    prob += y_s1[p] >= y_s1max[p] - y_s1min[p]
    prob += y_s2[p] >= y_s2max[p] - y_s2min[p]
    prob += y_s[p] >= y_s1[p]
    prob += y_s[p] >= y_s2[p]
    
for m in month:
    for p in part:
        prob += dgm[m] >= z[m][p]
    
for m in month:
    for pr in process:
        prob += u1[m][pr] == lpSum(supply_s1[m][p] * steps_s1[process.index(pr)][part.index(p)] for p in part) / cap[process.index(pr)][supplier.index('S1')]
        prob += u1[m][pr] <= 1
        prob += u2[m][pr] == lpSum(supply_s2[m][p] * steps_s2[process.index(pr)][part.index(p)] for p in part) /  cap[process.index(pr)][supplier.index('S2')]      
        prob += u2[m][pr] <= 1

prob += totcost == lpSum([v[p] for p in part])
prob += totgapp == lpSum([dgp[p] for p in part])
prob += totgapm == lpSum([dgm[m] for m in month])
prob += totrangep == lpSum([y_s1[p]+y_s2[p] for p in part])
    
prob.solve() 
print ("Status:", LpStatus[prob.status])


for (m,p) in pairs:
    solver_s1[m,p] = supply_s1[m][p].varValue
    solver_s2[m,p] = supply_s2[m][p].varValue
    
for p in part:
     cost[p] = v[p].varValue
  
SolverResult = LpStatus[prob.status]

【问题讨论】:

【参考方案1】:

如果和不是常数,归一化不是线性的:

 y[i] = x[i]/sum(x)

PuLP 只做线性程序,所以这很困难。还要注意

    prob += u1[m][pr] <= 1
    prob += u2[m][pr] <= 1

可以通过设置 u1 和 u2 的上限来替换

【讨论】:

以上是关于PuLP:规范化多个决策变量并分配权重的主要内容,如果未能解决你的问题,请参考以下文章

错误代码OpenAI权衡规范化get_variable tf1.4

Python:规范化权重的约束,使得没有权重大于 1/sqrt(n)

JavaScript的代码编写规范自检列表(add......)

读取简单数据声明并以分配给该变量的内存量响应的程序

Python数模笔记-PuLP库线性规划进阶

企业决策规范步骤