diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2017-02-12 06:19:36 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2017-02-12 06:19:36 -0500 |
commit | 18662ab0d5f11d5a1f0ea42df0d8480e5a54f288 (patch) | |
tree | 59ce86a4338b7a6b6a62bd547ad740dd1471da5a /perf/solve_poly.py | |
parent | 9a16552c9f689682ca63f86fb3acd68a436e4760 (diff) | |
download | python-coveragepy-18662ab0d5f11d5a1f0ea42df0d8480e5a54f288.tar.gz |
Keep the amazing poly solver by Kyle
Diffstat (limited to 'perf/solve_poly.py')
-rw-r--r-- | perf/solve_poly.py | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/perf/solve_poly.py b/perf/solve_poly.py new file mode 100644 index 0000000..41365f4 --- /dev/null +++ b/perf/solve_poly.py @@ -0,0 +1,247 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt + +# Given empirical data from perf_measure.py, calculate the coefficients of the +# polynomials for file, call, and line operation counts. +# +# Written by Kyle Altendorf. + +import attr +import itertools +import numpy +import scipy.optimize +import sys + + +def f(*args, simplify=False): + p = ((),) + for l in range(len(args)): + l += 1 + p = itertools.chain(p, itertools.product(*(args,), repeat=l)) + + if simplify: + p = {tuple(sorted(set(x))) for x in p} + p = sorted(p, key=lambda x: (len(x), x)) + + return p + +def m(*args): + if len(args) == 0: + return 0 + + r = 1 + for arg in args: + r *= arg + + return r + + +class Poly: + def __init__(self, *names): + self.names = names + + self.terms = f(*self.names, simplify=True) + + def calculate(self, coefficients, **name_values): + for name in name_values: + if name not in self.names: + raise Exception('bad parameter') + + substituted_terms = [] + for term in self.terms: + substituted_terms.append(tuple(name_values[name] for name in term)) + + c_tuples = ((c,) for c in coefficients) + + terms = tuple(a + b for a, b in zip(c_tuples, substituted_terms)) + + multiplied = tuple(m(*t) for t in terms) + total = sum(multiplied) + + return total + + +poly = Poly('f', 'c', 'l') + +#print('\n'.join(str(t) for t in poly.terms)) + +@attr.s +class FCL: + f = attr.ib() + c = attr.ib() + l = attr.ib() + +INPUT = """\ +1,1,1,18,242,1119 +1,1,2,18,242,1121 +1,1,3,18,242,1123 +1,1,4,18,242,1125 +1,1,5,18,242,1127 +1,2,1,18,243,1124 +1,2,2,18,243,1128 +1,2,3,18,243,1132 +1,2,4,18,243,1136 +1,2,5,18,243,1140 +1,3,1,18,244,1129 +1,3,2,18,244,1135 +1,3,3,18,244,1141 +1,3,4,18,244,1147 +1,3,5,18,244,1153 +1,4,1,18,245,1134 +1,4,2,18,245,1142 +1,4,3,18,245,1150 +1,4,4,18,245,1158 +1,4,5,18,245,1166 +1,5,1,18,246,1139 +1,5,2,18,246,1149 +1,5,3,18,246,1159 +1,5,4,18,246,1169 +1,5,5,18,246,1179 +2,1,1,19,399,1893 +2,1,2,19,399,1897 +2,1,3,19,399,1901 +2,1,4,19,399,1905 +2,1,5,19,399,1909 +2,2,1,19,401,1903 +2,2,2,19,401,1911 +2,2,3,19,401,1919 +2,2,4,19,401,1927 +2,2,5,19,401,1935 +2,3,1,19,403,1913 +2,3,2,19,403,1925 +2,3,3,19,403,1937 +2,3,4,19,403,1949 +2,3,5,19,403,1961 +2,4,1,19,405,1923 +2,4,2,19,405,1939 +2,4,3,19,405,1955 +2,4,4,19,405,1971 +2,4,5,19,405,1987 +2,5,1,19,407,1933 +2,5,2,19,407,1953 +2,5,3,19,407,1973 +2,5,4,19,407,1993 +2,5,5,19,407,2013 +3,1,1,20,556,2667 +3,1,2,20,556,2673 +3,1,3,20,556,2679 +3,1,4,20,556,2685 +3,1,5,20,556,2691 +3,2,1,20,559,2682 +3,2,2,20,559,2694 +3,2,3,20,559,2706 +3,2,4,20,559,2718 +3,2,5,20,559,2730 +3,3,1,20,562,2697 +3,3,2,20,562,2715 +3,3,3,20,562,2733 +3,3,4,20,562,2751 +3,3,5,20,562,2769 +3,4,1,20,565,2712 +3,4,2,20,565,2736 +3,4,3,20,565,2760 +3,4,4,20,565,2784 +3,4,5,20,565,2808 +3,5,1,20,568,2727 +3,5,2,20,568,2757 +3,5,3,20,568,2787 +3,5,4,20,568,2817 +3,5,5,20,568,2847 +4,1,1,21,713,3441 +4,1,2,21,713,3449 +4,1,3,21,713,3457 +4,1,4,21,713,3465 +4,1,5,21,713,3473 +4,2,1,21,717,3461 +4,2,2,21,717,3477 +4,2,3,21,717,3493 +4,2,4,21,717,3509 +4,2,5,21,717,3525 +4,3,1,21,721,3481 +4,3,2,21,721,3505 +4,3,3,21,721,3529 +4,3,4,21,721,3553 +4,3,5,21,721,3577 +4,4,1,21,725,3501 +4,4,2,21,725,3533 +4,4,3,21,725,3565 +4,4,4,21,725,3597 +4,4,5,21,725,3629 +4,5,1,21,729,3521 +4,5,2,21,729,3561 +4,5,3,21,729,3601 +4,5,4,21,729,3641 +4,5,5,21,729,3681 +5,1,1,22,870,4215 +5,1,2,22,870,4225 +5,1,3,22,870,4235 +5,1,4,22,870,4245 +5,1,5,22,870,4255 +5,2,1,22,875,4240 +5,2,2,22,875,4260 +5,2,3,22,875,4280 +5,2,4,22,875,4300 +5,2,5,22,875,4320 +5,3,1,22,880,4265 +5,3,2,22,880,4295 +5,3,3,22,880,4325 +5,3,4,22,880,4355 +5,3,5,22,880,4385 +5,4,1,22,885,4290 +5,4,2,22,885,4330 +5,4,3,22,885,4370 +5,4,4,22,885,4410 +5,4,5,22,885,4450 +5,5,1,22,890,4315 +5,5,2,22,890,4365 +5,5,3,22,890,4415 +5,5,4,22,890,4465 +5,5,5,22,890,4515 +""" + +inputs_outputs = {} +for row in INPUT.splitlines(): + row = [int(v) for v in row.split(",")] + inputs_outputs[FCL(*row[:3])] = FCL(*row[3:]) + +#print('\n'.join(str(t) for t in inputs_outputs.items())) + +def calc_poly_coeff(poly, coefficients): + c_tuples = list(((c,) for c in coefficients)) + poly = list(f(*poly)) + poly = list(a + b for a, b in zip(c_tuples, poly)) + multiplied = list(m(*t) for t in poly) + total = sum(multiplied) + return total + +def calc_error(inputs, output, coefficients): + result = poly.calculate(coefficients, **inputs) + return result - output + + +def calc_total_error(inputs_outputs, coefficients, name): + total_error = 0 + for inputs, outputs in inputs_outputs.items(): + total_error += abs(calc_error(attr.asdict(inputs), attr.asdict(outputs)[name], coefficients)) + + return total_error + +coefficient_count = len(poly.terms) +#print('count: {}'.format(coefficient_count)) +x0 = numpy.array((0,) * coefficient_count) + +#print(x0) + +with open('results', 'w') as f: + for name in sorted(attr.asdict(FCL(0,0,0))): + c = scipy.optimize.minimize( + fun=lambda c: calc_total_error(inputs_outputs, c, name), + x0=x0 + ) + + coefficients = [int(round(x)) for x in c.x] + terms = [''.join(t) for t in poly.terms] + message = "{}' = ".format(name) + message += ' + '.join("{}{}".format(coeff if coeff != 1 else '', term) for coeff, term in reversed(list(zip(coefficients, terms))) if coeff != 0) + print(message) + f.write(message) |