Major overhaul of temperature logic. Behavioral change.
I think the reason the temperature logic was so confused in the old code is because the Java code has a class `Temperature` that is used for graphical display *and* two variables in `formulas` that are used for most of the actual math. But somewhere along the line, some of the code in `formulas.java` started reading from `Temperature.value` as well. So the Python code was just faithfully copying that confusion. The actual abstraction here is a very simple "temperature" object with a stored value. It can be "clamped" to 100.0 for a given period. The only complication is that one of the codelets (the rule-transformer codelet) wants to get access to the "actual value" of the temperature even when it is clamped. The Python rule-transformer codelet also had a bug: it was accidentally setting `temperature.value` on the `temperature` module instead of on the `temperature.temperature` object! This turned some of its behavior into a no-op, for whatever that's worth. Lastly, the calculation of `finalTemperature` in the main program can now report 100.0 if the answer is found while the temperature is clamped. I don't fully understand why this didn't happen in the old code. I've hacked around it with `temperature.last_unclamped_value` for now, but I should TODO FIXME.
This commit is contained in:
@ -3,7 +3,7 @@ import logging
|
||||
import random
|
||||
|
||||
from slipnet import slipnet
|
||||
import temperature
|
||||
from temperature import temperature
|
||||
import formulas
|
||||
from workspaceFormulas import chooseDirectedNeighbor
|
||||
from workspaceFormulas import chooseNeighbor
|
||||
@ -130,7 +130,7 @@ def __slippability(conceptMappings):
|
||||
|
||||
@codelet('breaker')
|
||||
def breaker(coderack, codelet):
|
||||
probabilityOfFizzle = (100.0 - formulas.Temperature) / 100.0
|
||||
probabilityOfFizzle = (100.0 - temperature.value()) / 100.0
|
||||
if formulas.coinFlip(probabilityOfFizzle):
|
||||
return
|
||||
# choose a structure at random
|
||||
@ -804,13 +804,11 @@ def rule_translator(coderack, codelet):
|
||||
if bondDensity > 1.0:
|
||||
bondDensity = 1.0
|
||||
cutoff = __getCutOff(bondDensity) * 10.0
|
||||
assert cutoff >= formulas.actualTemperature
|
||||
if workspace.rule.buildTranslatedRule():
|
||||
workspace.foundAnswer = True
|
||||
else:
|
||||
temperature.clampTime = coderack.codeletsRun + 100
|
||||
temperature.clamped = True
|
||||
formulas.Temperature = 100.0
|
||||
if cutoff >= temperature.actual_value:
|
||||
if workspace.rule.buildTranslatedRule():
|
||||
workspace.foundAnswer = True
|
||||
else:
|
||||
temperature.clampUntil(coderack.codeletsRun + 100)
|
||||
|
||||
|
||||
@codelet('bottom-up-correspondence-scout')
|
||||
|
||||
@ -23,7 +23,7 @@ def probabilityOfPosting(workspace, codeletName):
|
||||
if codeletName == 'breaker':
|
||||
return 1.0
|
||||
if 'description' in codeletName:
|
||||
result = (formulas.Temperature / 100.0) ** 2
|
||||
result = (temperature.value() / 100.0) ** 2
|
||||
else:
|
||||
result = workspace.intraStringUnhappiness / 100.0
|
||||
if 'correspondence' in codeletName:
|
||||
@ -165,7 +165,7 @@ class Coderack(object):
|
||||
urgency = 3
|
||||
if codeletName == 'breaker':
|
||||
urgency = 1
|
||||
if formulas.Temperature < 25.0 and 'translator' in codeletName:
|
||||
if temperature.value() < 25.0 and 'translator' in codeletName:
|
||||
urgency = 5
|
||||
for _ in xrange(howMany):
|
||||
if formulas.coinFlip(probability):
|
||||
@ -303,7 +303,7 @@ class Coderack(object):
|
||||
|
||||
def chooseCodeletToRun(self):
|
||||
assert self.codelets
|
||||
scale = (100.0 - formulas.Temperature + 10.0) / 15.0
|
||||
scale = (100.0 - temperature.value() + 10.0) / 15.0
|
||||
urgsum = sum(codelet.urgency ** scale for codelet in self.codelets)
|
||||
threshold = random.random() * urgsum
|
||||
chosen = self.codelets[0]
|
||||
|
||||
@ -17,7 +17,7 @@ def mainLoop(lastUpdate):
|
||||
workspace.updateEverything()
|
||||
coderack.updateCodelets()
|
||||
slipnet.update()
|
||||
workspace.updateTemperature()
|
||||
temperature.update(workspace.getUpdatedTemperature())
|
||||
lastUpdate = currentTime
|
||||
logging.debug('Number of codelets: %d', len(coderack.codelets))
|
||||
coderack.chooseAndRunCodelet()
|
||||
@ -36,7 +36,7 @@ def runTrial(answers):
|
||||
answer = workspace.rule.finalAnswer
|
||||
else:
|
||||
answer = None
|
||||
finalTemperature = temperature.value
|
||||
finalTemperature = temperature.last_unclamped_value
|
||||
finalTime = coderack.codeletsRun
|
||||
print 'Answered %s (time %d, final temperature %.1f)' % (answer, finalTime, finalTemperature)
|
||||
answers[answer] = answers.get(answer, {'count': 0, 'tempsum': 0, 'timesum': 0})
|
||||
|
||||
@ -4,8 +4,6 @@ import random
|
||||
|
||||
from temperature import temperature
|
||||
|
||||
actualTemperature = Temperature = 100.0
|
||||
|
||||
|
||||
def selectListPosition(probabilities):
|
||||
total = sum(probabilities)
|
||||
@ -35,23 +33,18 @@ def weightedAverage(values):
|
||||
|
||||
|
||||
def temperatureAdjustedValue(value):
|
||||
#logging.info('Temperature: %s' % Temperature)
|
||||
#logging.info('actualTemperature: %s' % actualTemperature)
|
||||
return value ** (((100.0 - Temperature) / 30.0) + 0.5)
|
||||
return value ** (((100.0 - temperature.value()) / 30.0) + 0.5)
|
||||
|
||||
|
||||
def temperatureAdjustedProbability(value):
|
||||
if not value or value == 0.5 or not temperature.value:
|
||||
if value == 0 or value == 0.5 or temperature.value() == 0:
|
||||
return value
|
||||
if value < 0.5:
|
||||
return 1.0 - temperatureAdjustedProbability(1.0 - value)
|
||||
coldness = 100.0 - temperature.value
|
||||
coldness = 100.0 - temperature.value()
|
||||
a = math.sqrt(coldness)
|
||||
b = 10.0 - a
|
||||
c = b / 100
|
||||
d = c * (1.0 - (1.0 - value)) # as said the java
|
||||
e = (1.0 - value) + d
|
||||
f = 1.0 - e
|
||||
c = (10 - a) / 100
|
||||
f = (c + 1) * value
|
||||
return max(f, 0.5)
|
||||
|
||||
|
||||
|
||||
@ -1,19 +1,29 @@
|
||||
import logging
|
||||
|
||||
|
||||
class Temperature(object):
|
||||
def __init__(self):
|
||||
self.value = 100.0
|
||||
self.actual_value = 100.0
|
||||
self.last_unclamped_value = 100.0
|
||||
self.clamped = True
|
||||
self.clampTime = 30
|
||||
|
||||
def update(self, value):
|
||||
self.value = value
|
||||
self.last_unclamped_value = value
|
||||
if self.clamped:
|
||||
self.actual_value = 100.0
|
||||
else:
|
||||
self.actual_value = value
|
||||
|
||||
def clampUntil(self, when):
|
||||
self.clamped = True
|
||||
self.clampTime = when
|
||||
# but do not modify self.actual_value until someone calls update()
|
||||
|
||||
def tryUnclamp(self, currentTime):
|
||||
if self.clamped and currentTime >= self.clampTime:
|
||||
logging.info('unclamp temperature at %d', currentTime)
|
||||
self.clamped = False
|
||||
|
||||
def value(self):
|
||||
return 100.0 if self.clamped else self.actual_value
|
||||
|
||||
|
||||
temperature = Temperature()
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import logging
|
||||
|
||||
import formulas
|
||||
from temperature import temperature
|
||||
from workspaceString import WorkspaceString
|
||||
|
||||
|
||||
@ -85,19 +84,14 @@ class Workspace(object):
|
||||
self.initial.updateIntraStringUnhappiness()
|
||||
self.target.updateIntraStringUnhappiness()
|
||||
|
||||
def updateTemperature(self):
|
||||
def getUpdatedTemperature(self):
|
||||
self.assessTemperature()
|
||||
ruleWeakness = 100.0
|
||||
if self.rule:
|
||||
self.rule.updateStrength()
|
||||
ruleWeakness = 100.0 - self.rule.totalStrength
|
||||
values = ((self.totalUnhappiness, 0.8), (ruleWeakness, 0.2))
|
||||
above_actual_temperature = formulas.actualTemperature + 0.001
|
||||
formulas.actualTemperature = formulas.weightedAverage(values)
|
||||
if temperature.clamped:
|
||||
formulas.actualTemperature = 100.0
|
||||
formulas.Temperature = formulas.actualTemperature
|
||||
temperature.update(formulas.Temperature)
|
||||
return formulas.weightedAverage(values)
|
||||
|
||||
def numberOfUnrelatedObjects(self):
|
||||
"""A list of all objects in the workspace with >= 1 open bond slots"""
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import logging
|
||||
|
||||
from workspace import workspace
|
||||
from temperature import temperature
|
||||
from slipnet import slipnet
|
||||
import formulas
|
||||
|
||||
|
||||
Reference in New Issue
Block a user