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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.