python 创建自定义语法
python creating custom syntax
or-tools python 中的模块添加了自定义语法,其中函数可以将任意表达式作为参数(如下所示),它不是即时计算的,而是稍后作为约束解决的
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是特殊变量(某些class的实例),x,y,z的表达式存储为expression
a、b、c 是简单整数,立即计算表达式并将结果存储为 bool
它们会覆盖 python 运算符。
参考文献:
- https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
- https://github.com/google/or-tools/blob/b37d9c786b69128f3505f15beca09e89bf078a89/ortools/sat/python/cp_model.py#L212-L233
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))
or-tools 模块为模型变量定义了自己的 classes,并且在 class 定义中,模块定义了将运算符应用于那些 classes 的方法。
作为一个简单的例子,我们可以定义我们自己的 class 以及“+”的方法。
# 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.'
or-tools python 中的模块添加了自定义语法,其中函数可以将任意表达式作为参数(如下所示),它不是即时计算的,而是稍后作为约束解决的
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是特殊变量(某些class的实例),x,y,z的表达式存储为expression
a、b、c 是简单整数,立即计算表达式并将结果存储为 bool
它们会覆盖 python 运算符。
参考文献:
- https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
- https://github.com/google/or-tools/blob/b37d9c786b69128f3505f15beca09e89bf078a89/ortools/sat/python/cp_model.py#L212-L233
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))
or-tools 模块为模型变量定义了自己的 classes,并且在 class 定义中,模块定义了将运算符应用于那些 classes 的方法。
作为一个简单的例子,我们可以定义我们自己的 class 以及“+”的方法。
# 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.'