or-toolsconstraint-programmingcp-sat

How to pick an element from matrix (list of list in python) based on decision variables (one for row, and one for column) | OR-Tools, Python


I am new to constraint programming and OR-Tools. A brief about the problem. There are 8 positions, for each position I need to decide which move of type A (move_A) and which move of type B (move_B) should be selected such that the value achieved from the combination of the 2 moves (at each position) is maximized. (This is only a part of the bigger problem though). And I want to use AddElement approach to do the sub setting.

Please see the below attempt

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

# value achieved from combination of different moves of type A
# (moves_A (rows)) and different moves of type B (moves_B (columns))
# for e.g. 2nd move of type A and 3rd move of type B will give value = 2
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]
       ]

# 6 moves of type A
num_moves_A = len(value)

# 5 moves of type B
num_moves_B = len(value[0])

num_positions = 8

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

value_position = [model.NewIntVar(0, 10, f"value_position[{i}]") for i in range(num_positions)]

# I am getting an error when I run the below
objective_terms = []
for i in range(num_positions):
    model.AddElement(type_move_B_position[i], value[type_move_A_position[i]], value_position[i])
    objective_terms.append(value_position[i])

The error is as follows:

Traceback (most recent call last):

  File "<ipython-input-65-3696379ce410>", line 3, in <module>
    model.AddElement(type_move_B_position[i], value[type_move_A_position[i]], value_position[i])

TypeError: list indices must be integers or slices, not IntVar

In MiniZinc the below code would have worked

var int: obj = sum(i in 1..num_positions ) (value [type_move_A_position[i], type_move_B_position[i]])

I know in OR-Tools we will have to create some intermediary variables to store results first, so the above approach of minizinc will not work. But I am struggling to do so.

I can always create a 2 matrix of binary binary variables one for num_moves_A * num_positions and the other for num_moves_B * num_positions, add re;evant constraints and achieve the purpose

But I want to learn how to do the same thing via AddElement constraint

Any help on how to re-write the AddElement snippet is highly appreciated. Thanks.


Solution

  • AddElement is 1D only. The way it is translated from minizinc to CP-SAT is to create an intermediate variable p == index1 * max(index2) + index2 and use it in an element constraint with a flattened matrix.