Cleans code, moving formula choice to copycat.py
This commit is contained in:
@ -65,18 +65,14 @@ class Copycat(object):
|
|||||||
self.reporter.report_answer(answer)
|
self.reporter.report_answer(answer)
|
||||||
return answer
|
return answer
|
||||||
|
|
||||||
def run(self, initial, modified, target, iterations, testAdjFormulas=False):
|
def run(self, initial, modified, target, iterations):
|
||||||
self.workspace.resetWithStrings(initial, modified, target)
|
self.workspace.resetWithStrings(initial, modified, target)
|
||||||
|
|
||||||
if testAdjFormulas:
|
#self.temperature.useAdj('original')
|
||||||
formulas = self.temperature.adj_formulas()
|
#self.temperature.useAdj('entropy')
|
||||||
else:
|
self.temperature.useAdj('inverse') # 100 weight
|
||||||
formulas = ['inverse']
|
#self.temperature.useAdj('150-weight')
|
||||||
#formulas = ['entropy']
|
#self.temperature.useAdj('200-weight')
|
||||||
|
|
||||||
formulaList = []
|
|
||||||
for formula in formulas:
|
|
||||||
self.temperature.useAdj(formula)
|
|
||||||
answers = {}
|
answers = {}
|
||||||
for i in range(iterations):
|
for i in range(iterations):
|
||||||
answer = self.runTrial()
|
answer = self.runTrial()
|
||||||
@ -92,11 +88,7 @@ class Copycat(object):
|
|||||||
for answer, d in answers.items():
|
for answer, d in answers.items():
|
||||||
d['avgtemp'] = d.pop('sumtemp') / d['count']
|
d['avgtemp'] = d.pop('sumtemp') / d['count']
|
||||||
d['avgtime'] = d.pop('sumtime') / d['count']
|
d['avgtime'] = d.pop('sumtime') / d['count']
|
||||||
formulaList.append((formula, answers))
|
return answers
|
||||||
if not testAdjFormulas:
|
|
||||||
return formulaList[0][1]
|
|
||||||
else:
|
|
||||||
return formulaList
|
|
||||||
|
|
||||||
def run_forever(self, initial, modified, target):
|
def run_forever(self, initial, modified, target):
|
||||||
self.workspace.resetWithStrings(initial, modified, target)
|
self.workspace.resetWithStrings(initial, modified, target)
|
||||||
|
|||||||
@ -28,6 +28,11 @@ def _inverse_prob(temp, prob):
|
|||||||
iprob = 1 - prob
|
iprob = 1 - prob
|
||||||
return (temp / 100) * iprob + ((100 - temp) / 100) * prob
|
return (temp / 100) * iprob + ((100 - temp) / 100) * prob
|
||||||
|
|
||||||
|
def _create_weighted_inverse_prob(weight):
|
||||||
|
def _inner_weighted_prob(temp, prob):
|
||||||
|
iprob = 1 - prob
|
||||||
|
return (temp / weight) * iprob + ((weight - temp) / weight) * prob
|
||||||
|
return _inner_weighted_prob
|
||||||
|
|
||||||
class Temperature(object):
|
class Temperature(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -36,7 +41,9 @@ class Temperature(object):
|
|||||||
self._adjustmentFormulas = {
|
self._adjustmentFormulas = {
|
||||||
'original' : _original,
|
'original' : _original,
|
||||||
'entropy' : _entropy,
|
'entropy' : _entropy,
|
||||||
'inverse' : _inverse_prob
|
'inverse' : _inverse_prob,
|
||||||
|
'200-weight' : _create_weighted_inverse_prob(200),
|
||||||
|
'150-weight' : _create_weighted_inverse_prob(150)
|
||||||
}
|
}
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
@ -78,365 +85,3 @@ class Temperature(object):
|
|||||||
|
|
||||||
def adj_formulas(self):
|
def adj_formulas(self):
|
||||||
return self._adjustmentFormulas.keys()
|
return self._adjustmentFormulas.keys()
|
||||||
|
|
||||||
'''
|
|
||||||
def getAdjustedProbability(self, value):
|
|
||||||
if value == 0 or value == 0.5 or self.value() == 0:
|
|
||||||
return value
|
|
||||||
if value < 0.5:
|
|
||||||
return 1.0 - self.getAdjustedProbability(1.0 - value)
|
|
||||||
coldness = 100.0 - self.value()
|
|
||||||
a = math.sqrt(coldness)
|
|
||||||
c = (10 - a) / 100
|
|
||||||
f = (c + 1) * value
|
|
||||||
return max(f, 0.5)
|
|
||||||
|
|
||||||
def getAdjustedProbability(self, value):
|
|
||||||
if value == 0 or value == 0.5 or self.value() == 0:
|
|
||||||
return value
|
|
||||||
if value < 0.5:
|
|
||||||
return 1.0 - self.getAdjustedProbability(1.0 - value)
|
|
||||||
coldness = 100.0 - self.value()
|
|
||||||
a = math.sqrt(coldness)
|
|
||||||
c = (10 - a) / 100
|
|
||||||
f = (c + 1) * value
|
|
||||||
# return max(f, 0.5)
|
|
||||||
# return max(f, 0.0)
|
|
||||||
# return (0 + (-f * math.log2(f)))
|
|
||||||
return -f * math.log2(f)
|
|
||||||
# TODO: use entropy
|
|
||||||
|
|
||||||
"""
|
|
||||||
This function returns the probability for a decision.
|
|
||||||
Copied above.
|
|
||||||
|
|
||||||
Please look at the last line of it. Strangely, it was
|
|
||||||
return max(f, 0.5). Does that make sense? Let's compare
|
|
||||||
some results. Where it was (0.5), we obtained, for example:
|
|
||||||
|
|
||||||
iiijjjlll: 670 (avg time 1108.5, avg temp 23.6)
|
|
||||||
iiijjjd: 2 (avg time 1156.0, avg temp 35.0)
|
|
||||||
iiijjjkkl: 315 (avg time 1194.4, avg temp 35.5)
|
|
||||||
iiijjjkll: 8 (avg time 2096.8, avg temp 44.1)
|
|
||||||
iiijjjkkd: 5 (avg time 837.2, avg temp 48.0)
|
|
||||||
|
|
||||||
wyz: 5 (avg time 2275.2, avg temp 14.9)
|
|
||||||
xyd: 982 (avg time 2794.4, avg temp 17.5)
|
|
||||||
yyz: 7 (avg time 2731.9, avg temp 25.1)
|
|
||||||
dyz: 2 (avg time 3320.0, avg temp 27.1)
|
|
||||||
xyy: 2 (avg time 4084.5, avg temp 31.1)
|
|
||||||
xyz: 2 (avg time 1873.5, avg temp 52.1)
|
|
||||||
|
|
||||||
Now, let's see what return max(f, 0.0000) does:
|
|
||||||
|
|
||||||
wyz: 7 (avg time 3192.9, avg temp 13.1)
|
|
||||||
xyd: 985 (avg time 2849.1, avg temp 17.5)
|
|
||||||
yyz: 6 (avg time 3836.7, avg temp 18.6)
|
|
||||||
xyy: 1 (avg time 1421.0, avg temp 19.5)
|
|
||||||
xyz: 1 (avg time 7350.0, avg temp 48.3)
|
|
||||||
|
|
||||||
They *seem* better (in the strict sense that we've obtained both
|
|
||||||
lower T and more times of wyz.) But they're *not* statistically
|
|
||||||
significant (for 1000 runs).
|
|
||||||
|
|
||||||
Now... looking at the code... it seems to be a mess... what does
|
|
||||||
function f() even mean in intuitive terms?
|
|
||||||
|
|
||||||
Work it does, but dude... quite a hack.
|
|
||||||
|
|
||||||
Another run, with return f @line89:
|
|
||||||
|
|
||||||
wyz: 8 (avg time 4140.5, avg temp 13.3)
|
|
||||||
yyz: 6 (avg time 2905.2, avg temp 14.5)
|
|
||||||
xyd: 982 (avg time 3025.4, avg temp 17.6)
|
|
||||||
dyz: 4 (avg time 4265.0, avg temp 17.7)
|
|
||||||
|
|
||||||
Does it even matter? Another (quick) run, I think with return (0.5):
|
|
||||||
|
|
||||||
dyz: 1 (avg time 5198.0, avg temp 15.3)
|
|
||||||
wyz: 3 (avg time 4043.7, avg temp 17.1)
|
|
||||||
yyz: 9 (avg time 3373.6, avg temp 21.0)
|
|
||||||
xyd: 84 (avg time 5011.1, avg temp 23.3)
|
|
||||||
xyy: 3 (avg time 4752.0, avg temp 27.9)
|
|
||||||
|
|
||||||
Compared to return(0.99):
|
|
||||||
|
|
||||||
xyd: 1000 (avg time 1625.2, avg temp 17.3)
|
|
||||||
|
|
||||||
Comparing to return f --> Statistically significant.
|
|
||||||
Comparing to return(0.5) --> same, so this return value does something.
|
|
||||||
|
|
||||||
Now running return(0.0):
|
|
||||||
|
|
||||||
xyz: 3 (avg time 3996.7, avg temp 81.1)
|
|
||||||
dyz: 46 (avg time 5931.7, avg temp 82.6)
|
|
||||||
xd: 17 (avg time 6090.3, avg temp 83.8)
|
|
||||||
xyd: 934 (avg time 7699.8, avg temp 88.1)
|
|
||||||
|
|
||||||
It's bad overall, but at least it's statistically significant!
|
|
||||||
|
|
||||||
return (-f * (math.log2(f))) # Entropy test #1 (global).
|
|
||||||
|
|
||||||
wyz: 123 (avg time 5933.1, avg temp 16.5)
|
|
||||||
xyy: 200 (avg time 6486.7, avg temp 27.8)
|
|
||||||
yyz: 330 (avg time 6310.2, avg temp 38.5)
|
|
||||||
dyz: 75 (avg time 6393.3, avg temp 39.6)
|
|
||||||
yzz: 5 (avg time 4965.0, avg temp 59.3)
|
|
||||||
xyz: 160 (avg time 6886.2, avg temp 60.2)
|
|
||||||
xd: 4 (avg time 2841.0, avg temp 61.8)
|
|
||||||
dz: 3 (avg time 3721.0, avg temp 62.1)
|
|
||||||
xyd: 100 (avg time 5853.1, avg temp 67.5)
|
|
||||||
|
|
||||||
Here we get an intuitive result: entropy/uncertainty seems better at
|
|
||||||
exploring a whole range of possible solutions. It even seems, at least
|
|
||||||
to me, better than the distribution obtained by the original copycat.
|
|
||||||
|
|
||||||
instead of log2, trying ln --> return (-f * math.log(f)):
|
|
||||||
|
|
||||||
wyz: 78 (avg time 7793.7, avg temp 16.6)
|
|
||||||
xyy: 202 (avg time 9168.5, avg temp 27.5)
|
|
||||||
wxz: 1 (avg time 3154.0, avg temp 33.4)
|
|
||||||
dyz: 63 (avg time 7950.3, avg temp 41.7)
|
|
||||||
yyz: 217 (avg time 8147.4, avg temp 41.7)
|
|
||||||
xyz: 201 (avg time 7579.7, avg temp 62.5)
|
|
||||||
xxy: 1 (avg time 7994.0, avg temp 64.8)
|
|
||||||
yzz: 8 (avg time 4672.6, avg temp 65.7)
|
|
||||||
xd: 9 (avg time 9215.2, avg temp 68.1)
|
|
||||||
xyd: 217 (avg time 7677.9, avg temp 73.8)
|
|
||||||
dz: 3 (avg time 20379.0, avg temp 77.3)
|
|
||||||
|
|
||||||
(quickly) trying out (1-this_entropy_function):
|
|
||||||
|
|
||||||
xyd: 100 (avg time 2984.3, avg temp 18.2)
|
|
||||||
|
|
||||||
And that's beautiful! One wants an inverse function that punishes
|
|
||||||
exploration and creativity, that takes all the fluidity off
|
|
||||||
the system.
|
|
||||||
|
|
||||||
But somehow this completely messes up with abc abd iijjkk:
|
|
||||||
|
|
||||||
jijjkk: 66 (avg time 3200.1, avg temp 61.3)
|
|
||||||
iijjkk: 114 (avg time 5017.2, avg temp 63.5)
|
|
||||||
dijjkk: 23 (avg time 2209.0, avg temp 67.3)
|
|
||||||
iijjkl: 748 (avg time 3262.8, avg temp 70.0)
|
|
||||||
iijjkd: 49 (avg time 2315.9, avg temp 76.3)
|
|
||||||
|
|
||||||
Which leads me to suspect that someone may have overfitted the
|
|
||||||
model for either xyz or iijjkk or some other problem, and one
|
|
||||||
improvement there means disaster here.
|
|
||||||
|
|
||||||
Something tells me to invert again to 1-entropy... and bingo!
|
|
||||||
|
|
||||||
iijjll: 59 (avg time 797.4, avg temp 19.8)
|
|
||||||
iijjkl: 41 (avg time 696.1, avg temp 28.5)
|
|
||||||
|
|
||||||
My guess is that some code is prefering to find groups in the
|
|
||||||
opposite form that it likes finding the "symmetry/opposite"
|
|
||||||
concepts of the xyz problem.
|
|
||||||
|
|
||||||
Sould compare & contrast the unhappiness and relevance of both
|
|
||||||
the opposite/symmetry codelets and the grouping/chunking codelets.
|
|
||||||
My hunch is the sameness group code: something there that
|
|
||||||
interacts with Temperature is wicked, and should be relatively
|
|
||||||
easy to find the error.
|
|
||||||
|
|
||||||
Here's why: the following run was done on (1-entropy(f)):
|
|
||||||
|
|
||||||
mrrlll: 77 (avg time 2195.7, avg temp 41.4)
|
|
||||||
mrrd: 2 (avg time 1698.0, avg temp 42.6)
|
|
||||||
mrrkkl: 20 (avg time 1317.8, avg temp 46.6)
|
|
||||||
mrrkkd: 1 (avg time 1835.0, avg temp 48.6)
|
|
||||||
|
|
||||||
|
|
||||||
If (1-entropy(f)) binds the system into a tight corridor of possibilities,
|
|
||||||
then why does it easily get the samenessGroup right? If this is right,
|
|
||||||
then running just entropy(f) should have big trouble with samenessGroup.
|
|
||||||
Let's see:
|
|
||||||
|
|
||||||
nrrkkk: 11 (avg time 3637.8, avg temp 64.6)
|
|
||||||
drrkkk: 3 (avg time 5921.3, avg temp 66.2)
|
|
||||||
mrrkkd: 7 (avg time 6771.3, avg temp 74.6)
|
|
||||||
mrrkkl: 79 (avg time 3723.0, avg temp 74.9)
|
|
||||||
|
|
||||||
So there we are: the system is unable to find that change samenessGroup
|
|
||||||
to next letterCategory, so there ought to be something very different
|
|
||||||
in the code that:
|
|
||||||
|
|
||||||
* Interacts with Temperature (things like unhappiness, relevance, depth,
|
|
||||||
urgency, and whatever else interacts with T)
|
|
||||||
* something very close to samenessGroup... sameGroup, sameness,
|
|
||||||
sameNeighbors, etc... is encoded in a form that is *directly opposite*
|
|
||||||
to other concepts/categories/codlets, etc.
|
|
||||||
|
|
||||||
|
|
||||||
Need to play with this more... and WTF is f anyways?
|
|
||||||
|
|
||||||
LSaldyt:
|
|
||||||
|
|
||||||
Recall self.value():
|
|
||||||
def value(self):
|
|
||||||
return 100.0 if self.clamped else self.actual_value
|
|
||||||
|
|
||||||
f in terms of value() and value only
|
|
||||||
f = ((10 - sqrt(100 - self.value()))/100 + 1) * value
|
|
||||||
so, the function: (10 - sqrt(100 - temp)) / 100
|
|
||||||
produces a scalar from the current temperature,
|
|
||||||
ranging from 1.0 when the temp is 0 to 1.1 when the temp is 100.
|
|
||||||
This is used to scale probablities in their inverse directions
|
|
||||||
|
|
||||||
For the original LISP program:
|
|
||||||
; This function is a filter: it inputs a value (from 0 to 100) and returns
|
|
||||||
; a probability (from 0 - 1) based on that value and the temperature.
|
|
||||||
*********************************************************
|
|
||||||
; When the temperature is 0, the result is (/ value 100), but at higher
|
|
||||||
; temperatures, values below 50 get raised and values above 50 get lowered
|
|
||||||
; as a function of temperature.
|
|
||||||
**********************************************************
|
|
||||||
; I think this whole formula could probably be simplified.
|
|
||||||
**********************************************************
|
|
||||||
|
|
||||||
(defun get-temperature-adjusted-probability (prob &aux low-prob-factor
|
|
||||||
result)
|
|
||||||
(setq result
|
|
||||||
(cond ((= prob 0) 0)
|
|
||||||
((<= prob .5)
|
|
||||||
(setq low-prob-factor (max 1 (truncate (abs (log prob 10)))))
|
|
||||||
(min (+ prob
|
|
||||||
(* (/ (- 10 (sqrt (fake-reciprocal *temperature*)))
|
|
||||||
100)
|
|
||||||
(- (expt 10 (- (1- low-prob-factor))) prob)))
|
|
||||||
.5))
|
|
||||||
|
|
||||||
((= prob .5) .5)
|
|
||||||
((> prob .5)
|
|
||||||
(max (- 1
|
|
||||||
(+ (- 1 prob)
|
|
||||||
(* (/ (- 10 (sqrt (fake-reciprocal *temperature*)))
|
|
||||||
100)
|
|
||||||
(- 1 (- 1 prob)))))
|
|
||||||
.5))))
|
|
||||||
result)
|
|
||||||
|
|
||||||
Which was tested using:
|
|
||||||
|
|
||||||
(defun test-get-temperature-adjusted-probability (prob)
|
|
||||||
(with-open-file (ostream "testfile" :direction :output
|
|
||||||
:if-does-not-exist :create
|
|
||||||
:if-exists :append)
|
|
||||||
(format ostream "prob: ~a~&" prob)
|
|
||||||
(loop for temp in '(0 10 20 30 40 50 60 70 80 90 100) do
|
|
||||||
(setq *temperature* temp)
|
|
||||||
(format ostream "Temperature: ~a; probability ~a~&"
|
|
||||||
temp (float (get-temperature-adjusted-probability prob))))
|
|
||||||
(format ostream "~%")))
|
|
||||||
|
|
||||||
Interpretation:
|
|
||||||
|
|
||||||
Importantly, the values of .5 in both the min and max correspond to the mid-cutoff of 50:
|
|
||||||
i.e. 'values below 50 get raised and values above 50 get lowered'
|
|
||||||
Still, it is interesting to note that changing 'return max(f, 0.0) to max(f, 0.5) has no significant effect on the distribution
|
|
||||||
|
|
||||||
It looks like the function below preserves most of the functionality of the original lisp.
|
|
||||||
However, the comments themselves agree that the formula is overly complicated.
|
|
||||||
|
|
||||||
"""
|
|
||||||
prob = value # Slightly more descriptive (and less ambiguous), will change argument
|
|
||||||
# Temperature, potentially clamped
|
|
||||||
temp = self.value()
|
|
||||||
iprob = 1 - prob
|
|
||||||
|
|
||||||
|
|
||||||
# This function does precisely what I think the original lisp comment describes, but provides crappy results
|
|
||||||
# return (temp / 200) * iprob + ((200 - temp) / 200) * prob
|
|
||||||
# However, this version preforms much better:
|
|
||||||
# Essentially, it weights probabilities towards their inverses when temperature is higher, and leaves them unaffected when it is lower.
|
|
||||||
# Some statistical analysis is needed of course
|
|
||||||
return (temp / 100) * iprob + ((100 - temp) / 100) * prob
|
|
||||||
|
|
||||||
# This will give only xyd answers:
|
|
||||||
#return 1 - (temp / 100) * iprob + ((100 - temp) / 100) * prob
|
|
||||||
"""
|
|
||||||
lucas@infinity:~/projects/personal/copycat$ ./main.py abc abd xyz --iterations 10 --plot
|
|
||||||
Answered wyz (time 3865, final temperature 13.9)
|
|
||||||
Answered wyz (time 8462, final temperature 10.8)
|
|
||||||
Answered wyz (time 6062, final temperature 11.7)
|
|
||||||
Answered yyz (time 4022, final temperature 15.6)
|
|
||||||
Answered yyz (time 2349, final temperature 59.8)
|
|
||||||
Answered xyd (time 17977, final temperature 14.9)
|
|
||||||
Answered xyd (time 1550, final temperature 14.7)
|
|
||||||
Answered xyd (time 11755, final temperature 16.8)
|
|
||||||
Answered wyz (time 2251, final temperature 13.7)
|
|
||||||
Answered yyz (time 13007, final temperature 11.7)
|
|
||||||
wyz: 4 (avg time 5160.0, avg temp 12.5)
|
|
||||||
xyd: 3 (avg time 10427.3, avg temp 15.5)
|
|
||||||
yyz: 3 (avg time 6459.3, avg temp 29.0)
|
|
||||||
|
|
||||||
However, it generally does worse on abc:abd::ijjkk:_
|
|
||||||
|
|
||||||
lucas@infinity:~/projects/personal/copycat$ ./main.py abc abd ijjkkk --iterations 10 --plot
|
|
||||||
Answered ijjlll (time 7127, final temperature 17.6)
|
|
||||||
Answered ijjlll (time 968, final temperature 17.5)
|
|
||||||
Answered ijjkkl (time 1471, final temperature 19.8)
|
|
||||||
Answered ijjlll (time 1058, final temperature 13.2)
|
|
||||||
Answered ijjkkl (time 489, final temperature 83.9)
|
|
||||||
Answered ijjkkl (time 1576, final temperature 18.7)
|
|
||||||
Answered ijjkkl (time 1143, final temperature 65.2)
|
|
||||||
Answered ijjkkl (time 3067, final temperature 19.6)
|
|
||||||
Answered ijjkkl (time 1973, final temperature 40.4)
|
|
||||||
Answered ijjkkl (time 1064, final temperature 50.6)
|
|
||||||
ijjlll: 3 (avg time 3051.0, avg temp 16.1)
|
|
||||||
ijjkkl: 7 (avg time 1540.4, avg temp 42.6)
|
|
||||||
"""
|
|
||||||
# unparameterized version
|
|
||||||
#curvedProb = (temp / 100) * iprob + (cold / 100) * prob
|
|
||||||
|
|
||||||
#if prob < .5:
|
|
||||||
# # Curving small (<.5) probabilities to .5, but not over
|
|
||||||
# return max(curvedProb, .5)
|
|
||||||
#else:
|
|
||||||
# # Curving large (>.5) probabilities to .5, but not under
|
|
||||||
# return min(curvedProb, .5)
|
|
||||||
|
|
||||||
# parameterized version : weights towards or away from probabilities
|
|
||||||
# alpha = 1.0
|
|
||||||
# beta = 1.0
|
|
||||||
# return ((alpha + temp / 100) * iprob + (beta + cold / 100) * prob) / (alpha + beta)
|
|
||||||
|
|
||||||
"""
|
|
||||||
# A scaling factor (between 0 and infinity), based on temperature (i.e. 100/coldness)
|
|
||||||
if temp == 100: # Avoid dividing by zero
|
|
||||||
factor = float('inf')
|
|
||||||
else:
|
|
||||||
# My factor:
|
|
||||||
# factor = 100 / (100 - temp)
|
|
||||||
# SQRT:
|
|
||||||
# factor = math.sqrt(100 / (100 - temp))
|
|
||||||
# Original factor:
|
|
||||||
# factor = (110 - math.sqrt(100 - temp)) / 100
|
|
||||||
# Factor ^ 10:
|
|
||||||
# factor = ((110 - math.sqrt(100 - temp)) / 100) ** 10.
|
|
||||||
# Factor ^ 20
|
|
||||||
# factor = ((110 - math.sqrt(100 - temp)) / 100) ** 20.
|
|
||||||
# No factor:
|
|
||||||
# factor = 1
|
|
||||||
if prob == .5:
|
|
||||||
return .5
|
|
||||||
elif prob > .5:
|
|
||||||
prob = prob / factor
|
|
||||||
elif prob < .5:
|
|
||||||
prob = prob * factor
|
|
||||||
return min(max(prob, 0), 1) # Normalize between 0 and 1.
|
|
||||||
|
|
||||||
if value == 0 or value == 0.5 or self.value() == 0:
|
|
||||||
return value
|
|
||||||
if value < 0.5:
|
|
||||||
return 1.0 - self.getAdjustedProbability(1.0 - value)
|
|
||||||
coldness = 100.0 - self.value()
|
|
||||||
a = math.sqrt(coldness)
|
|
||||||
c = (10 - a) / 100
|
|
||||||
f = (c + 1) * value
|
|
||||||
# return max(f, 0.5)
|
|
||||||
# return max(f, 0.0)
|
|
||||||
# return (0 + (-f * math.log2(f)))
|
|
||||||
return -f * math.log2(f)
|
|
||||||
'''
|
|
||||||
|
|||||||
52
multi-run.py
52
multi-run.py
@ -1,52 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import argparse, logging
|
|
||||||
from copycat import Copycat, Reporter, plot_answers, save_answers
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
class SimpleReporter(Reporter):
|
|
||||||
"""Reports results from a single run."""
|
|
||||||
def report_answer(self, answer):
|
|
||||||
"""Self-explanatory code."""
|
|
||||||
print('Answered %s (time %d, final temperature %.1f)' % (
|
|
||||||
answer['answer'], answer['time'], answer['temp'],
|
|
||||||
))
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument('--iterations', type=int, default=1, help='Run the given case this many times.')
|
|
||||||
options = parser.parse_args()
|
|
||||||
|
|
||||||
copycat = Copycat(reporter=SimpleReporter())
|
|
||||||
|
|
||||||
with open('input/reduced_problems.csv', 'r') as infile:
|
|
||||||
for line in infile:
|
|
||||||
line = line.replace('\n', '')
|
|
||||||
a, b, c = line.split(',')
|
|
||||||
answerList = copycat.run(a, b, c, options.iterations, True)
|
|
||||||
results = dict()
|
|
||||||
for formula, answers in answerList:
|
|
||||||
answers = sorted(answers.items(), key=lambda kv : kv[1]['count'])
|
|
||||||
keys = [k for k, v in answers]
|
|
||||||
counts = [v['count'] for k, v in answers]
|
|
||||||
results[formula] = (keys, counts)
|
|
||||||
|
|
||||||
originalCounts = defaultdict(lambda : 0)
|
|
||||||
originalCounts.update(dict(zip(*results['original'])))
|
|
||||||
|
|
||||||
for formula, (keys, counts) in results.items():
|
|
||||||
if formula != 'original':
|
|
||||||
chi2 = 0
|
|
||||||
for answer, count in zip(keys, counts):
|
|
||||||
originalCount = originalCounts[answer]
|
|
||||||
if originalCount != 0:
|
|
||||||
chi2 += (count + originalCount) ** 2 / originalCount
|
|
||||||
print('Chi^2 value for {}:{}'.format(formula, chi2))
|
|
||||||
|
|
||||||
#for answer, d in sorted(iter(answers.items()), key=lambda kv: kv[1]['avgtemp']):
|
|
||||||
#print('%s: %d (avg time %.1f, avg temp %.1f)' % (answer, d['count'], d['avgtime'], d['avgtemp']))
|
|
||||||
|
|
||||||
#filename = 'output/{}-{}-{}.csv'.format(a, b, c)
|
|
||||||
#save_answers(answers, filename)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
Reference in New Issue
Block a user