如何使用 Symbol 的自定义子类创建 Sympy IndexedBase?

问题描述 投票:0回答:1

我想创建一个二进制变量的二维矩阵

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
类吗?

提前非常感谢!

python binary sympy symbolic-math
1个回答
0
投票

这是一种不同的策略,但您可以不定义自定义

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