函数代数,用于在单个向量中添加或乘以多个python函数和打包参数

2024-09-30 10:33:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用多个简单函数的和和和积来构造一个更复杂的函数。我想创建一个类,在这个类中我可以添加一个新的简单函数及其操作来构造一个复杂函数,然后对复杂函数求值

例如,假设我具有以下功能:

def f1(a, b, c):
    return 2 * c

def f2(a, b, c, d):
    return c + d

并希望构建如下内容:

f1(0, 0, 1) + f2(0, 0, 1, 0) * f1(0, 0, 2)
#Out:6

但是不需要输入整个表达式,并且参数打包在一个向量中,这样我就可以优化它们。我已经建立了一个类来做这件事,但它真的很笨拙,不遵循BODMAS(运算的数学顺序,括号,of,除法,乘法,加法和减法):

class FunctionAlgebra:

    def __init__(self):
        self.f = []
        self.op = []
        self.hpid = []
        self.hyperparameters = []
        self.name = '0'

    def compose(self, f, p, op):
        """
        Compose an expression
        """
        self.hpid = np.concatenate([self.hpid, len(self.f) * np.ones(len(p))])
        self.hyperparameters = np.concatenate([self.hyperparameters, p])
        self.f.append(f)
        self.op.append(op)
        self.name += " {} {}".format(op.__name__, f.__name__)
        self.name = self.name.replace('add', "+").replace("multiply", '*')

    def _evalf_(self, a, b, f, args):
        """
        Evaluate a function
        """
        self.cr = f(a, b, *args)

    def multiply(self):
        """
        Multiply function result by total result
        """
        self.result *= self.cr

    def add(self):
        """
        Add function result to the total result.
        """
        self.result += self.cr

    def call(self, a, b, p):
        """
        Call and evaluate the expression
        """
        self.result = 0
        for i in range(len(self.f)):
            args = p[self.hpid == i]
            self._evalf_(a, b, self.f[i], args)
            self.op[i]()
        return self.result

对第一个示例进行测试,答案应为6,但由于没有BODMAS,答案应为12:

f = FunctionAlgebra()
f.compose(f1, [1], f.add)
f.compose(f2, [1, 0], f.add)
f.compose(f1, [2], f.multiply)
f.call(0, 0, f.hyperparameters)
#Out:12

有没有人知道一种更像python的方法,将函数相加和相乘,并将它们的参数组合成一个向量

谢谢

罗宾


Tags: 函数composenameselfaddreturndefnp
1条回答
网友
1楼 · 发布于 2024-09-30 10:33:39

您没有实现bodma,因此所有操作都是从左到右顺序执行的

要实现运算符优先级,您应该:

  • 以某种方式提供一个表达式(仅使用流畅的方式是不够的)
  • 解析表达式(例如使用antlr4
  • 最后,按要求的顺序执行操作(如BODMAS)

这是一条漫长(但有力且正确)的道路。 Python具有内置的eval函数,因此可以将其用于您的目的:

class FunctionAlgebra:

    def __init__(self):
        self.parts=[]

    def compose(self, f, p, op):
        self.parts.append({
            'function':f,
            'params':p,
            'operation':op})

    def call(self, *hyperparams):

        #build expression and its input params
        expr = '0'
        inp={}
        i = 0 

        for part in self.parts:
            varname = f'v{i}'
            expr += part['operation']+varname
            inp[varname] = part['function'](*hyperparams, *part['params'])
            i+=1

        print (expr, inp)
        #and eval it
        return eval(expr,inp)


def f1(a, b, c):
    return 2 * c

def f2(a, b, c, d):
    return c + d


f = FunctionAlgebra()
f.compose(f1, [1], '+')
f.compose(f2, [1, 0], '+')
f.compose(f1, [2], '*')

print (f.call(0, 0))

# 0+v0+v1*v2 {'v0': 2, 'v1': 1, 'v2': 4}
# Output 6

相关问题 更多 >

    热门问题