如何在Google Or Tools中比较set()与list()以实现背包约束?
问题原因
你遇到的报错本质是约束写法不符合Google OR-Tools的使用规则:matrix[i][j]是OR-Tools定义的布尔决策变量,和数值相乘后得到的是OR-Tools内置的表达式对象,不是普通Python数值,无法作为set的可哈希元素,所以直接触发unhashable type: 'ProductCst'报错。
同时你原本的思路(直接比较列表和去重后列表相等)也不适用于线性规划约束定义,所有约束必须转换为OR-Tools支持的线性表达式形式。
可行解决方案
你的需求是「单个箱子中仅能存放同一个物品的一个部分」,本质可以转化为:对每个箱子,属于同一个物品ID的所有拆分部件,最多只能有1个被放入该箱子。
具体实现步骤如下:
- 先将所有物品按所属的物品ID分组,得到每个ID对应的所有物品索引列表
from collections import defaultdict # 按item_id分组,存储每个id对应的物品索引 item_id_groups = defaultdict(list) for item_idx, item_id in enumerate(data['item_ids']): item_id_groups[item_id].append(item_idx)
- 遍历所有箱子和所有物品ID分组,添加约束:同一分组内的物品在单个箱子中的选中数量之和≤1
# 遍历所有箱子 for bin_idx in range(len(data['bin_capacities'])): # 遍历每个物品ID的分组 for group_item_indices in item_id_groups.values(): # 约束:当前分组中,最多1个物品可以放入当前箱子 solver.Add(sum(matrix[item_idx][bin_idx] for item_idx in group_item_indices) <= 1)
说明
该写法完全符合OR-Tools的约束定义规则,能精准实现你的需求:如果同一个物品的两个拆分部分尝试放入同一个箱子,求和结果会等于2,违反≤1的约束,会被求解器自动排除。
内容的提问来源于stack exchange,提问作者pythonislovepythonislife
相关产品推荐
相关产品推荐

