python 创建自定义语法

问题描述 投票:0回答:2
python 中的

or-tools 模块添加了自定义语法,其中函数可以采用任意表达式作为参数(如下所示),该语法不是立即求值,而是稍后作为约束解决

model.Add(x + 2 * y -1 >= z)

当我从函数中打印参数类型时,它会显示

<class 'ortools.sat.python.cp_model.BoundedLinearExpression'>

一种简单的方法是将表达式作为字符串传递,但感觉更好。我想了解这是如何实现的。这是在 python 中创建自定义语法的方法吗?是否需要更新解析器或类似的东西?

这是简单的程序

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 是特殊变量(某个类的实例),带有 x、y、z 的表达式存储为表达式

a、b、c 是简单整数,立即计算表达式并将结果存储为 bool

python syntax or-tools cp-sat
2个回答
5
投票

它们覆盖了 python 运算符。

参考资料:

    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))

1
投票

or-tools 模块为模型变量定义了自己的类,并且在类定义中,该模块定义了将运算符应用于这些类的方法。

作为一个简单的例子,我们可以定义自己的类以及“+”的方法。

# 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.'
© www.soinside.com 2019 - 2024. All rights reserved.