From 6951fd5de77cfce0c414e075e95eb1e08723faca Mon Sep 17 00:00:00 2001 From: LSaldyt Date: Tue, 14 Nov 2017 17:16:02 -0700 Subject: [PATCH 1/3] Adds meta and parameterized meta formulas, for fun --- copycat/copycat.py | 2 +- copycat/temperature.py | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/copycat/copycat.py b/copycat/copycat.py index 2d41050..cfa4258 100644 --- a/copycat/copycat.py +++ b/copycat/copycat.py @@ -71,7 +71,7 @@ class Copycat(object): self.workspace.resetWithStrings(initial, modified, target) answers = {} - for formula in ['original', 'best', 'sbest', 'pbest', 'none']: + for formula in ['original', 'best', 'sbest', 'pbest', 'meta', 'pmeta', 'none']: self.temperature.useAdj(formula) answers = {} for i in range(iterations): diff --git a/copycat/temperature.py b/copycat/temperature.py index ce78d96..06a673d 100644 --- a/copycat/temperature.py +++ b/copycat/temperature.py @@ -24,19 +24,19 @@ def _entropy(temp, prob): f = (c + 1) * prob return -f * math.log2(f) -def _weighted(temp, prob, s, u, alpha=1, beta=1): +def _weighted(temp, s, u): weighted = (temp / 100) * s + ((100 - temp) / 100) * u return weighted def _weighted_inverse(temp, prob): iprob = 1 - prob - return _weighted(temp, prob, iprob, prob) + return _weighted(temp, iprob, prob) def _fifty_converge(temp, prob): # Uses .5 instead of 1-prob - return _weighted(temp, prob, .5, prob) + return _weighted(temp, .5, prob) def _soft_curve(temp, prob): # Curves to the average of the (1-p) and .5 - return min(1, _weighted(temp, prob, (1.5-prob)/2, prob)) + return min(1, _weighted(temp, (1.5-prob)/2, prob)) def _weighted_soft_curve(temp, prob): # Curves to the weighted average of the (1-p) and .5 weight = 100 @@ -49,25 +49,25 @@ def _weighted_soft_curve(temp, prob): # Curves to the weighted average of the (1 def _alt_fifty(temp, prob): s = .5 u = prob ** 2 if prob < .5 else math.sqrt(prob) - return _weighted(temp, prob, s, u) + return _weighted(temp, s, u) def _averaged_alt(temp, prob): s = (1.5 - prob)/2 u = prob ** 2 if prob < .5 else math.sqrt(prob) - return _weighted(temp, prob, s, u) + return _weighted(temp, s, u) def _working_best(temp, prob): s = .5 # convergence r = 1.05 # power u = prob ** r if prob < .5 else prob ** (1/r) - return _weighted(temp, prob, s, u) + return _weighted(temp, s, u) def _soft_best(temp, prob): s = .5 # convergence r = 1.05 # power u = prob ** r if prob < .5 else prob ** (1/r) - return _weighted(temp, prob, s, u) + return _weighted(temp, s, u) def _parameterized_best(temp, prob): # (D$66/100)*($E$64*$B68 + $G$64*$F$64)/($E$64 + $G$64)+((100-D$66)/100)*IF($B68 > 0.5, $B68^(1/$H$64), $B68^$H$64) @@ -78,7 +78,24 @@ def _parameterized_best(temp, prob): s = (alpha * prob + beta * s) / (alpha + beta) r = 1.05 u = prob ** r if prob < .5 else prob ** (1/r) - return _weighted(temp, prob, s, u) + return _weighted(temp, s, u) + +def _meta(temp, prob): + r = _weighted(temp, 1, 2) # Make r a function of temperature + s = .5 + u = prob ** r if prob < .5 else prob ** (1/r) + return _weighted(temp, s, u) + +def _meta_parameterized(temp, prob): + r = _weighted(temp, 1, 2) # Make r a function of temperature + + alpha = 5 + beta = 1 + s = .5 + s = (alpha * prob + beta * s) / (alpha + beta) + u = prob ** r if prob < .5 else prob ** (1/r) + + return _weighted(temp, s, u) def _none(temp, prob): return prob @@ -99,6 +116,8 @@ class Temperature(object): 'best' : _working_best, 'sbest' : _soft_best, 'pbest' : _parameterized_best, + 'meta' : _meta, + 'pmeta' : _meta_parameterized, 'none' : _none} self.diffs = 0 self.ndiffs = 0 From 06c5625f75c8b76b96d28dbd9e81e15126cc41fe Mon Sep 17 00:00:00 2001 From: LSaldyt Date: Sun, 19 Nov 2017 10:58:02 -0700 Subject: [PATCH 2/3] Updates distributions --- .distributions | Bin 1388 -> 883 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.distributions b/.distributions index 5f4912fbe683882d49b53d15fd2fc1a550d7763e..3f59c8ff05e0c01763f9795f5d1bb4cf3bf80e2e 100644 GIT binary patch literal 883 zcmZ|NPmBvu90%~O{@vQe{$rKxvb%K3s@+-}iYhbH#ZE96~l* zuGF)V5vl0qjHVR*r|e&73txp51e}8CcQ_o_P;|+_(kCgC z1&`>X|8ix$XlhawylMViEXz2D6&ZYXP=Ie41t;eMZywf7vub7#yNI;})(ME79J!GPdDF;; z+K~mvY61EYWv-{pfW^eB3>ye+o1V_p6E=fg+D-yvJoqTq;*H{`H?N(YGVRKO2IB;xJb8QgG+VT?gH;~-b}o4Q z@!ckP7lDao!0ZDo>bk0`u$z%5DS3~;ze_$YK#ag%zQe5(4U3EIaOD02^T&(4*~k{? fsrM0x^X$FkLcC`oPBj6RJ)HdY<=xj1*C>&{;t&BB literal 1388 zcmZY9Yitx%6bJBaw+|>_U-Us;`hd0$g0&U;P|$84Qre|kwneiE58d6F?Vaszw`X^z zbPdlX=L-+Sd>*Z8AQJWll~BgM_%9@F8G&RDR>_@Vu~<}1iFhx&EP4xsJk9ziaeUR^7g>^$=S@o-m3f7-gPtgCaJthFYMw~1qCpYM)V)k(|1<}i#4v1z(Qd?Oi;Za2Kp&KFC^fpT6wQn7 zDGz7%DAqBVd(Z(-JVY30% zKmaN@R1!S#vk8+#a69%lhNM0TX6c@EW7b8f_} zN#oT0@qPUpzaKRgKN5QjYB;<=@ER*W-d=tjyG$2dR==OWWY^-)K@8z`4m$|WjBghQ z!VCeM-}xZ>`X>cO#UX^X9O?*OeN6KpOryDvcpEn*ry5X3SkIw>;JnT3k@m)MZ}gi^ z>jkr-3@>tciQr)>D0Z77fBoD@{qkpJPXtsO4`?TcU5S8R#(-Xt+$p#e?sp$Fa{`7CryZEUPZzWk7x;X43J9|cS ao7jQwxj%n$<@Nl(-T!V4fJ^r(RsRA=-;&b+ From 98c2b497a600b4965b1dc5a9effec83997d7c4c6 Mon Sep 17 00:00:00 2001 From: LSaldyt Date: Sun, 19 Nov 2017 14:29:09 -0700 Subject: [PATCH 3/3] Fixes bugs with multi-formula distributions --- .distributions | Bin 883 -> 10248 bytes copycat/copycat.py | 35 ++++++++++++++++------------------- copycat/problem.py | 17 ++++++++++++----- 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/.distributions b/.distributions index 3f59c8ff05e0c01763f9795f5d1bb4cf3bf80e2e..25f566f7b8ef4e6bc0f6e3c9f7a2e1a275660cc7 100644 GIT binary patch literal 10248 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 UjIfa#!?t^Npfd1-}iYhbH#ZE96~l* zuGF)V5vl0qjHVR*r|e&73txp51e}8CcQ_o_P;|+_(kCgC z1&`>X|8ix$XlhawylMViEXz2D6&ZYXP=Ie41t;eMZywf7vub7#yNI;})(ME79J!GPdDF;; z+K~mvY61EYWv-{pfW^eB3>ye+o1V_p6E=fg+D-yvJoqTq;*H{`H?N(YGVRKO2IB;xJb8QgG+VT?gH;~-b}o4Q z@!ckP7lDao!0ZDo>bk0`u$z%5DS3~;ze_$YK#ag%zQe5(4U3EIaOD02^T&(4*~k{? fsrM0x^X$FkLcC`oPBj6RJ)HdY<=xj1*C>&{;t&BB diff --git a/copycat/copycat.py b/copycat/copycat.py index cfa4258..d910fb8 100644 --- a/copycat/copycat.py +++ b/copycat/copycat.py @@ -71,26 +71,23 @@ class Copycat(object): self.workspace.resetWithStrings(initial, modified, target) answers = {} - for formula in ['original', 'best', 'sbest', 'pbest', 'meta', 'pmeta', 'none']: - self.temperature.useAdj(formula) - answers = {} - for i in range(iterations): - answer = self.runTrial() - d = answers.setdefault(answer['answer'], { - 'count': 0, - 'sumtemp': 0, # TODO: use entropy - 'sumtime': 0 - }) - d['count'] += 1 - d['sumtemp'] += answer['temp'] # TODO: use entropy - d['sumtime'] += answer['time'] + for i in range(iterations): + answer = self.runTrial() + d = answers.setdefault(answer['answer'], { + 'count': 0, + 'sumtemp': 0, # TODO: use entropy + 'sumtime': 0 + }) + d['count'] += 1 + d['sumtemp'] += answer['temp'] # TODO: use entropy + d['sumtime'] += answer['time'] - for answer, d in answers.items(): - d['avgtemp'] = d.pop('sumtemp') / d['count'] - d['avgtime'] = d.pop('sumtime') / d['count'] - print('The formula {} provided:'.format(formula)) - print('Average difference: {}'.format(self.temperature.getAverageDifference())) - pprint(answers) + for answer, d in answers.items(): + d['avgtemp'] = d.pop('sumtemp') / d['count'] + d['avgtime'] = d.pop('sumtime') / d['count'] + #print('The formula {} provided:'.format(formula)) + #print('Average difference: {}'.format(self.temperature.getAverageDifference())) + #pprint(answers) return answers diff --git a/copycat/problem.py b/copycat/problem.py index bf335e5..6f23777 100644 --- a/copycat/problem.py +++ b/copycat/problem.py @@ -5,6 +5,12 @@ from pprint import pprint class Problem: def __init__(self, initial, modified, target, iterations, distributions=None, formulas=None): self.formulas = formulas + if formulas is not None: + assert hasattr(Copycat(), 'temperature') + else: + if hasattr(Copycat(), 'temperature'): + self.formulas = set(Copycat().temperature.adj_formulas()) + print(self.formulas) self.initial = initial self.modified = modified self.target = target @@ -14,8 +20,7 @@ class Problem: self.distributions = self.solve() else: self.distributions = distributions - if formulas is not None: - assert hasattr(Copycat().workspace, 'temperature') + print(self.formulas) def test(self, comparison, expected=None): print('-' * 120) @@ -41,8 +46,8 @@ class Problem: copycat = Copycat() answers = dict() if self.formulas == None: - if hasattr(copycat.workspace, 'temperature'): - formula = copycat.workspace.temperature.getAdj() + if hasattr(copycat, 'temperature'): + formula = copycat.temperature.getAdj() else: formula = None answers[formula] = copycat.run(self.initial, @@ -50,12 +55,14 @@ class Problem: self.target, self.iterations) else: + print(self.formulas) for formula in self.formulas: copycat.temperature.useAdj(formula) - answers[formulas] = copycat.run(self.initial, + answers[formula] = copycat.run(self.initial, self.modified, self.target, self.iterations) + print('Done with {}'.format(formula)) return answers def generate(self):