生成器表达式在具有纸浆的线性规划约束中不按预期工作

2024-06-16 12:11:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用纸浆来解决这个最小化问题

我们有一包一包的芒果,每包都有一个类别、年龄和芒果的数量

# 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)

但我们现在还有两个限制:

  1. 挑选的数据包不应来自两个以上的类别
  2. 拾取的任何两个数据包之间的年龄差不应大于25岁

我在下面添加了限制,以限制类别的数量。这基本上是计算独特的类别,并确保其应小于或等于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
    }
}

Tags: ofnameinagecountpackpulpyes
1条回答
网友
1楼 · 发布于 2024-06-16 12:11:36

我不认为你可以将集合的大小求和,并将其作为约束条件呈现给解算器……所以这可能是该语句的问题所在

您需要重新格式化模型,并为切换约束添加另一个索引变量。切换约束应为二进制值,按不同类别索引

您应该使用如下内容启用变量:(伪代码)

x[pack, cat] <= u[pack, cat]*y[cat]

其中x[pack,cat]是从一个包装中选择的一个类别的芒果数量,u[cat]是该类别包装中可用的最大数量(或仅是该类别整体的最大数量),如果选择该类别,y[cat]是二进制的

然后限制类别的数量(伪代码)

sum(y[cat]) <= 2

对于这个时代。。。你应该考虑在你的包中复制一个索引,这样你就可以比较所有的差异

相关问题 更多 >