You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OR-Tools中如何通过AddElement约束按行列决策变量提取矩阵元素

问题解决

你遇到的报错本质是Python原生列表无法使用OR-Tools的IntVar类型作为下标索引,AddElement约束要求第二个入参必须是Python常量列表,因此二维收益表的取值需要做对应调整,这里提供两种基于AddElement的实现方案:

方案1:扁平化收益表+单层AddElement(推荐)

把二维收益表拉平为一维列表,用「A类动作索引 * B类动作总数 + B类动作索引」作为一维表的访问下标,即可直接调用AddElement实现取值:

from ortools.sat.python import cp_model
model = cp_model.CpModel()

# 不同A型动作(行)与B型动作(列)组合对应的收益值
value = [
            [ -1,  5,  3,  2,  2],
            [  2,  4,  2, -1,  1], 
            [  4,  4,  0, -1,  2],
            [  5,  1, -1,  2,  2],
            [  0,  0,  0,  0, 0],
            [  2,  1,  1,  2, 0]
       ]

num_moves_A = len(value)
num_moves_B = len(value[0])
num_positions = 8

# 拉平二维收益表为一维
flat_value = []
for row in value:
    flat_value.extend(row)

type_move_A_position = [model.NewIntVar(0, num_moves_A - 1, f"move_A[{i}]") for i in range(num_positions)]
type_move_B_position = [model.NewIntVar(0, num_moves_B - 1, f"move_B[{i}]") for i in range(num_positions)]
# 注意收益存在-1,变量下界要调整为-1避免约束冲突
value_position = [model.NewIntVar(-1, 10, f"value_position[{i}]") for i in range(num_positions)]

objective_terms = []
for i in range(num_positions):
    # 计算一维表的访问索引
    idx = model.NewIntVar(0, num_moves_A * num_moves_B - 1, f"idx_{i}")
    model.Add(idx == type_move_A_position[i] * num_moves_B + type_move_B_position[i])
    # 调用AddElement取值
    model.AddElement(idx, flat_value, value_position[i])
    objective_terms.append(value_position[i])

# 补充最大化目标
model.Maximize(sum(objective_terms))

方案2:两层AddElement嵌套实现

如果你需要严格通过两层AddElement对应二维表的两次索引,可结合布尔可选约束实现:

# 前面变量定义和方案1一致,仅修改循环部分
objective_terms = []
for i in range(num_positions):
    # 为每个A类动作定义行选择布尔变量
    row_select = [model.NewBoolVar(f"row_select_{i}_{a}") for a in range(num_moves_A)]
    for a in range(num_moves_A):
        model.Add(type_move_A_position[i] == a).OnlyEnforceIf(row_select[a])
        model.Add(type_move_A_position[i] != a).OnlyEnforceIf(row_select[a].Not())
        # 当选中第a行时,用B类索引取对应行的收益
        model.AddElement(type_move_B_position[i], value[a], value_position[i]).OnlyEnforceIf(row_select[a])
    objective_terms.append(value_position[i])

方案1的执行效率远高于方案2,是OR-Tools处理二维表索引的官方推荐写法。

内容的提问来源于stack exchange,提问作者Bhartendu Awasthi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 06:51:02