Massive overhaul of "codelet methods" and the coderack.

Should be no functional change, but this gets rid of one circular
import (some codelet methods need a pointer to the coderack, but
they should be getting that pointer from their caller, not from
the global scope) and a lot of reflection-magic.
This commit is contained in:
Arthur O'Dwyer
2017-04-16 21:12:39 -07:00
parent f37b88d032
commit a3b122b75c
2 changed files with 80 additions and 107 deletions

View File

@ -1,15 +1,12 @@
import inspect
import random
import logging import logging
import random
from slipnet import slipnet from slipnet import slipnet
import temperature import temperature
import formulas import formulas
from workspaceFormulas import chooseDirectedNeighbor from workspaceFormulas import chooseDirectedNeighbor
from workspaceFormulas import chooseNeighbor from workspaceFormulas import chooseNeighbor
from coderack import coderack
from workspaceObject import WorkspaceObject from workspaceObject import WorkspaceObject
from letter import Letter from letter import Letter
from replacement import Replacement from replacement import Replacement
@ -21,6 +18,14 @@ from correspondence import Correspondence
from workspaceFormulas import chooseUnmodifiedObject from workspaceFormulas import chooseUnmodifiedObject
from workspaceFormulas import chooseBondFacet from workspaceFormulas import chooseBondFacet
def codelet(name):
"""Decorator for otherwise-unused functions that are in fact used as codelet behaviors"""
def wrap(f):
assert tuple(inspect.getargspec(f)) == (['coderack', 'codelet'], None, None, None)
f.is_codelet_method = True
f.codelet_name = name
return f
return wrap
# some methods common to the codelets # some methods common to the codelets
def __showWhichStringObjectIsFrom(structure): def __showWhichStringObjectIsFrom(structure):
@ -123,8 +128,8 @@ def __slippability(conceptMappings):
return False return False
# start the actual codelets @codelet('breaker')
def breaker(): def breaker(coderack, codelet):
probabilityOfFizzle = (100.0 - formulas.Temperature) / 100.0 probabilityOfFizzle = (100.0 - formulas.Temperature) / 100.0
assert not formulas.coinFlip(probabilityOfFizzle) assert not formulas.coinFlip(probabilityOfFizzle)
# choose a structure at random # choose a structure at random
@ -148,7 +153,8 @@ def breaker():
structure.break_the_structure() structure.break_the_structure()
def bottom_up_description_scout(codelet): @codelet('bottom-up-description-scout')
def bottom_up_description_scout(coderack, codelet):
chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects) chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects)
assert chosenObject assert chosenObject
__showWhichStringObjectIsFrom(chosenObject) __showWhichStringObjectIsFrom(chosenObject)
@ -165,7 +171,8 @@ def bottom_up_description_scout(codelet):
chosenProperty, codelet) chosenProperty, codelet)
def top_down_description_scout(codelet): @codelet('top-down-description-scout')
def top_down_description_scout(coderack, codelet):
descriptionType = codelet.arguments[0] descriptionType = codelet.arguments[0]
chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects) chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects)
assert chosenObject assert chosenObject
@ -179,7 +186,8 @@ def top_down_description_scout(codelet):
chosenProperty, codelet) chosenProperty, codelet)
def description_strength_tester(codelet): @codelet('description-strength-tester')
def description_strength_tester(coderack, codelet):
description = codelet.arguments[0] description = codelet.arguments[0]
description.descriptor.buffer = 100.0 description.descriptor.buffer = 100.0
description.updateStrength() description.updateStrength()
@ -189,7 +197,8 @@ def description_strength_tester(codelet):
coderack.newCodelet('description-builder', codelet, strength) coderack.newCodelet('description-builder', codelet, strength)
def description_builder(codelet): @codelet('description-builder')
def description_builder(coderack, codelet):
description = codelet.arguments[0] description = codelet.arguments[0]
assert description.object in workspace.objects assert description.object in workspace.objects
if description.object.described(description.descriptor): if description.object.described(description.descriptor):
@ -199,7 +208,8 @@ def description_builder(codelet):
description.build() description.build()
def bottom_up_bond_scout(codelet): @codelet('bottom-up-bond-scout')
def bottom_up_bond_scout(coderack, codelet):
source = chooseUnmodifiedObject('intraStringSalience', workspace.objects) source = chooseUnmodifiedObject('intraStringSalience', workspace.objects)
__showWhichStringObjectIsFrom(source) __showWhichStringObjectIsFrom(source)
destination = chooseNeighbor(source) destination = chooseNeighbor(source)
@ -222,7 +232,8 @@ def bottom_up_bond_scout(codelet):
sourceDescriptor, destinationDescriptor, codelet) sourceDescriptor, destinationDescriptor, codelet)
def rule_scout(codelet): @codelet('rule-scout')
def rule_scout(coderack, codelet):
assert workspace.numberOfUnreplacedObjects() == 0 assert workspace.numberOfUnreplacedObjects() == 0
changedObjects = [o for o in workspace.initial.objects if o.changed] changedObjects = [o for o in workspace.initial.objects if o.changed]
#assert len(changedObjects) < 2 #assert len(changedObjects) < 2
@ -284,7 +295,8 @@ def rule_scout(codelet):
slipnet.letter, relation, codelet) slipnet.letter, relation, codelet)
def rule_strength_tester(codelet): @codelet('rule-strength-tester')
def rule_strength_tester(coderack, codelet):
rule = codelet.arguments[0] rule = codelet.arguments[0]
rule.updateStrength() rule.updateStrength()
probability = formulas.temperatureAdjustedProbability( probability = formulas.temperatureAdjustedProbability(
@ -293,7 +305,8 @@ def rule_strength_tester(codelet):
coderack.newCodelet('rule-builder', codelet, rule.totalStrength, rule) coderack.newCodelet('rule-builder', codelet, rule.totalStrength, rule)
def replacement_finder(): @codelet('replacement-finder')
def replacement_finder(coderack, codelet):
# choose random letter in initial string # choose random letter in initial string
letters = [o for o in workspace.initial.objects if isinstance(o, Letter)] letters = [o for o in workspace.initial.objects if isinstance(o, Letter)]
letterOfInitialString = random.choice(letters) letterOfInitialString = random.choice(letters)
@ -330,7 +343,8 @@ def replacement_finder():
logging.info('building replacement') logging.info('building replacement')
def top_down_bond_scout__category(codelet): @codelet('top-down-bond-scout--category')
def top_down_bond_scout__category(coderack, codelet):
logging.info('top_down_bond_scout__category') logging.info('top_down_bond_scout__category')
category = codelet.arguments[0] category = codelet.arguments[0]
source = __getScoutSource(category, formulas.localBondCategoryRelevance, source = __getScoutSource(category, formulas.localBondCategoryRelevance,
@ -358,7 +372,8 @@ def top_down_bond_scout__category(codelet):
sourceDescriptor, codelet) sourceDescriptor, codelet)
def top_down_bond_scout__direction(codelet): @codelet('top-down-bond-scout--direction')
def top_down_bond_scout__direction(coderack, codelet):
direction = codelet.arguments[0] direction = codelet.arguments[0]
source = __getScoutSource( source = __getScoutSource(
direction, formulas.localDirectionCategoryRelevance, 'bond') direction, formulas.localDirectionCategoryRelevance, 'bond')
@ -376,7 +391,8 @@ def top_down_bond_scout__direction(codelet):
sourceDescriptor, destinationDescriptor, codelet) sourceDescriptor, destinationDescriptor, codelet)
def bond_strength_tester(codelet): @codelet('bond-strength-tester')
def bond_strength_tester(coderack, codelet):
bond = codelet.arguments[0] bond = codelet.arguments[0]
__showWhichStringObjectIsFrom(bond) __showWhichStringObjectIsFrom(bond)
bond.updateStrength() bond.updateStrength()
@ -391,7 +407,8 @@ def bond_strength_tester(codelet):
coderack.newCodelet('bond-builder', codelet, strength) coderack.newCodelet('bond-builder', codelet, strength)
def bond_builder(codelet): @codelet('bond-builder')
def bond_builder(coderack, codelet):
bond = codelet.arguments[0] bond = codelet.arguments[0]
__showWhichStringObjectIsFrom(bond) __showWhichStringObjectIsFrom(bond)
bond.updateStrength() bond.updateStrength()
@ -433,7 +450,8 @@ def bond_builder(codelet):
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
def top_down_group_scout__category(codelet): @codelet('top-down-group-scout--category')
def top_down_group_scout__category(coderack, codelet):
groupCategory = codelet.arguments[0] groupCategory = codelet.arguments[0]
category = groupCategory.getRelatedNode(slipnet.bondCategory) category = groupCategory.getRelatedNode(slipnet.bondCategory)
assert category assert category
@ -515,7 +533,8 @@ def top_down_group_scout__category(codelet):
direction, bondFacet, codelet) direction, bondFacet, codelet)
def top_down_group_scout__direction(codelet): @codelet('top-down-group-scout--direction')
def top_down_group_scout__direction(coderack, codelet):
direction = codelet.arguments[0] direction = codelet.arguments[0]
source = __getScoutSource(direction, source = __getScoutSource(direction,
formulas.localDirectionCategoryRelevance, formulas.localDirectionCategoryRelevance,
@ -606,7 +625,8 @@ def top_down_group_scout__direction(codelet):
#noinspection PyStringFormat #noinspection PyStringFormat
def group_scout__whole_string(codelet): @codelet('group-scout--whole-string')
def group_scout__whole_string(coderack, codelet):
string = workspace.initial string = workspace.initial
if random.random() > 0.5: if random.random() > 0.5:
string = workspace.target string = workspace.target
@ -646,7 +666,8 @@ def group_scout__whole_string(codelet):
bondFacet, codelet) bondFacet, codelet)
def group_strength_tester(codelet): @codelet('group-strength-tester')
def group_strength_tester(coderack, codelet):
# update strength value of the group # update strength value of the group
group = codelet.arguments[0] group = codelet.arguments[0]
__showWhichStringObjectIsFrom(group) __showWhichStringObjectIsFrom(group)
@ -661,7 +682,8 @@ def group_strength_tester(codelet):
coderack.newCodelet('group-builder', codelet, strength) coderack.newCodelet('group-builder', codelet, strength)
def group_builder(codelet): @codelet('group-builder')
def group_builder(coderack, codelet):
# update strength value of the group # update strength value of the group
group = codelet.arguments[0] group = codelet.arguments[0]
#print '%s' % group #print '%s' % group
@ -735,7 +757,8 @@ def group_builder(codelet):
logging.info('building group') logging.info('building group')
def rule_builder(codelet): @codelet('rule-builder')
def rule_builder(coderack, codelet):
rule = codelet.arguments[0] rule = codelet.arguments[0]
if rule.ruleEqual(workspace.rule): if rule.ruleEqual(workspace.rule):
rule.activateRuleDescriptions() rule.activateRuleDescriptions()
@ -768,7 +791,8 @@ def __getCutOff(density):
return len(distribution) return len(distribution)
def rule_translator(): @codelet('rule-translator')
def rule_translator(coderack, codelet):
assert workspace.rule assert workspace.rule
if len(workspace.initial) == 1 and len(workspace.target) == 1: if len(workspace.initial) == 1 and len(workspace.target) == 1:
bondDensity = 1.0 bondDensity = 1.0
@ -789,7 +813,8 @@ def rule_translator():
formulas.Temperature = 100.0 formulas.Temperature = 100.0
def bottom_up_correspondence_scout(codelet): @codelet('bottom-up-correspondence-scout')
def bottom_up_correspondence_scout(coderack, codelet):
objectFromInitial = chooseUnmodifiedObject('interStringSalience', objectFromInitial = chooseUnmodifiedObject('interStringSalience',
workspace.initial.objects) workspace.initial.objects)
objectFromTarget = chooseUnmodifiedObject('interStringSalience', objectFromTarget = chooseUnmodifiedObject('interStringSalience',
@ -826,7 +851,8 @@ def bottom_up_correspondence_scout(codelet):
conceptMappings, flipTargetObject, codelet) conceptMappings, flipTargetObject, codelet)
def important_object_correspondence_scout(codelet): @codelet('important-object-correspondence-scout')
def important_object_correspondence_scout(coderack, codelet):
objectFromInitial = chooseUnmodifiedObject('relativeImportance', objectFromInitial = chooseUnmodifiedObject('relativeImportance',
workspace.initial.objects) workspace.initial.objects)
descriptors = objectFromInitial.relevantDistinguishingDescriptors() descriptors = objectFromInitial.relevantDistinguishingDescriptors()
@ -876,7 +902,8 @@ def important_object_correspondence_scout(codelet):
conceptMappings, flipTargetObject, codelet) conceptMappings, flipTargetObject, codelet)
def correspondence_strength_tester(codelet): @codelet('correspondence-strength-tester')
def correspondence_strength_tester(coderack, codelet):
correspondence = codelet.arguments[0] correspondence = codelet.arguments[0]
objectFromInitial = correspondence.objectFromInitial objectFromInitial = correspondence.objectFromInitial
objectFromTarget = correspondence.objectFromTarget objectFromTarget = correspondence.objectFromTarget
@ -899,7 +926,8 @@ def correspondence_strength_tester(codelet):
strength, correspondence) strength, correspondence)
def correspondence_builder(codelet): @codelet('correspondence-builder')
def correspondence_builder(coderack, codelet):
correspondence = codelet.arguments[0] correspondence = codelet.arguments[0]
objectFromInitial = correspondence.objectFromInitial objectFromInitial = correspondence.objectFromInitial
objectFromTarget = correspondence.objectFromTarget objectFromTarget = correspondence.objectFromTarget

