pythonor-toolsconstraint-programmingcp-sat

How does constraint parameters look for a string and compare string length? (python)


I am currently trying to learn constraint programming. I am trying to add some conditions to the model that is a string, and a length both should satisfy the model but for some reason it does not. This is the code :

from ortools.sat.python import cp_model

# Create model
model = cp_model.CpModel()

number_choices = []
for i in range(5):
    # numbers from 1 to max_value
    number_choices.append(model.NewIntVar(1, 5, f"number {i}"))

model.Add(sum(number_choices) == 12)

# - this works
# model.Add(number_choices[1] - number_choices[0] == 2)

# - this should satisfy the model but does not work
model.Add(str(number_choices[1] - number_choices[0]) == "2")
model.Add(len(str(number_choices[1] - number_choices[0])) == 1)

solver = cp_model.CpSolver()
status = solver.Solve(model)

if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
    print([solver.Value(v) for v in number_choices])
else:
    print(None)  # no solution found

If you uncomment the condition with length and string, this would be the result :

[1, 3, 5, 2, 1]

so 3 - 1 = 2, 2 has a length of 1. I am quite confused as to why this does not satisfy the condition. Sorry if this impossible, I am new to constraint programming


Solution

  • When using constraint programming, you have to stay within the supported operations for the variables. Constraints that are added need to be constructed from variables and expressions built from those variables.

    In your particular code, the misunderstanding is that calling str on a integer model variable or an expression will not return a string variable, it will return a string representation of that variable or expression. OR-Tools does not support string variables (very few constraint programming systems do, it is mostly a research area).

    To understand this more, instead of model.Add(str(number_choices[1] - number_choices[0]) == "2"), you can print out the expression str(number_choices[1] - number_choices[0]) to see what it is and see that it will always be different from the string "2". Thus, the whole line is essentially equivalent to model.Add(False) which fails the whole model.