0

I am new using function generators. I am working with the following function:

def math_model(n: float):
    def crrcn(x, t0: float, amp: float, tau: float, offset: float, dt: float, k: float):
        crrcn = np.zeros(np.shape(x))
        for i, a in enumerate(x):
            if a < (t0 + dt):
                crrcn[i] = offset
            else: 
                crrcn[i] = offset + k * amp * (math.exp(n) / (n ** n)) * ((a - (t0 + dt)) / tau) ** n * math.exp( - (a - (t0 + dt)) / tau) 
        return crrcn
    return crrcn

which defines a mathematical model I will use later to fit some data with scipy curve_fit. I wanted to use this same model to build a more complicated one with the following line.

model = partial(math_model(N), dt = 0, k = 1) + math_model(N)

which gives me:

TypeError: unsupported operand type(s) for +: 'functools.partial' and 'function'

From which I understand that I cannot build a function from two functions using this operator and as far as I know there are no function operands in python. How can one build a function from other functions without explicitly evaluating them?

2 Answers 2

2

PREVIOUS ANSWER:

This seems like a misunderstanding of partial.

partial(...) returns a new function. It does not execute it, it just creates it.

So your line model = partial(math_model(N), dt = 0, k = 1) + math_model(N) is invalid, because you are basically doing a a + b operation, where a is ... a function :)

What you may wish to do is simply applying the model. That can be done using math_model(N)(dt = 0, k = 1).

So

model = math_model(N)(dt = 0, k = 1) + math_model(N)

may do the trick

NEW EDIT: It seems that I misunderstood you. You actually wish to create a function by combining two functions. This is therefore some kind of symbolic reasoning. There are a few libraries out there for this, the most advanced that I know is SymPy. Or if your functions have only one argument, you can use my mini_lambda

For example with mini-lambda:

from mini_lambda import x

f1 = x ** 2
f2 = 5 * x
f3 = f1 + f2

print(f3.to_string())
print(f3.evaluate(1))

yields

x ** 2 + 5 * x
6
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the clarifying. Currying does a nice job. The thing is that I actually need model to be a function object. As long as I use '+' python won't be happy considering that '+' does not supports function types.
Thanks will give sympy a look.
1

Given that the function depends on multiple variables mini_lambda was not an option.But with sympy it was nice and easy.

def math_model():
    a, o, t, t0, tau, dt, k = sympy.symbols('a, o, t, t0, tau, dt, k')
    semi = a * sympy.exp(-(t - t0)/ tau)
    reflex = k * a * sympy.exp(-(t -(t0 + dt))/ tau)
    double = sympy.Piecewise((o, t < t0),(o + semi, (t0 <= t) & (t < t0 + dt)), (o + semi + reflex, t0 + dt <= t))
    return sympy.lambdify([t, t0, dt, k, o, a, tau], double, 'scipy')

Thanks for suggesting Sympy. After using lambdify the result is a python function which in this case relies on scipy definitions of mathematical functions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.