How to efficiently pass function through? How to efficiently pass function through? numpy numpy

How to efficiently pass function through?


Let's start by changing the code to output the current iteration:

_u = self.ufor t in range(0, self.T):    print(t)    lparams = np.random.randint(self.a, self.b, 6).reshape(3, 2).tolist()    functions = [self._function_template(_u, *lparams[i])                 for i in range(0, 3)]    # evaluate functions    pairs = list(itertools.combinations(functions, 2))    fval = [F(diff(*pairs[i]), self.a, self.b) for i in range(0, 3)]    ind = np.sort(np.unique(np.random.randint(self.a, self.b, 10)))    _u = _temp(ind, np.asarray(functions)[ind % 3])

Looking into the line causing the behaviour,

fval = [F(diff(*pairs[i]), self.a, self.b) for i in range(0, 3)]

functions of interest would be F and diff. The latter being straightforward, the former:

def F(f, a, b):    try:        brentq(f, a=a, b=b)    except ValueError:        pass

Hmm, swallowing exceptions, let's see what happens if we:

def F(f, a, b):    brentq(f, a=a, b=b)

Immediately, for the first function and on the first iteration, an error is thrown:

ValueError: f(a) and f(b) must have different signs

Looking at the docs this is a prerequisite of the root finding function brentq. Let's change the definition once more to monitor this condition on each iteration.

def F(f, a, b):    try:        brentq(f, a=a, b=b)    except ValueError as e:        print(e)

The output is

if(a) and f(b) must have different signsf(a) and f(b) must have different signsf(a) and f(b) must have different signs

for i ranging from 0 to 57. Meaning, the first time the function F ever does any real work is for i=58. And it keeps doing so for higher values of i.

Conclusion: it takes longer for these higher values, because:

  1. the root is never calculated for the lower values
  2. the number of calculations grows linear for i>58


Your code is really far too complex to explain your problem - strive for something simpler. Sometimes you have to write code just to demonstrate the problem.

I'm taking a stab, based purely on your description rather than your code (although I ran the code and verified) . Here's your problem:

method eval: This is the core function to generate the blue, green and red versions every time. It takes three varying parameters each iteration: vfunction which is the dominating function from the previous step, m and s which are two parameters (flaots) affecting the shape of the resulting curve.

Your vfunction parameter is more complex on each iteration. You are passing a nested function built up over previous iterations, which causes a recursive execution. Each iteration increases the depth of the recursive call.

How can you avoid this? There's no easy or built in way. The simplest answer is - assuming the inputs to these functions are consistent - to store the functional result (i.e. the numbers) rather than the function themselves. You can do this as long as you have a finite number of known inputs.

If the inputs to the underlying functions aren't consistent then there's no shortcut. You need to repeatedly evaluate those underlying functions. I see that you're doing some piecewise splicing of the underlying functions - you can test whether the cost of doing so exceeds the cost of simply taking the max of each of the underlying functions.

The test that I ran (10 iterations) took a few seconds. I don't see that as a problem.