View File

@ -1,9 +1,8 @@
import re
import inspect
import math import math
import logging import logging
import random import random
import codeletMethods
import formulas import formulas
import workspaceFormulas import workspaceFormulas
from slipnet import slipnet from slipnet import slipnet
@ -24,18 +23,17 @@ def getUrgencyBin(urgency):
class CodeRack(object): class CodeRack(object):
def __init__(self): def __init__(self):
self.speedUpBonds = False
self.removeBreakerCodelets = False
self.removeTerracedScan = False
self.pressures = CoderackPressures() self.pressures = CoderackPressures()
self.pressures.initialisePressures() self.pressures.initialisePressures()
self.reset() self.reset()
self.initialCodeletNames = ('bottom-up-bond-scout', self.initialCodeletNames = (
'replacement-finder', 'bottom-up-bond-scout',
'bottom-up-correspondence-scout') 'replacement-finder',
self.codeletMethodsDir = None 'bottom-up-correspondence-scout',
)
self.runCodelets = {} self.runCodelets = {}
self.postings = {} self.postings = {}
self.getCodeletMethods()
def reset(self): def reset(self):
self.codelets = [] self.codelets = []
@ -87,17 +85,11 @@ class CodeRack(object):
self.__postBottomUpCodelets('replacement-finder') self.__postBottomUpCodelets('replacement-finder')
self.__postBottomUpCodelets('rule-scout') self.__postBottomUpCodelets('rule-scout')
self.__postBottomUpCodelets('rule-translator') self.__postBottomUpCodelets('rule-translator')
if not self.removeBreakerCodelets: self.__postBottomUpCodelets('breaker')
self.__postBottomUpCodelets('breaker')
def __postBottomUpCodelets(self, codeletName): def __postBottomUpCodelets(self, codeletName):
probability = workspaceFormulas.probabilityOfPosting(codeletName) probability = workspaceFormulas.probabilityOfPosting(codeletName)
howMany = workspaceFormulas.howManyToPost(codeletName) howMany = workspaceFormulas.howManyToPost(codeletName)
#if codeletName == 'bottom-up-bond-scout':
# print 'post --> %f:%d' % (probability,howMany)
if self.speedUpBonds:
if 'bond' in codeletName or 'group' in codeletName:
howMany *= 3
urgency = 3 urgency = 3
if codeletName == 'breaker': if codeletName == 'breaker':
urgency = 1 urgency = 1
@ -121,7 +113,7 @@ class CodeRack(object):
else: else:
newCodelet.arguments = oldCodelet.arguments newCodelet.arguments = oldCodelet.arguments
newCodelet.pressure = oldCodelet.pressure newCodelet.pressure = oldCodelet.pressure
self.tryRun(newCodelet) self.post(newCodelet)
# pylint: disable=too-many-arguments # pylint: disable=too-many-arguments
def proposeRule(self, facet, description, category, relation, oldCodelet): def proposeRule(self, facet, description, category, relation, oldCodelet):
@ -209,7 +201,7 @@ class CodeRack(object):
return None return None
urgencies = [] urgencies = []
for codelet in self.codelets: for codelet in self.codelets:
urgency = ((coderack.codeletsRun - codelet.timeStamp) * urgency = ((self.codeletsRun - codelet.timeStamp) *
(7.5 - codelet.urgency)) (7.5 - codelet.urgency))
urgencies += [urgency] urgencies += [urgency]
threshold = random.random() * sum(urgencies) threshold = random.random() * sum(urgencies)
@ -226,17 +218,14 @@ class CodeRack(object):
codelet = Codelet(name, 1, self.codeletsRun) codelet = Codelet(name, 1, self.codeletsRun)
self.post(codelet) self.post(codelet)
def tryRun(self, newCodelet): def getCodeletMethods(self):
if self.removeTerracedScan: self.methods = {}
self.run(newCodelet) for name in dir(codeletMethods):
else: method = getattr(codeletMethods, name)
self.post(newCodelet) if getattr(method, 'is_codelet_method', False):
self.methods[method.codelet_name] = method
def getCodeletmethods(self): assert set(self.methods.keys()) == set([
import codeletMethods
self.codeletMethodsDir = dir(codeletMethods)
knownCodeletNames = (
'breaker', 'breaker',
'bottom-up-description-scout', 'bottom-up-description-scout',
'top-down-description-scout', 'top-down-description-scout',
@ -261,19 +250,11 @@ class CodeRack(object):
'important-object-correspondence-scout', 'important-object-correspondence-scout',
'correspondence-strength-tester', 'correspondence-strength-tester',
'correspondence-builder', 'correspondence-builder',
) ])
self.methods = {}
for codeletName in knownCodeletNames:
methodName = re.sub('[ -]', '_', codeletName)
if methodName not in self.codeletMethodsDir:
raise NotImplementedError(
'Cannot find %s in codeletMethods' % methodName)
method = getattr(codeletMethods, methodName)
self.methods[methodName] = method
def chooseAndRunCodelet(self): def chooseAndRunCodelet(self):
if not len(coderack.codelets): if not len(self.codelets):
coderack.postInitialCodelets() self.postInitialCodelets()
codelet = self.chooseCodeletToRun() codelet = self.chooseCodeletToRun()
if codelet: if codelet:
self.run(codelet) self.run(codelet)
@ -282,21 +263,6 @@ class CodeRack(object):
if not self.codelets: if not self.codelets:
return None return None
#logging.info('temperature: %f', formulas.Temperature)
#logging.info('actualTemperature: %f', formulas.actualTemperature)
#logging.info('Slipnet:')
#for node in slipnet.slipnodes:
# logging.info("\tnode %s, activation: %d, buffer: %d, depth: %s",
# node.get_name(), node.activation, node.buffer,
# node.conceptualDepth)
#logging.info('Coderack:')
#for codelet in self.codelets:
# logging.info('\t%s, %d', codelet.name, codelet.urgency)
#from workspace import workspace
#workspace.initial.log("Initial: ")
#workspace.target.log("Target: ")
scale = (100.0 - formulas.Temperature + 10.0) / 15.0 scale = (100.0 - formulas.Temperature + 10.0) / 15.0
urgsum = sum(codelet.urgency ** scale for codelet in self.codelets) urgsum = sum(codelet.urgency ** scale for codelet in self.codelets)
threshold = random.random() * urgsum threshold = random.random() * urgsum
@ -314,33 +280,12 @@ class CodeRack(object):
return chosen return chosen
def run(self, codelet): def run(self, codelet):
methodName = re.sub('[ -]', '_', codelet.name) methodName = codelet.name
self.codeletsRun += 1 self.codeletsRun += 1
self.runCodelets[methodName] = self.runCodelets.get(methodName, 0) + 1 self.runCodelets[methodName] = self.runCodelets.get(methodName, 0) + 1
#if self.codeletsRun > 2000:
#import sys
#print "running too many codelets"
#for name,count in self.postings.iteritems():
#print '%d:%s' % (count,name)
#raise ValueError
#else:
# print 'running %d' % self.codeletsRun
if not self.codeletMethodsDir:
self.getCodeletmethods()
#if not self.codeletMethodsDir:
method = self.methods[methodName] method = self.methods[methodName]
if not method:
raise ValueError('Found %s in codeletMethods, but cannot get it',
methodName)
if not callable(method):
raise RuntimeError('Cannot call %s()' % methodName)
args, _varargs, _varkw, _defaults = inspect.getargspec(method)
try: try:
if 'codelet' in args: method(self, codelet)
method(codelet)
else:
method()
except AssertionError: except AssertionError:
pass pass