如何使用Symbol的自定义子类创建Sympy IndexedBase,使元素具备二元变量的幂等特性?
如何使用Symbol的自定义子类创建Sympy IndexedBase,使元素具备二元变量的幂等特性?
嗨,我完全理解你的困扰——你已经成功实现了单个二元变量的幂等特性(也就是x^n = x,n>0),但想把这个能力扩展到IndexedBase生成的矩阵元素上,结果发现直接用自定义Symbol子类初始化IndexedBase并不生效。问题的核心在于:IndexedBase生成的索引元素是Indexed类的实例,而不是你自定义的Binary类实例,所以它们不会继承_eval_power方法的重写逻辑。
这里给你两种可行的解决方案,你可以根据自己的需求选择:
方案一:自定义IndexedBase和Indexed子类(推荐)
这种方式更优雅,不会影响全局的Sympy对象,完全隔离你的二元变量矩阵逻辑:
from sympy import Symbol, IndexedBase, Indexed # 保留你原来的二元Symbol子类实现 class Binary(Symbol): def _eval_power(self, other): return self # 自定义Indexed子类,添加幂等的幂运算行为 class BinaryIndexed(Indexed): def _eval_power(self, other): return self # 自定义IndexedBase子类,确保索引时返回BinaryIndexed实例 class BinaryIndexedBase(IndexedBase): def __getitem__(self, args): # 兼容单个索引和多维索引的情况 if not isinstance(args, tuple): args = (args,) return BinaryIndexed(self, *args) # 测试使用 imax, jmax = 3, 3 # 示例维度 x = BinaryIndexedBase('x', shape=(imax, jmax)) print(x[0,0]**2 == x[0,0]) # 输出:True print(x[1,2]**5 == x[1,2]) # 同样输出:True
方案二:猴子补丁快速实现(适合临时脚本)
如果你只是在单个脚本中使用,不想定义太多子类,可以用猴子补丁直接修改Indexed类的_eval_power方法。注意这种方式会影响所有Sympy中的Indexed对象,所以只推荐在特定场景下使用:
from sympy import Symbol, IndexedBase, Indexed class Binary(Symbol): def _eval_power(self, other): return self # 给Indexed类打补丁,添加幂等特性 def binary_eval_power(self, other): return self Indexed._eval_power = binary_eval_power # 现在用你原来的方式创建IndexedBase就能生效了 imax, jmax = 3, 3 x = IndexedBase(Binary('x'), shape=(imax, jmax)) print(x[0,0]**2 == x[0,0]) # 输出:True
两种方案都能实现你想要的二元变量幂等特性,第一种更稳健,第二种更快捷,你可以根据自己的项目场景选择~
备注:内容来源于stack exchange,提问作者ccalaza
相关产品推荐
相关产品推荐

