RosettaCodeData/Task/Demings-funnel/Python/demings-funnel-2.py

76 lines
2.0 KiB
Python

from random import gauss
from math import sqrt
from pprint import pprint as pp
NMAX=50
def statscreator():
sum_ = sum2 = n = 0
def stats(x):
nonlocal sum_, sum2, n
sum_ += x
sum2 += x*x
n += 1.0
return sum_/n, sqrt(sum2/n - sum_*sum_/n/n)
return stats
def drop(target, sigma=1.0):
'Drop ball at target'
return gauss(target, sigma)
def deming(rule, nmax=NMAX):
''' Simulate Demings funnel in 1D. '''
stats = statscreator()
target = 0
for i in range(nmax):
value = drop(target)
mean, sdev = stats(value)
target = rule(target, value)
if i == nmax - 1:
return mean, sdev
def d1(target, value):
''' Keep Funnel over target. '''
return target
def d2(target, value):
''' The new target starts at the center, 0,0 then is adjusted to
be the previous target _minus_ the offset of the new drop from the
previous target. '''
return -value # - (target - (target - value)) = - value
def d3(target, value):
''' The new target starts at the center, 0,0 then is adjusted to
be the previous target _minus_ the offset of the new drop from the
center, 0.0. '''
return target - value
def d4(target, value):
''' (Dumb). The new target is where it last dropped. '''
return value
def printit(rule, trials=5):
print('\nDeming simulation. %i trials using rule %s:\n %s'
% (trials, rule.__name__.upper(), rule.__doc__))
for i in range(trials):
print(' Mean: %7.3f, Sdev: %7.3f' % deming(rule))
if __name__ == '__main__':
rcomments = [ (d1, 'Should have smallest deviations ~1.0, and be centered on 0.0'),
(d2, 'Should be centred on 0.0 with larger deviations than D1'),
(d3, 'Should be centred on 0.0 with larger deviations than D1'),
(d4, 'Center wanders all over the place, with deviations to match!'),
]
for rule, comment in rcomments:
printit(rule)
print(' %s\n' % comment)