0

I have a function H(t) returning a float. I then want to numerically compute several integrals involving this function. However, one of the integrals basically invokes the previous integral, e.g.

from scipy.integrate import quad

def H(t):
    return t

def G1(t):
    return quad(lambda x: H(x)*H(t-x),0,1)[0]

def G2(t):
    return quad(lambda x: G1(x)*H(t-x),0,1)[0]

res = quad(G1,0,1) + quad(G2,0,1)

I will need to do this for a large number of functions (i.e. continue like this with G3, G4... Gn) and my end-result will depend on all of them. Since I have to compute G1 for many values of t anyway in order to perform quad(G1,0,1), is it possible to store those computed values and use them when computing quad(G2,0,1)? I could maybe try to write my own simplistic integration function, but how would I go about storing and re-using these values?

Shinja
  • 125
  • 5
  • There is `lru_cache` in the standard library ([see here](https://docs.python.org/3.4/library/functools.html#functools.lru_cache)) but I'm not sure if that is the best way for this problem. Is it possible to change the formula for what you try to calculate i.e. write the formula down on paper and try to manipulate it until you only need to evaluate G1 once? – syntonym Sep 21 '16 at 09:11
  • @syntonym Unfortunately not (yet). I am basically writing this program because we don't know yet how to rewrite it analytically and want to see some numerical results. – Shinja Sep 21 '16 at 09:27
  • Then I guess lru_cache is worth a try. I'm not sure how exactly scipy integrates but it caches calls to a function. Maybe you need to tweak the cache size a bit, to really cache everything you want. – syntonym Sep 21 '16 at 09:29
  • Also thank you for the link to lru_cache, that may work (although I probably still have to write my own integration function for that I guess) – Shinja Sep 21 '16 at 09:34
  • You should be able to put that around G1 (and G2 and G3 and ...) so when the `quad` function calls G1(3) (or whatever) it doesn't need to do the calculation again. Maybe it doesn't work, but just try it out. – syntonym Sep 21 '16 at 10:03

1 Answers1

0

I guess it's exactly same as lru_cache, but since I already wrote it, might as well share:

def store_result(func):
    def remember(t):
        if t not in func.results:
            func.results[t]  = func(t)
        return func.results[t]
    setattr(func, 'results', {}) # make dictionary to store results
    return remember

This is decorator that modifies function to store results to dictionary and retrieve those when they are called with the same arguments. You can modify it to suit your needs.

usage:

@store_result
def G1(t):
    return quad(lambda x: H(x)*H(t-x),0,1)[0]
user1308345
  • 1,032
  • 1
  • 8
  • 14
  • Thanks a lot, even if lru_cache solves it, this is the type of solution I was looking for and it shows me how I can write it in the future. – Shinja Sep 21 '16 at 11:46