or-tools module in python adds custom syntax where functions can take arbitrary expressions as arguments (something like below), which is evaluated not instantaneously but solved as a constraint later
model.Add(x + 2 * y -1 >= z)
When I print the type of the argument from my function, it shows
<class 'ortools.sat.python.cp_model.BoundedLinearExpression'>
A simple way is to pass the expression as a string, but it feels better. I wish to understand how this is achieved. Is this a way to create custom syntax in python? Does it require updating the parser or something like that?
Here is the simple program
from ortools.sat.python import cp_model
def foo(expr):
print(expr, type(expr))
def main():
model = cp_model.CpModel()
var_upper_bound = max(50, 45, 37)
x = model.NewIntVar(0, var_upper_bound, 'x')
y = model.NewIntVar(0, var_upper_bound, 'y')
z = model.NewIntVar(0, var_upper_bound, 'z')
a = 0
b = 0
c = 0
model.Add(2*x + 7*y + 3*z == 50)
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL:
print('x value: ', solver.Value(x))
print('y value: ', solver.Value(y))
print('z value: ', solver.Value(z))
foo(2*x + 7*y + 3*z == 50)
foo(2*a + 7*b + 3*c == 50)
if __name__ == '__main__':
main()
x, y, z are special variables (instances of some class) and the expression with x, y, z is stored as expression
a, b, c are simple integers and the expression is evaluated immediately and the result is stored as a bool
They override the python operators.
References:
def __mul__(self, arg):
if isinstance(arg, numbers.Integral):
if arg == 1:
return self
elif arg == 0:
return 0
cp_model_helper.AssertIsInt64(arg)
return _ProductCst(self, arg)
else:
raise TypeError('Not an integer linear expression: ' + str(arg))