1

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

2
  • I see the OR source code but I don't know how to make an example to reproduce what you are seeing when you "print the type of the argument". Please can you edit the question to show a short code snippet that will produce the output shown in your question? Commented Sep 12, 2021 at 7:34
  • Note that BoundedLinearExpression have an str method, but not a repr one. So str(x + 2 *y - 1 >= z) should be be pretty-printed. Commented Sep 12, 2021 at 11:33

2 Answers 2

5

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))
Sign up to request clarification or add additional context in comments.

Comments

1

The or-tools module defines its own classes for model variables, and within the class definitions the module defines methods for applying operators to those classes.

As a trivial example we can define our own class along with a method for '+'.

# New class will normally not support math operators.
class Blah(object):
    def __init__(self, context):
        self.context = context

    def __add__(self, value):
        # Support '+' operator with class Blah.
        return self.context.format(value)

x = Blah("Chocolate with {} is the result.")

# '*' operator is not supported.
x * 2
# Traceback (most recent call last):
#
#   File "<ipython-input-26-80b83cb135a7>", line 1, in <module>
#     x * 2
#
# TypeError: unsupported operand type(s) for *: 'Blah' and 'int'

# '+' operator is implemented for class Blah.
x + 3
# 'Chocolate with 3 is the result.'

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.