Spaces:
Running
Running
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 | |