我试图用纸浆来解决这个最小化问题
我们有一包一包的芒果,每包都有一个类别、年龄和芒果的数量
# Packet Names and the count, category and age of mangoes in each packet.
mango_packs = {
"pack_1": {
"count": 5,
"category": "pack",
"age": 10
},
"pack_2": {
"count": 9,
"category": "pack",
"age": 10
},
"bag_2": {
"count": 5,
"category": "bag",
"age": 20
},
"sack_1": {
"count": 5,
"category": "sack",
"age": 5
},
}
我们将需要大量芒果。(这将是一个整数)。 我们的目标是以较少残留芒果的方式提供包装。 例如,如果需求量为10,则我们为该包提供10个芒果。如果没有,则提供2包,每包5个芒果。如果我们只有3包,每包5、7和6个芒果,那么我们提供的是5和6个芒果,所以我们只有1个剩余。下面的代码正是我们需要的
对于需求15,它将给出以下输出
Status: Optimal
OpenPack_bag_2? yes
OpenPack_pack_1? yes
OpenPack_pack_2? no
OpenPack_sack_1? yes
import pulp
def optimise(mango_packs, mango_count):
pack_names = list(mango_packs.keys())
prob = pulp.LpProblem("MangoPacks", pulp.LpMinimize)
# variables: names of the mango packs. We can either open them or not (0/1)
lp_pack_vars = pulp.LpVariable.dicts("OpenPack", pack_names, 0, 1, "Integer")
# objective: minimise total count of mangoes in the selected packs (so to
# minimise remnants). In case of a tie, minimise the number of opened packs.
prob += (
pulp.lpSum([mango_packs[name]["count"] * lp_pack_vars[name]
for name in pack_names]) * len(mango_packs) + pulp.lpSum(
[lp_pack_vars[name] for name in pack_names]))
# constraint 1: the opened packs need to amount to a minimum number of mangos
prob += pulp.lpSum(
[mango_packs[name]["count"] * lp_pack_vars[name]
for name in pack_names]) >= mango_count
# Packets should not be from more than 2 category.
# prob += len(set([mango_packs[name]["category"] for name in pack_names if lp_pack_vars[name] == 1 ])) <= 1
prob.solve()
print("Status:", pulp.LpStatus[prob.status])
# Each of the variables is printed with it's resolved optimum value
for i, v in enumerate(prob.variables()):
print("{}? {}".format(v.name, ("no", "yes")[int(v.varValue)]))
# Packet Names and the count of mangoes in each packet.
mango_packs = {
"pack_1": {
"count": 5,
"category": "pack",
"age": 10
},
"pack_2": {
"count": 9,
"category": "pack",
"age": 10
},
"bag_2": {
"count": 5,
"category": "bag",
"age": 20
},
"sack_1": {
"count": 5,
"category": "sack",
"age": 5
},
}
optimise(mango_packs, 15)
但我们现在还有两个限制:
我在下面添加了限制,以限制类别的数量。这基本上是计算独特的类别,并确保其应小于或等于2
prob += len(set([mango_packs[name]["category"] for name in pack_names if lp_pack_vars[name] == 1 ])) <= 2
但这不起作用,在这样做的同时,它给出了一个阶段输出,即打开所有芒果,然后是一个异常
Status: Optimal
OpenPack_bag_2? yes
OpenPack_pack_1? yes
OpenPack_pack_2? yes
OpenPack_sack_1? yes Traceback (most recent call last):
File "main.py", line 61, in
optimise(mango_packs, 15)
File "main.py", line 34, in optimise
print("{}? {}".format(v.name, ("no", "yes")[int(v.varValue)]))
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
由于某种原因,生成器表达式中的if条件似乎总是返回True。不太确定
如何解决这个问题?我们需要添加新的2个约束
没有2个新约束的工作代码可以从这里运行:https://repl.it/@VinodM1/OptimumMangoes
编辑: 相同的数据在这里表示不同,如果它有助于尝试解决方案的人,因为我相信我们需要重新构建模型以找到解决方案
mango_packs_cat = {
"cat_pack": {
"packets": {
"pack_1": {
"name": "pack_1",
"count": 5
},
"pack_2": {
"name": "pack_2",
"count": 9
}
},
"age": 10
},
"cat_bag": {
"packets":{
"bag_1":{
"name": "bag_1",
"count": 5
}
},
"age": 20
},
"cat_sack": {
"packets":{
"sack_1":{
"name": "sack_1",
"count": 5
}
},
"age": 5
}
}
我不认为你可以将集合的大小求和,并将其作为约束条件呈现给解算器……所以这可能是该语句的问题所在
您需要重新格式化模型,并为切换约束添加另一个索引变量。切换约束应为二进制值,按不同类别索引
您应该使用如下内容启用变量:(伪代码)
其中x[pack,cat]是从一个包装中选择的一个类别的芒果数量,u[cat]是该类别包装中可用的最大数量(或仅是该类别整体的最大数量),如果选择该类别,y[cat]是二进制的
然后限制类别的数量(伪代码)
对于这个时代。。。你应该考虑在你的包中复制一个索引,这样你就可以比较所有的差异
相关问题 更多 >
编程相关推荐