我想创建一个二进制变量的二维矩阵
x
。现在我这样做:
x = IndexedBase('x', shape=(imax,jmax), integer=True)
对于二元变量,以下恒等式成立:
x_i**n == x_i
代表n>0
,我想利用这个恒等式来简化稍后的表达式。因此,“整数”假设应替换为“更强”的“二元”假设。
创建单个二进制变量是可行的(参考:https://stackoverflow.com/a/73953040/7740977):
from sympy import *
class Binary(Symbol):
def _eval_power(self, other):
return self
x0 = Binary('x0')
x0**2 == x0
输出:
True
我现在正在努力创建一个
IndexedBase
对象,其中它的条目是我的 Binary
类的实例而不是 Symbol
的实例。查看 https://docs.sympy.org/latest/modules/tensor/indexed.html#sympy.tensor.indexed.IndexedBase 我发现如果使用 Symbol 来初始化 IndexedBase
,则可以继承假设,这导致我尝试以下方法失败:
x = symbols('x', cls=Binary)
x = IndexedBase(x)
x[0,0]**2 == x[0,0]
输出:
False
(预期True
)
还有其他方法让
IndexedBase
使用我的自定义 Binary
类吗?
提前非常感谢!
这是一种不同的策略,但您可以不定义自定义
Symbol
属性,而可以 .replace()
取幂
Symbol
可以简化Wild
,但不会匹配嵌套实例class Binary(Symbol):
pass
a = Wild("a", properties=[lambda a: isinstance(a, Indexed) and a.atoms(Binary)])
b = Wild("b", properties=[lambda b: isinstance(b, Number)])
现在设置问题并使用
.replace()
>>> x = Binary("x")
>>> A = IndexedBase(x)
>>> expr
x[0, 0]
>>> expr = expr**2
>>> expr
x[0, 0]**2
>>> srepr(expr) # NOTE the Indexed wrapper
"Pow(Indexed(IndexedBase(Binary('x')), Integer(0), Integer(0)), Integer(2))"
>>> expr.replace(Pow(a, b), lambda a, b: a)
x[0, 0]
如果您要将其传递给其他人,请考虑使用自定义函数以使其看起来更干净和文档字符串,但是
.replace()
+ Wild
非常强大,可以触及各种表达式
>>> expr = Integral(5*A[0,0]**2 + sin(A[0,1]**3), x) # not meaningful
>>> expr
Integral(sin(x[0, 1]**3) + 5*x[0, 0]**2, x)
>>> expr.replace(Pow(a, b), lambda a, b: a)
Integral(sin(x[0, 1]) + 5*x[0, 0], x)