I am trying to construct a more complex function from the sum and product of multiple simple functions. I want to create a class where I can add a new simple function and its operation to construct a complex function then evaluate the complex function.
For example say I have the functions:
def f1(a, b, c):
return 2 * c
def f2(a, b, c, d):
return c + d
And would like to construct something like:
f1(0, 0, 1) + f2(0, 0, 1, 0) * f1(0, 0, 2)
#Out:6
But without typing out the whole expression and with the parameters packaged in a single vector so I can optimise them. I have built a class to do it but it is really quite clumsy and doesn't follow BODMAS (the mathematical order of operations, Bracket, Of, Division, Multiplication, Addition and Subtraction):
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
Testing on the first example the answer should be 6 but is 12 due to no BODMAS:
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
Does anyone know a more pythonic way of adding and multiplying functions together and combining their parameters into a single vector?
Thanks,
Robin