123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- def monitor(f, input='print', output='print'):
- """
- Returns a wrapped copy of *f* that monitors evaluation by calling
- *input* with every input (*args*, *kwargs*) passed to *f* and
- *output* with every value returned from *f*. The default action
- (specify using the special string value ``'print'``) is to print
- inputs and outputs to stdout, along with the total evaluation
- count::
- >>> from mpmath import *
- >>> mp.dps = 5; mp.pretty = False
- >>> diff(monitor(exp), 1) # diff will eval f(x-h) and f(x+h)
- in 0 (mpf('0.99999999906867742538452148'),) {}
- out 0 mpf('2.7182818259274480055282064')
- in 1 (mpf('1.0000000009313225746154785'),) {}
- out 1 mpf('2.7182818309906424675501024')
- mpf('2.7182808')
- To disable either the input or the output handler, you may
- pass *None* as argument.
- Custom input and output handlers may be used e.g. to store
- results for later analysis::
- >>> mp.dps = 15
- >>> input = []
- >>> output = []
- >>> findroot(monitor(sin, input.append, output.append), 3.0)
- mpf('3.1415926535897932')
- >>> len(input) # Count number of evaluations
- 9
- >>> print(input[3]); print(output[3])
- ((mpf('3.1415076583334066'),), {})
- 8.49952562843408e-5
- >>> print(input[4]); print(output[4])
- ((mpf('3.1415928201669122'),), {})
- -1.66577118985331e-7
- """
- if not input:
- input = lambda v: None
- elif input == 'print':
- incount = [0]
- def input(value):
- args, kwargs = value
- print("in %s %r %r" % (incount[0], args, kwargs))
- incount[0] += 1
- if not output:
- output = lambda v: None
- elif output == 'print':
- outcount = [0]
- def output(value):
- print("out %s %r" % (outcount[0], value))
- outcount[0] += 1
- def f_monitored(*args, **kwargs):
- input((args, kwargs))
- v = f(*args, **kwargs)
- output(v)
- return v
- return f_monitored
- def timing(f, *args, **kwargs):
- """
- Returns time elapsed for evaluating ``f()``. Optionally arguments
- may be passed to time the execution of ``f(*args, **kwargs)``.
- If the first call is very quick, ``f`` is called
- repeatedly and the best time is returned.
- """
- once = kwargs.get('once')
- if 'once' in kwargs:
- del kwargs['once']
- if args or kwargs:
- if len(args) == 1 and not kwargs:
- arg = args[0]
- g = lambda: f(arg)
- else:
- g = lambda: f(*args, **kwargs)
- else:
- g = f
- from timeit import default_timer as clock
- t1=clock(); v=g(); t2=clock(); t=t2-t1
- if t > 0.05 or once:
- return t
- for i in range(3):
- t1=clock();
- # Evaluate multiple times because the timer function
- # has a significant overhead
- g();g();g();g();g();g();g();g();g();g()
- t2=clock()
- t=min(t,(t2-t1)/10)
- return t
|