7

Let's say I want to integrate x**2 from 0 to 1. I do it using the scipy.integrate.quad:

from scipy import integrate
def f(x): return x**2
I = integrate.quad(f, 0, 1)[0]
print(I)

Questions: Is there any way to know how many times the user-defined function f gets called by the quad? I want to do it as I am interested to know how many have been utilized by quad to evaluate the integral.

martineau
  • 119,623
  • 25
  • 170
  • 301
rainman
  • 237
  • 3
  • 9

6 Answers6

9

Sure. Use a call-counting wrapper:

import functools
def counted_calls(f):
    @functools.wraps(f)
    def count_wrapper(*args, **kwargs):
        count_wrapper.count += 1
        return f(*args, **kwargs)
    count_wrapper.count = 0
    return count_wrapper

And pass the wrapped version to quad:

wrapped = counted_calls(f)
integrate.quad(wrapped, 0, 1)
print(wrapped.count)

Demo, with a call count of 21.

I've specifically avoided using a global counter or using counted_calls as a decorator on the f definition (though you can use it as a decorator if you want), to make it easier to take separate counts. With a global, or using it as a decorator, you'd have to remember to manually reset the counter every time.

user2357112
  • 260,549
  • 28
  • 431
  • 505
4

Just add to a global whenever f is called:

from scipy import integrate
count = 0
def f(x):
    global count
    count += 1
    return x ** 2
I = integrate.quad(f, 0, 1)[0]
print(I)
print('called', count, 'times')
chepner
  • 497,756
  • 71
  • 530
  • 681
Joe Iddon
  • 20,101
  • 7
  • 33
  • 54
4

You could do something like this:

from scipy import integrate

class FWrap(object):
    def __init__(self):
        self.count = 0
    def f(self, x):
        self.count += 1
        return x ** 2

fwrap = FWrap()
f = lambda x: fwrap.f(x)
I = integrate.quad(f, 0, 1)[0]
print(I)
print(fwrap.count)

I prefer this to globals, though there's probably a simpler way. (EDIT: There is)

mVChr
  • 49,587
  • 11
  • 107
  • 104
1

In your small example, you can use variables or some other custom code to keep track, but if you'd rather not have to keep editing your code (maybe in a large program where you want to track many functions' calls), it'd be better to use trace and/or some call graphing library. More standard approach too, and gives you other things like timing data if you want it.

I've used this one with Gprof before and was happy with it, and it works for more than just Python: https://github.com/jrfonseca/gprof2dot

sudo
  • 5,604
  • 5
  • 40
  • 78
0

You can add a simple counter inside the function to tally how many times the specific code was ran.

0

An interesting system that I don't think has been explored in the previous (and very valid) answers, is the definition of a counter attribute (say count) for your function.

Since in my personal experience I've always avoided the use of global variables, this could be a simple and at the same time safer approach.

from scipy import integrate

def f(x):
    return x**2
    f.count += 1

f.count = 0

I = integrate.quad(f, 0, 1)[0]
print(I)
print(f.count)
Max Shouman
  • 1,333
  • 1
  • 4
  • 11