【问题标题】:how to change Add operator to custom function op2 in solve function of sympy?如何在 sympy 的求解函数中将添加运算符更改为自定义函数 op2?
【发布时间】:2017-03-24 01:00:49
【问题描述】:

更新:

>>> solve([A(x)*A(y) + A(-1), A(x) + A(-2)], x, y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 12, in __mul__
TypeError: unbound method __multiplyFunction__() must be called with A instance
as first argument (got Symbol instance instead)

class A:
    @staticmethod
    def __additionFunction__(a1, a2):
        return a1*a2 #Put what you want instead of this
    def __multiplyFunction__(a1, a2):
        return a1*a2+a1 #Put what you want instead of this
    def __init__(self, value):
        self.value = value
    def __add__(self, other):
        return self.__class__.__additionFunction__(self.value, other.value)
    def __mul__(self, other):
        return self.__class__.__multiplyFunction__(self.value, other.value)

solve([A(x)*A(y) + A(-1), A(x) + A(-2)], x, y)

更新2:

>>> ss([x*y + -1, x-2], x, y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: solve instance has no __call__ method

 class AA:
    @staticmethod
    def __additionFunction__(a1, a2):
        return a1*a2 #Put what you want instead of this
    def __multiplyFunction__(a1, a2):
        return a1*a2+a1 #Put what you want instead of this
    def __init__(self, value):
        self.value = value
    def __add__(self, other):
        return self.__class__.__additionFunction__(self.value, other.value)
    def __mul__(self, other):
        return self.__class__.__multiplyFunction__(self.value, other.value)


ss = solve(AA)
ss([x*y + -1, x-2], x, y)

想在求解函数中将添加运算符更改为自定义函数 op2 然后这个求解([x*y - 1, x + 2], x, y) 在求解过程中,参数也发生变化 添加到自定义函数 op2

错误,因为我不知道如何将 op2 作为 ast 树注入 ast 树以供 ast 树使用

>>> class ChangeAddToMultiply(ast.NodeTransformer, ast2.NodeTransformer): 
...     """Wraps all integers in a call to Integer()""" 
...     def visit_BinOp(self, node): 
...         print(dir(node)) 
...         print(dir(node.left)) 
...         if isinstance(node.op, ast.Add): 
...             ast.Call(Name(id="op2", ctx=ast2.Load()), [node.left, node.right 
], []) 
...         return node 
... 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
NameError: name 'ast2' is not defined 
>>> 
>>> code = inspect.getsourcelines(solve) 
>>> tree = ast.parse(code) 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
  File "C:\Python27\lib\ast.py", line 37, in parse 
    return compile(source, filename, mode, PyCF_ONLY_AST) 
TypeError: expected a readable buffer object 
>>> tree2 = ast.parse("def op2(a,b): return a*b+a") 
>>> tree = ChangeAddToMultiply().visit(tree,tree2) 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
NameError: name 'tree' is not defined 
>>> ast.fix_missing_locations(tree) 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
NameError: name 'tree' is not defined 
>>> co = compile(tree, '<ast>', "exec") 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
NameError: name 'tree' is not defined 
>>> 
>>> exec(code) 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
TypeError: exec: arg 1 must be a string, file, or code object 
>>> exec(co) 

原代码

import ast 
from __future__ import division 
from sympy import * 
x, y, z, t = symbols('x y z t') 
k, m, n = symbols('k m n', integer=True) 
f, g, h = symbols('f g h', cls=Function) 
import inspect 
def op2(a,b): 
    return a*b+a 

class ChangeAddToMultiply(ast.NodeTransformer, ast2.NodeTransformer): 
    """Wraps all integers in a call to Integer()""" 
    def visit_BinOp(self, node): 
        print(dir(node)) 
        print(dir(node.left)) 
        if isinstance(node.op, ast.Add): 
            ast.Call(Name(id="op2", ctx=ast2.Load()), [node.left, node.right], []) 
        return node 


code = inspect.getsourcelines(solve([x*y - 1, x - 2], x, y)) 
tree = ast.parse(code) 
tree2 = ast.parse("def op2(a,b): return a*b+a") 
tree = ChangeAddToMultiply().visit(tree,tree2) 
ast.fix_missing_locations(tree) 
co = compile(tree, '<ast>', "exec") 

exec(code) 
exec(co) 

【问题讨论】:

    标签: python python-2.7 sympy


    【解决方案1】:

    我猜__add__ 就是你要找的东西。

    class A:
        def __init__(self, value):
            self.value = value
    
        def __add__(self, other):
            return self.value*other.value + 4
    
    >>> a = A(3)
    >>> b = A(4)
    >>> a + b
    16
    

    编辑:

    + 运算符替换为已存在的函数的解决方案:

    class A:
        @staticmethod
        def additionFunction(a1, a2):
            return a1*a2 #Put what you want instead of this
    
        def __init__(self, value):
            self.value = value
    
        def __add__(self, other):
            return self.__class__.additionFunction(self.value, other.value)
    

    这个有点棘手。在我看来,additionFunction 应该属于 A 类,但 Python 中没有静态方法之类的东西。所以这个函数必须从self:self.__class__.additionFunction调用。

    更进一步,可以想象一个使用元类Addable 的解决方案,其构造函数将additionFunction 作为参数...但这可能不值得。

    【讨论】:

    • 我要求在求解函数中用自定义函数 op2 替换添加运算符,如何将您的解决方案应用于求解函数?
    • @user353573 编辑并添加了一个示例。尽管如此,最简单的方法还是写 op2(self, other) 而不是 self.value*other.value + 4,这显然是一个例子......
    • 它如何与 sympy 求解函数一起使用?您的意思是 sympy 求解函数可以使用扩展方法来覆盖其中的添加吗?
    • @user353573 好吧,您应该尝试确定,但是当您在类中覆盖 __add__ 时,它会重新定义该类的实例的添加,因此任何时候 Python 遇到 a+b ,它会知道它的意思是__add__(a, b)。实际上,当 Python 看到 a+b 时,它会从 ab 的类中调用 __add__ 方法,如果找不到该方法,则会引发错误。
    • class AA: @staticmethod def additionFunction__(a1, a2): return a1*a2 #放你想要的而不是这个 def __init__(self, value): self.value = value def __add__(self, other): return self.__class.__additionFunction__(self.value, other.value) ss = solve(AA) ss([x*y - 1, x - 2], x, y) AttributeError: 解决实例没有 call 方法
    猜你喜欢
    • 2014-09-10
    • 2016-09-01
    • 2019-02-14
    • 2016-09-03
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2021-05-14
    相关资源
    最近更新 更多