I am trying to solve a basic puzzle by using Google OR-Tools, this is my first try with OR-Tools and I am trying to learn. I completed almost everything and was ready to conclude the program until I came across this problem.
For information my game_board
is a dictionary including entire board, with already given values and not given values that are set to IntVar
.
I have several values in each cell as following:
- Variable, cell is set as
IntVar
which were initially 0 in board, so it will be determined to be filled or not, values are 0 for empty, 1 for filled) - 8, the cell is free connection, indicating this is just a virtual cell added to represent the game in a matrix so cell above this, is connected to cell below it directly
- 9, the cell is a solid block, so it separates its above and below cells.
What I do is, I iterate over the board and I am try to fill water according to gravity (and some other rules), so I assigned A cell should be equal to the cell below it if there is no block between them. However I forgot that, cell below can be full and the cell above can be empty, however with the constraint set above they can only be equal.
I used the part below the set the constraint mentioned above and I have 2 problems at this point.
if (row+1 <= max(row_variable_indices)) and (game_board[(row+1,column)] == 8):
if (game_board[(row+1,column)] == -1):
model.Add(game_board[(row,column)] == game_board[(row+1,column)])
else:
model.Add(game_board[(row,column)] == game_board[(row+2,column)])
I overcame this by other methods, but still wanted to ask how can I differentiate
IntVar
from something else. I can not differentiateIntVar
as checkingIntVar == Int
orIntVar != Int
since thety both returnTrue
for any givenInt
. So I checked if cell is equal to 8 first, if cell is 8 then cell is either a free connection or a variable, and then I checked if cell is -1 as -1 is not used in the board anywhere, it would only choose the variables.My main problem is I need to change this constraint to A cell should be equal to the cell below it if there is no block between them and the cell below is assigned to 0. I tried doing it
.OnlyEnforceIf()
by something like following, but it didn't work and gave following error. How can I solve this. I understand I need to useBoolVar
however I am not sure how to set aBoolVar
for this condition (and for every other cell I have) because if I can not say if a variable A is set to value x, I can not set the bool based on if A is set to x either
model.Add(game_board[(row,column)] == game_board[(row+1,column)]).OnlyEnforceIf(game_board[(row+1,column)] == 1)
Note I actually tried it on some dummy matrix as following:
model.Add(x[(0,0)]==5).OnlyEnforceIf(x[(0,1)]==6)
/usr/local/lib/python3.6/dist-packages/ortools/sat/python/cp_model.py in OnlyEnforceIf(self, boolvar)
607 self.__constraint.enforcement_literal.append(b.Index())
608 else:
--> 609 self.__constraint.enforcement_literal.append(boolvar.Index())
610 return self
611
AttributeError: 'BoundedLinearExpression' object has no attribute 'Index'
Edited to add that, I can not change (or I don't know if I can) my IntVar
variables to BoolVar
variables and check this filling problem, because I also use sum()
somewhere else counting the filled cells of that row/column by adding up the all IntVar
variables of that row/column. I don't think it works in BoolVar
as they don't have a value to be summed up unlike integer value of IntVar
which is summable.