diff --git a/copycat/bond.py b/copycat/bond.py index 778c4f1..666e466 100644 --- a/copycat/bond.py +++ b/copycat/bond.py @@ -2,8 +2,9 @@ from workspaceStructure import WorkspaceStructure from slipnet import slipnet from workspace import workspace + class Bond(WorkspaceStructure): - def __init__(self,source, destination, bondCategory, bondFacet, sourceDescriptor, destinationDescriptor): + def __init__(self, source, destination, bondCategory, bondFacet, sourceDescriptor, destinationDescriptor): WorkspaceStructure.__init__(self) self.source = source self.string = self.source.string @@ -38,18 +39,18 @@ class Bond(WorkspaceStructure): return '' % self.__str__() def __str__(self): - return '%s bond between %s and %s' % ( self.category.name, self.leftObject, self.rightObject) + return '%s bond between %s and %s' % (self.category.name, self.leftObject, self.rightObject) def buildBond(self): - workspace.structures += [ self ] - self.string.bonds += [ self ] + workspace.structures += [self] + self.string.bonds += [self] self.category.buffer = 100.0 if self.directionCategory: self.directionCategory.buffer = 100.0 self.leftObject.rightBond = self self.rightObject.leftBond = self - self.leftObject.bonds += [ self ] - self.rightObject.bonds += [ self ] + self.leftObject.bonds += [self] + self.rightObject.bonds += [self] def break_the_structure(self): self.breakBond() @@ -78,7 +79,7 @@ class Bond(WorkspaceStructure): objekt = self.leftObject.correspondence.objectFromInitial if objekt.leftmost and objekt.rightBond: if objekt.rightBond.directionCategory and objekt.rightBond.directionCategory != self.directionCategory: - incompatibles += [ correspondence ] + incompatibles += [correspondence] if self.rightObject.rightmost and self.rightObject.correspondence: correspondence = self.rightObject.correspondence if self.string == workspace.initial: @@ -87,7 +88,7 @@ class Bond(WorkspaceStructure): objekt = self.rightObject.correspondence.objectFromInitial if objekt.rightmost and objekt.leftBond: if objekt.leftBond.directionCategory and objekt.leftBond.directionCategory != self.directionCategory: - incompatibles += [ correspondence ] + incompatibles += [correspondence] return incompatibles def updateInternalStrength(self): @@ -104,7 +105,7 @@ class Bond(WorkspaceStructure): facetFactor = 1.0 else: facetFactor = 0.7 - strength = min(100.0,memberCompatibility * facetFactor * self.category.bondDegreeOfAssociation()) + strength = min(100.0, memberCompatibility * facetFactor * self.category.bondDegreeOfAssociation()) self.internalStrength = strength def updateExternalStrength(self): @@ -114,21 +115,21 @@ class Bond(WorkspaceStructure): density = self.localDensity() / 100.0 density = density ** 0.5 * 100.0 supportFactor = 0.6 ** (1.0 / supporters ** 3) - supportFactor = max(1.0,supportFactor) + supportFactor = max(1.0, supportFactor) strength = supportFactor * density self.externalStrength = strength def numberOfLocalSupportingBonds(self): - return len([ b for b in self.string.bonds if b.string == self.get_source().string and + return len([b for b in self.string.bonds if b.string == self.get_source().string and self.leftObject.letterDistance(b.leftObject) != 0 and self.rightObject.letterDistance(b.rightObject) != 0 and self.category == b.category and - self.directionCategory == b.directionCategory ]) + self.directionCategory == b.directionCategory]) - def sameCategories(self,other): + def sameCategories(self, other): return self.category == other.category and self.directionCategory == other.directionCategory - def myEnds(self,object1,object2): + def myEnds(self, object1, object2): if self.get_source() == object1 and self.destination == object2: return True return self.get_source() == object2 and self.destination == object1 @@ -144,19 +145,19 @@ class Bond(WorkspaceStructure): if object1.beside(object2): slotSum += 1.0 for bond in self.string.bonds: - if bond != self and self.sameCategories(bond) and self.myEnds(object1,object2): + if bond != self and self.sameCategories(bond) and self.myEnds(object1, object2): supportSum += 1.0 if slotSum == 0.0: return 0.0 return 100.0 * supportSum / slotSum - def sameNeighbours(self,other): + def sameNeighbours(self, other): if self.leftObject == other.leftObject: return True return self.rightObject == other.rightObject def getIncompatibleBonds(self): - return [ b for b in self.string.bonds if self.sameNeighbours(b) ] + return [b for b in self.string.bonds if self.sameNeighbours(b)] def get_source(self): return self.source @@ -164,19 +165,20 @@ class Bond(WorkspaceStructure): def set_source(self, value): self.source = value + def possibleGroupBonds(bondCategory, directionCategory, bondFacet, bonds): result = [] for bond in bonds: if bond.category == bondCategory and bond.directionCategory == directionCategory: - result += [ bond ] + result += [bond] else: # a modified bond might be made if bondCategory == slipnet.sameness: - return None # a different bond cannot be made here + return None # a different bond cannot be made here if bond.category == bondCategory or bond.directionCategory == directionCategory: - return None # a different bond cannot be made here + return None # a different bond cannot be made here if bond.category == slipnet.sameness: return None bond = Bond(bond.destination, bond.get_source(), bondCategory, bondFacet, bond.destinationDescriptor, bond.sourceDescriptor) - result += [ bond ] + result += [bond] return result diff --git a/copycat/codeletMethods.py b/copycat/codeletMethods.py index 4de8dff..f618add 100644 --- a/copycat/codeletMethods.py +++ b/copycat/codeletMethods.py @@ -10,56 +10,63 @@ from group import Group from bond import Bond, possibleGroupBonds from correspondence import Correspondence + # some methods common to the codelets def __showWhichStringObjectIsFrom(structure): if not structure: return whence = 'other' - if isinstance(structure,WorkspaceObject): - whence='target' + if isinstance(structure, WorkspaceObject): + whence = 'target' if structure.string == workspace.initial: - whence='initial' - print 'object chosen = %s from %s string' % ( structure, whence ) + whence = 'initial' + print 'object chosen = %s from %s string' % (structure, whence) -def __getScoutSource(slipnode,relevanceMethod,typeName): - initialRelevance = relevanceMethod(workspace.initial,slipnode) - targetRelevance = relevanceMethod(workspace.target,slipnode) + +def __getScoutSource(slipnode, relevanceMethod, typeName): + initialRelevance = relevanceMethod(workspace.initial, slipnode) + targetRelevance = relevanceMethod(workspace.target, slipnode) initialUnhappiness = workspace.initial.intraStringUnhappiness targetUnhappiness = workspace.target.intraStringUnhappiness - logging.info('initial : relevance = %d, unhappiness=%d' % (initialRelevance,int(initialUnhappiness)) ) - logging.info('target : relevance = %d, unhappiness=%d' % (targetRelevance,int(targetUnhappiness)) ) + logging.info('initial : relevance = %d, unhappiness=%d' % (initialRelevance, int(initialUnhappiness))) + logging.info('target : relevance = %d, unhappiness=%d' % (targetRelevance, int(targetUnhappiness))) string = workspace.initial - if utils.random() * (initialRelevance + initialUnhappiness+targetRelevance+targetUnhappiness) > (initialRelevance + initialUnhappiness): + if utils.random() * (initialRelevance + initialUnhappiness + targetRelevance + targetUnhappiness) > (initialRelevance + initialUnhappiness): string = workspace.target - logging.info('target string selected: %s for %s' % (workspace.target,typeName)) + logging.info('target string selected: %s for %s' % (workspace.target, typeName)) else: - logging.info('initial string selected: %s for %s' % (workspace.initial,typeName)) - source = chooseUnmodifiedObject('intraStringSalience',string.objects) + logging.info('initial string selected: %s for %s' % (workspace.initial, typeName)) + source = chooseUnmodifiedObject('intraStringSalience', string.objects) return source -def __getBondFacet(source,destination): - bondFacet = chooseBondFacet(source,destination) + +def __getBondFacet(source, destination): + bondFacet = chooseBondFacet(source, destination) assert bondFacet return bondFacet -def __getDescriptors(bondFacet,source,destination): + +def __getDescriptors(bondFacet, source, destination): sourceDescriptor = source.getDescriptor(bondFacet) destinationDescriptor = destination.getDescriptor(bondFacet) assert sourceDescriptor and destinationDescriptor return sourceDescriptor, destinationDescriptor -def __allOppositeMappings(mappings): - return len([ m for m in mappings if m.label != slipnet.opposite ]) == 0 -def __structureVsStructure(structure1,weight1,structure2,weight2): +def __allOppositeMappings(mappings): + return len([m for m in mappings if m.label != slipnet.opposite]) == 0 + + +def __structureVsStructure(structure1, weight1, structure2, weight2): structure1.updateStrength() structure2.updateStrength() weightedStrength1 = temperatureAdjustedValue(structure1.totalStrength * weight1) weightedStrength2 = temperatureAdjustedValue(structure2.totalStrength * weight2) rhs = (weightedStrength1 + weightedStrength2) * utils.random() - logging.info('%d > %d' % (weightedStrength1,rhs)) + logging.info('%d > %d' % (weightedStrength1, rhs)) return weightedStrength1 > rhs + def __fightItOut(structure, structureWeight, incompatibles, incompatibleWeight): if not (incompatibles and len(incompatibles)): return True @@ -70,9 +77,10 @@ def __fightItOut(structure, structureWeight, incompatibles, incompatibleWeight): logging.info('won fight with %s' % incompatible) return True -def __fightIncompatibles(incompatibles,structure,name,structureWeight,incompatibleWeight): + +def __fightIncompatibles(incompatibles, structure, name, structureWeight, incompatibleWeight): if len(incompatibles): - if __fightItOut(structure,structureWeight,incompatibles,incompatibleWeight): + if __fightItOut(structure, structureWeight, incompatibles, incompatibleWeight): logging.info('broke the %s' % name) return True logging.info('failed to break %s: Fizzle' % name) @@ -80,6 +88,7 @@ def __fightIncompatibles(incompatibles,structure,name,structureWeight,incompatib logging.info('no incompatible %s' % name) return True + def __slippability(conceptMappings): for mapping in conceptMappings: slippiness = mapping.slipability() / 100.0 @@ -88,64 +97,69 @@ def __slippability(conceptMappings): return True return False + # start the actual codelets def breaker(): - probabilityOfFizzle = (100.0-Temperature)/100.0 + probabilityOfFizzle = (100.0 - Temperature) / 100.0 assert not coinFlip(probabilityOfFizzle) # choose a structure at random - structures = [ s for s in workspace.structures if - isinstance(s,Group) or - isinstance(s,Bond) or - isinstance(s,Correspondence) ] + structures = [s for s in workspace.structures if + isinstance(s, Group) or + isinstance(s, Bond) or + isinstance(s, Correspondence)] assert len(structures) structure = utils.choice(structures) __showWhichStringObjectIsFrom(structure) - breakObjects = [ structure ] - if isinstance(structure,Bond): + breakObjects = [structure] + if isinstance(structure, Bond): if structure.source.group and structure.source.group == structure.destination.group: - breakObjects += [ structure.source.group ] + breakObjects += [structure.source.group] # try to break all objects for structure in breakObjects: - breakProbability = temperatureAdjustedProbability(structure.totalStrength/100.0) + breakProbability = temperatureAdjustedProbability(structure.totalStrength / 100.0) if coinFlip(breakProbability): return for structure in breakObjects: structure.break_the_structure() + def bottom_up_description_scout(codelet): - chosenObject = chooseUnmodifiedObject('totalSalience',workspace.objects) + chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects) assert chosenObject __showWhichStringObjectIsFrom(chosenObject) description = chooseRelevantDescriptionByActivation(chosenObject) assert description sliplinks = similarPropertyLinks(description.descriptor) assert sliplinks and len(sliplinks) - values = [ sliplink.degreeOfAssociation() * sliplink.destination.activation for sliplink in sliplinks ] + values = [sliplink.degreeOfAssociation() * sliplink.destination.activation for sliplink in sliplinks] i = selectListPosition(values) - chosen = sliplinks[ i ] + chosen = sliplinks[i] chosenProperty = chosen.destination - coderack.proposeDescription(chosenObject,chosenProperty.category(),chosenProperty,codelet) + coderack.proposeDescription(chosenObject, chosenProperty.category(), chosenProperty, codelet) + def top_down_description_scout(codelet): descriptionType = codelet.arguments[0] - chosenObject = chooseUnmodifiedObject('totalSalience',workspace.objects) + chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects) assert chosenObject __showWhichStringObjectIsFrom(chosenObject) descriptions = chosenObject.getPossibleDescriptions(descriptionType) assert descriptions and len(descriptions) - values = [ n.activation for n in descriptions ] + values = [n.activation for n in descriptions] i = selectListPosition(values) - chosenProperty = descriptions[ i ] - coderack.proposeDescription(chosenObject,chosenProperty.category(), chosenProperty,codelet) + chosenProperty = descriptions[i] + coderack.proposeDescription(chosenObject, chosenProperty.category(), chosenProperty, codelet) + def description_strength_tester(codelet): description = codelet.arguments[0] description.descriptor.buffer = 100.0 description.updateStrength() strength = description.totalStrength - probability = temperatureAdjustedProbability(strength/100.0) + probability = temperatureAdjustedProbability(strength / 100.0) assert formulas.coinFlip(probability) - coderack.newCodelet('description-builder',codelet,strength) + coderack.newCodelet('description-builder', codelet, strength) + def description_builder(codelet): description = codelet.arguments[0] @@ -156,16 +170,17 @@ def description_builder(codelet): else: description.build() + def bottom_up_bond_scout(codelet): - source = chooseUnmodifiedObject('intraStringSalience',workspace.objects) + source = chooseUnmodifiedObject('intraStringSalience', workspace.objects) __showWhichStringObjectIsFrom(source) destination = chooseNeighbour(source) assert destination logging.info('destination: %s' % destination) - bondFacet = __getBondFacet(source,destination) + bondFacet = __getBondFacet(source, destination) logging.info('chosen bond facet: %s' % bondFacet.get_name()) - logging.info('Source: %s, destination: %s' % (source,destination)) - sourceDescriptor, destinationDescriptor = __getDescriptors(bondFacet,source,destination) + logging.info('Source: %s, destination: %s' % (source, destination)) + sourceDescriptor, destinationDescriptor = __getDescriptors(bondFacet, source, destination) logging.info("source descriptor: " + sourceDescriptor.name.upper()) logging.info("destination descriptior: " + destinationDescriptor.name.upper()) category = sourceDescriptor.getBondCategory(destinationDescriptor) @@ -173,15 +188,16 @@ def bottom_up_bond_scout(codelet): if category == slipnet.identity: category = slipnet.sameness logging.info('proposing %s bond ' % category.name) - coderack.proposeBond(source,destination,category,bondFacet,sourceDescriptor,destinationDescriptor,codelet) + coderack.proposeBond(source, destination, category, bondFacet, sourceDescriptor, destinationDescriptor, codelet) + def rule_scout(codelet): 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 # if there are no changed objects, propose a rule with no changes if not changedObjects: - return coderack.proposeRule(None,None,None,None,codelet) + return coderack.proposeRule(None, None, None, None, codelet) changed = changedObjects[-1] # generate a list of distinguishing descriptions for the first object @@ -190,11 +206,11 @@ def rule_scout(codelet): objectList = [] position = changed.getDescriptor(slipnet.stringPositionCategory) if position: - objectList += [ position ] + objectList += [position] letter = changed.getDescriptor(slipnet.letterCategory) - otherObjectsOfSameLetter = [ o for o in workspace.initial.objects if not o != changed and o.getDescriptionType(letter) ] - if not len(otherObjectsOfSameLetter): # then the letter is a distinguishing feature - objectList += [ letter ] + otherObjectsOfSameLetter = [o for o in workspace.initial.objects if not o != changed and o.getDescriptionType(letter)] + if not len(otherObjectsOfSameLetter): # then the letter is a distinguishing feature + objectList += [letter] # if this object corresponds to another object in the workspace # objectList = the union of this and the distingushing descriptors if changed.correspondence: @@ -204,49 +220,51 @@ def rule_scout(codelet): for node in objectList: node = node.applySlippages(slippages) if targetObject.hasDescription(node) and targetObject.distinguishingDescriptor(node): - newList += [ node ] - objectList = newList # XXX surely this should be += ("the union of this and the distinguishing descriptors") + newList += [node] + objectList = newList # XXX surely this should be += ("the union of this and the distinguishing descriptors") assert objectList and len(objectList) # use conceptual depth to choose a description valueList = [] for node in objectList: depth = node.conceptualDepth value = temperatureAdjustedValue(depth) - valueList += [ value ] + valueList += [value] i = selectListPosition(valueList) - descriptor = objectList[ i ] + descriptor = objectList[i] # choose the relation (change the letmost object to..xxxx) i.e. "successor" or "d" objectList = [] if changed.replacement.relation: - objectList += [ changed.replacement.relation ] - objectList += [ changed.replacement.objectFromModified.getDescriptor(slipnet.letterCategory) ] + objectList += [changed.replacement.relation] + objectList += [changed.replacement.objectFromModified.getDescriptor(slipnet.letterCategory)] # use conceptual depth to choose a relation valueList = [] for node in objectList: depth = node.conceptualDepth value = temperatureAdjustedValue(depth) - valueList += [ value ] + valueList += [value] i = selectListPosition(valueList) - relation = objectList[ i ] - coderack.proposeRule(slipnet.letterCategory,descriptor,slipnet.letter,relation,codelet) + relation = objectList[i] + coderack.proposeRule(slipnet.letterCategory, descriptor, slipnet.letter, relation, codelet) + def rule_strength_tester(codelet): rule = codelet.arguments[0] rule.updateStrength() probability = temperatureAdjustedProbability(rule.totalStrength / 100.0) assert utils.random() <= probability - coderack.newCodelet('rule-builder',codelet,rule.totalStrength,rule) + coderack.newCodelet('rule-builder', codelet, rule.totalStrength, rule) + def replacement_finder(): # 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 = utils.choice(letters) logging.info('selected letter in initial string = %s' % letterOfInitialString) if letterOfInitialString.replacement: logging.info("Replacement already found for %s, so fizzling" % letterOfInitialString) return position = letterOfInitialString.leftStringPosition - moreLetters = [ o for o in workspace.modified.objects if isinstance(o,Letter) and o.leftStringPosition == position ] + moreLetters = [o for o in workspace.modified.objects if isinstance(o, Letter) and o.leftStringPosition == position] letterOfModifiedString = moreLetters and moreLetters[0] or None assert letterOfModifiedString position -= 1 @@ -254,27 +272,28 @@ def replacement_finder(): modifiedAscii = ord(workspace.modifiedString[position]) diff = initialAscii - modifiedAscii if abs(diff) < 2: - relations = { 0:slipnet.sameness, -1:slipnet.successor, 1:slipnet.predecessor } + relations = {0: slipnet.sameness, -1: slipnet.successor, 1: slipnet.predecessor} relation = relations[diff] logging.info('Relation found: %s' % relation.name) else: relation = None logging.info('no relation found') - letterOfInitialString.replacement = Replacement(letterOfInitialString,letterOfModifiedString,relation) + letterOfInitialString.replacement = Replacement(letterOfInitialString, letterOfModifiedString, relation) if relation != slipnet.sameness: letterOfInitialString.changed = True workspace.changedObject = letterOfInitialString logging.info('building replacement') + def top_down_bond_scout__category(codelet): logging.info('top_down_bond_scout__category') category = codelet.arguments[0] - source = __getScoutSource(category,localBondCategoryRelevance,'bond') + source = __getScoutSource(category, localBondCategoryRelevance, 'bond') destination = chooseNeighbour(source) - logging.info('source: %s, destination: %s' % (source,destination)) + logging.info('source: %s, destination: %s' % (source, destination)) assert destination - bondFacet = __getBondFacet(source,destination) - sourceDescriptor, destinationDescriptor = __getDescriptors(bondFacet,source,destination) + bondFacet = __getBondFacet(source, destination) + sourceDescriptor, destinationDescriptor = __getDescriptors(bondFacet, source, destination) forwardBond = sourceDescriptor.getBondCategory(destinationDescriptor) if forwardBond == slipnet.identity: forwardBond = slipnet.sameness @@ -283,37 +302,40 @@ def top_down_bond_scout__category(codelet): backwardBond = destinationDescriptor.getBondCategory(sourceDescriptor) assert category == forwardBond or category == backwardBond if category == forwardBond: - coderack.proposeBond(source,destination,category,bondFacet,sourceDescriptor, destinationDescriptor,codelet) + coderack.proposeBond(source, destination, category, bondFacet, sourceDescriptor, destinationDescriptor, codelet) else: - coderack.proposeBond(destination,source,category,bondFacet,destinationDescriptor,sourceDescriptor,codelet) + coderack.proposeBond(destination, source, category, bondFacet, destinationDescriptor, sourceDescriptor, codelet) + def top_down_bond_scout__direction(codelet): direction = codelet.arguments[0] - source = __getScoutSource(direction,localDirectionCategoryRelevance,'bond') - destination = chooseDirectedNeighbor(source,direction) + source = __getScoutSource(direction, localDirectionCategoryRelevance, 'bond') + destination = chooseDirectedNeighbor(source, direction) assert destination logging.info('to object: %s' % destination) - bondFacet = __getBondFacet(source,destination) - sourceDescriptor, destinationDescriptor = __getDescriptors(bondFacet,source,destination) + bondFacet = __getBondFacet(source, destination) + sourceDescriptor, destinationDescriptor = __getDescriptors(bondFacet, source, destination) category = sourceDescriptor.getBondCategory(destinationDescriptor) assert category if category == slipnet.identity: category = slipnet.sameness - coderack.proposeBond(source,destination,category,bondFacet,sourceDescriptor, destinationDescriptor,codelet) + coderack.proposeBond(source, destination, category, bondFacet, sourceDescriptor, destinationDescriptor, codelet) + def bond_strength_tester(codelet): bond = codelet.arguments[0] __showWhichStringObjectIsFrom(bond) bond.updateStrength() strength = bond.totalStrength - probability = temperatureAdjustedProbability(strength/100.0) - logging.info('bond strength = %d for %s' % (strength,bond)) + probability = temperatureAdjustedProbability(strength / 100.0) + logging.info('bond strength = %d for %s' % (strength, bond)) assert formulas.coinFlip(probability) bond.facet.buffer = 100.0 bond.sourceDescriptor.buffer = 100.0 bond.destinationDescriptor.buffer = 100.0 logging.info("succeeded: posting bond-builder") - coderack.newCodelet('bond-builder',codelet,strength) + coderack.newCodelet('bond-builder', codelet, strength) + def bond_builder(codelet): bond = codelet.arguments[0] @@ -331,9 +353,9 @@ def bond_builder(codelet): logging.info('number of incompatibleBonds: %d' % len(incompatibleBonds)) if len(incompatibleBonds): logging.info('%s' % incompatibleBonds[0]) - assert __fightIncompatibles(incompatibleBonds,bond,'bonds',1.0,1.0) + assert __fightIncompatibles(incompatibleBonds, bond, 'bonds', 1.0, 1.0) incompatibleGroups = bond.source.getCommonGroups(bond.destination) - assert __fightIncompatibles(incompatibleGroups,bond,'groups',1.0,1.0) + assert __fightIncompatibles(incompatibleGroups, bond, 'groups', 1.0, 1.0) # fight all incompatible correspondences incompatibleCorrespondences = [] if bond.leftObject.leftmost or bond.rightObject.rightmost: @@ -341,7 +363,7 @@ def bond_builder(codelet): incompatibleCorrespondences = bond.getIncompatibleCorrespondences() if incompatibleCorrespondences: logging.info("trying to break incompatible correspondences") - assert __fightItOut(bond,2.0,incompatibleCorrespondences,3.0) + assert __fightItOut(bond, 2.0, incompatibleCorrespondences, 3.0) #assert __fightIncompatibles(incompatibleCorrespondences,bond,'correspondences',2.0,3.0) for incompatible in incompatibleBonds: incompatible.break_the_structure() @@ -352,19 +374,20 @@ def bond_builder(codelet): logging.info('building bond %s' % bond) bond.buildBond() + def top_down_group_scout__category(codelet): groupCategory = codelet.arguments[0] category = groupCategory.getRelatedNode(slipnet.bondCategory) assert category - source = __getScoutSource(category,localBondCategoryRelevance,'group') + source = __getScoutSource(category, localBondCategoryRelevance, 'group') assert source and not source.spansString() if source.leftmost: direction = slipnet.right elif source.rightmost: direction = slipnet.left else: - activations = [ slipnet.left.activation ] - activations += [ slipnet.right.activation ] + activations = [slipnet.left.activation] + activations += [slipnet.right.activation] if not selectListPosition(activations): direction = slipnet.left else: @@ -380,11 +403,11 @@ def top_down_group_scout__category(codelet): else: firstBond = source.rightBond if not firstBond or firstBond.category != category: - if category == slipnet.sameness and isinstance(source,Letter): - group = Group(source.string,slipnet.samenessGroup, None,slipnet.letterCategory, [ source ], []) + if category == slipnet.sameness and isinstance(source, Letter): + group = Group(source.string, slipnet.samenessGroup, None, slipnet.letterCategory, [source], []) probability = group.singleLetterGroupProbability() assert utils.random() >= probability - coderack.proposeSingleLetterGroup( source, codelet) + coderack.proposeSingleLetterGroup(source, codelet) return direction = firstBond.directionCategory search = True @@ -414,26 +437,27 @@ def top_down_group_scout__category(codelet): destination = destination.rightBond.rightObject search = True assert destination != source - objects = [ source ] + objects = [source] bonds = [] while source != destination: - bonds += [ source.rightBond ] - objects += [ source.rightBond.rightObject ] + bonds += [source.rightBond] + objects += [source.rightBond.rightObject] source = source.rightBond.rightObject - coderack.proposeGroup(objects,bonds,groupCategory,direction,bondFacet,codelet) + coderack.proposeGroup(objects, bonds, groupCategory, direction, bondFacet, codelet) + def top_down_group_scout__direction(codelet): direction = codelet.arguments[0] - source = __getScoutSource(direction,localDirectionCategoryRelevance,'direction') + source = __getScoutSource(direction, localDirectionCategoryRelevance, 'direction') logging.info('source chosen = %s' % source) assert not source.spansString() - if source.leftmost : + if source.leftmost: mydirection = slipnet.right elif source.rightmost: mydirection = slipnet.left else: - activations = [ slipnet.left.activation ] - activations += [ slipnet.right.activation ] + activations = [slipnet.left.activation] + activations += [slipnet.right.activation] if not selectListPosition(activations): mydirection = slipnet.left else: @@ -464,7 +488,7 @@ def top_down_group_scout__direction(codelet): category = firstBond.category assert category groupCategory = category.getRelatedNode(slipnet.groupCategory) - logging.info('trying from %s to %s' % (source,category.name) ) + logging.info('trying from %s to %s' % (source, category.name)) bondFacet = None # find leftmost object in group with these bonds search = True @@ -491,23 +515,24 @@ def top_down_group_scout__direction(codelet): destination = destination.rightBond.rightObject search = True assert destination != source - logging.info('proposing group from %s to %s' % (source,destination) ) - objects = [ source ] + logging.info('proposing group from %s to %s' % (source, destination)) + objects = [source] bonds = [] while source != destination: - bonds += [ source.rightBond ] - objects += [ source.rightBond.rightObject ] + bonds += [source.rightBond] + objects += [source.rightBond.rightObject] source = source.rightBond.rightObject - coderack.proposeGroup(objects,bonds,groupCategory,direction,bondFacet,codelet) + coderack.proposeGroup(objects, bonds, groupCategory, direction, bondFacet, codelet) + #noinspection PyStringFormat def group_scout__whole_string(codelet): string = workspace.initial if utils.random() > 0.5: string = workspace.target - logging.info('target string selected: %s' % workspace.target ) + logging.info('target string selected: %s' % workspace.target) else: - logging.info('initial string selected: %s' % workspace.initial ) + logging.info('initial string selected: %s' % workspace.initial) # find leftmost object & the highest group to which it belongs leftmost = None for objekt in string.objects: @@ -518,14 +543,14 @@ def group_scout__whole_string(codelet): if leftmost.spansString(): # the object already spans the string - propose this object group = leftmost - coderack.proposeGroup(group.objectList, group.bondList,group.groupCategory,group.directionCategory, group.facet,codelet) + coderack.proposeGroup(group.objectList, group.bondList, group.groupCategory, group.directionCategory, group.facet, codelet) return bonds = [] - objects = [ leftmost ] + objects = [leftmost] while leftmost.rightBond: - bonds += [ leftmost.rightBond ] + bonds += [leftmost.rightBond] leftmost = leftmost.rightBond.rightObject - objects += [ leftmost ] + objects += [leftmost] assert leftmost.rightmost # choose a random bond from list chosenBond = utils.choice(bonds) @@ -535,7 +560,8 @@ def group_scout__whole_string(codelet): bonds = possibleGroupBonds(category, directionCategory, bondFacet, bonds) assert bonds groupCategory = category.getRelatedNode(slipnet.groupCategory) - coderack.proposeGroup(objects,bonds,groupCategory,directionCategory,bondFacet,codelet) + coderack.proposeGroup(objects, bonds, groupCategory, directionCategory, bondFacet, codelet) + def group_strength_tester(codelet): # update strength value of the group @@ -543,13 +569,14 @@ def group_strength_tester(codelet): __showWhichStringObjectIsFrom(group) group.updateStrength() strength = group.totalStrength - probability = temperatureAdjustedProbability(strength/100.0) + probability = temperatureAdjustedProbability(strength / 100.0) assert utils.random() <= probability # it is strong enough - post builder & activate nodes group.groupCategory.getRelatedNode(slipnet.bondCategory).buffer = 100.0 if group.directionCategory: - group.directionCategory.buffer=100.0 - coderack.newCodelet('group-builder',codelet,strength) + group.directionCategory.buffer = 100.0 + coderack.newCodelet('group-builder', codelet, strength) + def group_builder(codelet): # update strength value of the group @@ -557,7 +584,7 @@ def group_builder(codelet): #print '%s' % group __showWhichStringObjectIsFrom(group) equivalent = group.string.equivalentGroup(group) - if equivalent : + if equivalent: logging.info('already exists...activate descriptors & fizzle') group.activateDescriptions() equivalent.addDescriptions(group.descriptions) @@ -575,7 +602,7 @@ def group_builder(codelet): if leftBond: lefty = leftBond.leftObject if lefty != previous or leftBond.directionCategory != group.directionCategory: - incompatibleBonds += [ leftBond ] + incompatibleBonds += [leftBond] previous = objekt next = group.objectList[-1] for objekt in reversed(group.objectList[:-1]): @@ -583,20 +610,20 @@ def group_builder(codelet): if rightBond: righty = rightBond.rightObject if righty != next or rightBond.directionCategory != group.directionCategory: - incompatibleBonds += [ rightBond ] + incompatibleBonds += [rightBond] next = objekt # if incompatible bonds exist - fight group.updateStrength() - assert __fightIncompatibles(incompatibleBonds,group,'bonds',1.0,1.0) + assert __fightIncompatibles(incompatibleBonds, group, 'bonds', 1.0, 1.0) # fight incompatible groups # fight all groups containing these objects incompatibleGroups = group.getIncompatibleGroups() - assert __fightIncompatibles(incompatibleGroups,group,'Groups',1.0,1.0) + assert __fightIncompatibles(incompatibleGroups, group, 'Groups', 1.0, 1.0) for incompatible in incompatibleBonds: incompatible.break_the_structure() # create new bonds group.bondList = [] - for i in range(1,len(group.objectList)): + for i in range(1, len(group.objectList)): #print 803 object1 = group.objectList[i - 1] object2 = group.objectList[i] @@ -609,15 +636,16 @@ def group_builder(codelet): destination = object1 category = group.groupCategory.getRelatedNode(slipnet.bondCategory) facet = group.facet - newBond = Bond(source,destination,category,facet,source.getDescriptor(facet),destination.getDescriptor(facet)) + newBond = Bond(source, destination, category, facet, source.getDescriptor(facet), destination.getDescriptor(facet)) newBond.buildBond() - group.bondList += [ object1.rightBond ] + group.bondList += [object1.rightBond] for incompatible in incompatibleGroups: incompatible.break_the_structure() group.buildGroup() group.activateDescriptions() logging.info('building group') + def rule_builder(codelet): rule = codelet.arguments[0] if rule.ruleEqual(workspace.rule): @@ -627,28 +655,30 @@ def rule_builder(codelet): assert rule.totalStrength # fight against other rules if workspace.rule: - assert __structureVsStructure(rule,1.0,workspace.rule,1.0) + assert __structureVsStructure(rule, 1.0, workspace.rule, 1.0) workspace.buildRule(rule) + def __getCutOff(density): if density > 0.8: - distribution = [ 5.0,150.0,5.0,2.0,1.0,1.0,1.0,1.0,1.0,1.0 ] + distribution = [5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] elif density > 0.6: - distribution = [ 2.0,5.0,150.0,5.0,2.0,1.0,1.0,1.0,1.0,1.0 ] + distribution = [2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0] elif density > 0.4: - distribution = [ 1.0,2.0,5.0,150.0,5.0,2.0,1.0,1.0,1.0,1.0 ] + distribution = [1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0] elif density > 0.2: - distribution = [ 1.0,1.0,2.0,5.0,150.0,5.0,2.0,1.0,1.0,1.0 ] + distribution = [1.0, 1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0] else: - distribution = [ 1.0,1.0,1.0,2.0,5.0,150.0,5.0,2.0,1.0,1.0 ] + distribution = [1.0, 1.0, 1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0] stop = sum(distribution) * utils.random() total = 0.0 - for i in range(0,len(distribution)): + for i in range(0, len(distribution)): total += distribution[i] if total >= stop: return i + 1 return len(distribution) + def rule_translator(): assert workspace.rule if len(workspace.initial) == 1 and len(workspace.target) == 1: @@ -657,7 +687,7 @@ def rule_translator(): numberOfBonds = len(workspace.initial.bonds) + len(workspace.target.bonds) nearlyTotalLength = len(workspace.initial) + len(workspace.target) - 2 bondDensity = numberOfBonds / nearlyTotalLength - if bondDensity>1.0: + if bondDensity > 1.0: bondDensity = 1.0 cutoff = __getCutOff(bondDensity) * 10.0 assert cutoff >= formulas.actualTemperature @@ -668,31 +698,33 @@ def rule_translator(): temperature.clamped = True formulas.Temperature = 100.0 + def bottom_up_correspondence_scout(codelet): - objectFromInitial = chooseUnmodifiedObject('interStringSalience',workspace.initial.objects) - objectFromTarget = chooseUnmodifiedObject('interStringSalience',workspace.target.objects) + objectFromInitial = chooseUnmodifiedObject('interStringSalience', workspace.initial.objects) + objectFromTarget = chooseUnmodifiedObject('interStringSalience', workspace.target.objects) assert objectFromInitial.spansString() == objectFromTarget.spansString() # get the posible concept mappings - conceptMappings = getMappings( objectFromInitial, objectFromTarget, objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) + conceptMappings = getMappings(objectFromInitial, objectFromTarget, objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) assert conceptMappings and __slippability(conceptMappings) #find out if any are distinguishing - distinguishingMappings = [ m for m in conceptMappings if m.distinguishing() ] + distinguishingMappings = [m for m in conceptMappings if m.distinguishing()] assert distinguishingMappings # if both objects span the strings, check to see if the # string description needs to be flipped - oppositeMappings = [ m for m in distinguishingMappings + oppositeMappings = [m for m in distinguishingMappings if m.initialDescriptionType == slipnet.stringPositionCategory and - m.initialDescriptionType != slipnet.bondFacet ] - initialDescriptionTypes = [ m.initialDescriptionType for m in oppositeMappings ] + m.initialDescriptionType != slipnet.bondFacet] + initialDescriptionTypes = [m.initialDescriptionType for m in oppositeMappings] flipTargetObject = False if objectFromInitial.spansString() and objectFromTarget.spansString() and slipnet.directionCategory in initialDescriptionTypes and __allOppositeMappings(oppositeMappings) and slipnet.opposite.activation != 100.0: objectFromTarget = objectFromTarget.flippedVersion() - conceptMappings = getMappings( objectFromInitial, objectFromTarget, objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) + conceptMappings = getMappings(objectFromInitial, objectFromTarget, objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) flipTargetObject = True - coderack.proposeCorrespondence(objectFromInitial,objectFromTarget,conceptMappings,flipTargetObject,codelet) + coderack.proposeCorrespondence(objectFromInitial, objectFromTarget, conceptMappings, flipTargetObject, codelet) + def important_object_correspondence_scout(codelet): - objectFromInitial = chooseUnmodifiedObject('relativeImportance',workspace.initial.objects) + objectFromInitial = chooseUnmodifiedObject('relativeImportance', workspace.initial.objects) descriptors = objectFromInitial.relevantDistinguishingDescriptors() slipnode = chooseSlipnodeByConceptualDepth(descriptors) assert slipnode @@ -704,26 +736,27 @@ def important_object_correspondence_scout(codelet): for objekt in workspace.target.objects: for description in objekt.relevantDescriptions(): if description.descriptor == initialDescriptor: - targetCandidates += [ objekt ] + targetCandidates += [objekt] assert targetCandidates - objectFromTarget = chooseUnmodifiedObject('interStringSalience',targetCandidates) + objectFromTarget = chooseUnmodifiedObject('interStringSalience', targetCandidates) assert objectFromInitial.spansString() == objectFromTarget.spansString() # get the posible concept mappings - conceptMappings = getMappings( objectFromInitial, objectFromTarget, objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) + conceptMappings = getMappings(objectFromInitial, objectFromTarget, objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) assert conceptMappings and __slippability(conceptMappings) #find out if any are distinguishing - distinguishingMappings = [ m for m in conceptMappings if m.distinguishing() ] + distinguishingMappings = [m for m in conceptMappings if m.distinguishing()] assert distinguishingMappings # if both objects span the strings, check to see if the # string description needs to be flipped - oppositeMappings = [ m for m in distinguishingMappings if m.initialDescriptionType == slipnet.stringPositionCategory and m.initialDescriptionType != slipnet.bondFacet ] - initialDescriptionTypes = [ m.initialDescriptionType for m in oppositeMappings ] + oppositeMappings = [m for m in distinguishingMappings if m.initialDescriptionType == slipnet.stringPositionCategory and m.initialDescriptionType != slipnet.bondFacet] + initialDescriptionTypes = [m.initialDescriptionType for m in oppositeMappings] flipTargetObject = False if objectFromInitial.spansString() and objectFromTarget.spansString() and slipnet.directionCategory in initialDescriptionTypes and __allOppositeMappings(oppositeMappings) and slipnet.opposite.activation != 100.0: objectFromTarget = objectFromTarget.flippedVersion() - conceptMappings = getMappings( objectFromInitial, objectFromTarget,objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) + conceptMappings = getMappings(objectFromInitial, objectFromTarget, objectFromInitial.relevantDescriptions(), objectFromTarget.relevantDescriptions()) flipTargetObject = True - coderack.proposeCorrespondence(objectFromInitial,objectFromTarget,conceptMappings,flipTargetObject,codelet) + coderack.proposeCorrespondence(objectFromInitial, objectFromTarget, conceptMappings, flipTargetObject, codelet) + def correspondence_strength_tester(codelet): correspondence = codelet.arguments[0] @@ -732,7 +765,7 @@ def correspondence_strength_tester(codelet): assert objectFromInitial in workspace.objects and (objectFromTarget in workspace.objects or correspondence.flipTargetObject and not workspace.target.equivalentGroup(objectFromTarget.flipped_version())) correspondence.updateStrength() strength = correspondence.totalStrength - probability = temperatureAdjustedProbability(strength/100.0) + probability = temperatureAdjustedProbability(strength / 100.0) assert utils.random() <= probability # activate some concepts for mapping in correspondence.conceptMappings: @@ -740,7 +773,8 @@ def correspondence_strength_tester(codelet): mapping.initialDescriptor.buffer = 100.0 mapping.targetDescriptionType.buffer = 100.0 mapping.targetDescriptor.buffer = 100.0 - coderack.newCodelet('correspondence-builder',codelet,strength,correspondence) + coderack.newCodelet('correspondence-builder', codelet, strength, correspondence) + def correspondence_builder(codelet): correspondence = codelet.arguments[0] @@ -763,7 +797,7 @@ def correspondence_builder(codelet): if mapping.label: mapping.label.buffer = 100.0 if not mapping.isContainedBy(existing.conceptMappings): - existing.conceptMappings += [ mapping ] + existing.conceptMappings += [mapping] return incompatibleCorrespondences = correspondence.getIncompatibleCorrespondences() # fight against all correspondences @@ -771,7 +805,7 @@ def correspondence_builder(codelet): correspondenceSpans = correspondence.objectFromInitial.letterSpan() + correspondence.objectFromTarget.letterSpan() for incompatible in incompatibleCorrespondences: incompatibleSpans = incompatible.objectFromInitial.letterSpan() + incompatible.objectFromTarget.letterSpan() - assert __structureVsStructure(correspondence,correspondenceSpans,incompatible,incompatibleSpans) + assert __structureVsStructure(correspondence, correspondenceSpans, incompatible, incompatibleSpans) incompatibleBond = None incompatibleGroup = None # if there is an incompatible bond then fight against it @@ -780,16 +814,16 @@ def correspondence_builder(codelet): incompatibleBond = correspondence.getIncompatibleBond() if incompatibleBond: # bond found - fight against it - assert __structureVsStructure(correspondence,3.0,incompatibleBond,2.0) + assert __structureVsStructure(correspondence, 3.0, incompatibleBond, 2.0) # won against incompatible bond incompatibleGroup = correspondence.objectFromTarget.group if incompatibleGroup: - assert __structureVsStructure(correspondence,1.0,incompatibleGroup,1.0) + assert __structureVsStructure(correspondence, 1.0, incompatibleGroup, 1.0) # if there is an incompatible rule, fight against it incompatibleRule = None if workspace.rule and workspace.rule.incompatibleRuleCorrespondence(correspondence): incompatibleRule = workspace.rule - assert __structureVsStructure( correspondence,1.0,incompatibleRule,1.0) + assert __structureVsStructure(correspondence, 1.0, incompatibleRule, 1.0) for incompatible in incompatibleCorrespondences: incompatible.break_the_structure() # break incompatible group and bond if they exist diff --git a/copycat/coderack.py b/copycat/coderack.py index f5e1c01..c0b7fcf 100644 --- a/copycat/coderack.py +++ b/copycat/coderack.py @@ -1,4 +1,7 @@ -import re, inspect, math, logging +import re +import inspect +import math +import logging import utils import formulas @@ -12,6 +15,7 @@ MAX_NUMBER_OF_CODELETS = 100 codeletsUsed = {} + class CodeRack(object): def __init__(self): #logging.debug('coderack.__init__()') @@ -21,7 +25,7 @@ class CodeRack(object): self.pressures = CoderackPressures() self.pressures.initialisePressures() self.reset() - self.initialCodeletNames = ( 'bottom-up-bond-scout', 'replacement-finder', 'bottom-up-correspondence-scout' ) + self.initialCodeletNames = ('bottom-up-bond-scout', 'replacement-finder', 'bottom-up-correspondence-scout') self.codeletMethodsDir = None self.runCodelets = {} self.postings = {} @@ -166,7 +170,7 @@ class CodeRack(object): def proposeSingleLetterGroup(self, source, codelet): self.proposeGroup([source], [], slipnet.samenessGroup, None, slipnet.letterCategory, codelet) - def proposeGroup(self, objects, bondList, groupCategory, directionCategory, bondFacet, oldCodelet ): + def proposeGroup(self, objects, bondList, groupCategory, directionCategory, bondFacet, oldCodelet): from group import Group bondCategory = groupCategory.getRelatedNode(slipnet.bondCategory) @@ -177,7 +181,7 @@ class CodeRack(object): urgency = bondCategory.bondDegreeOfAssociation() self.newCodelet('group-strength-tester', oldCodelet, urgency, group) - def proposeBond(self, source, destination, bondCategory, bondFacet, sourceDescriptor, destinationDescriptor, oldCodelet ): + def proposeBond(self, source, destination, bondCategory, bondFacet, sourceDescriptor, destinationDescriptor, oldCodelet): from bond import Bond bondFacet.buffer = 100.0 @@ -255,7 +259,7 @@ class CodeRack(object): for codeletName in knownCodeletNames: methodName = re.sub('[ -]', '_', codeletName) if methodName not in self.codeletMethodsDir: - raise NotImplementedError, 'Cannot find %s in codeletMethods' % methodName + raise NotImplementedError('Cannot find %s in codeletMethods' % methodName) method = getattr(codeletMethods, methodName) self.methods[methodName] = method @@ -270,7 +274,7 @@ class CodeRack(object): if not self.codelets: return None temp = formulas.Temperature - scale = ( 100.0 - temp + 10.0 ) / 15.0 + scale = (100.0 - temp + 10.0) / 15.0 # threshold = sum( [ c.urgency ** scale for c in self.codelets ] ) * utils.random() urgsum = 0.0 for codelet in self.codelets: @@ -321,9 +325,9 @@ class CodeRack(object): #if not self.codeletMethodsDir: method = self.methods[methodName] if not method: - raise ValueError, 'Found %s in codeletMethods, but cannot get it' % methodName + raise ValueError('Found %s in codeletMethods, but cannot get it' % methodName) if not callable(method): - raise RuntimeError, 'Cannot call %s()' % methodName + raise RuntimeError('Cannot call %s()' % methodName) args, varargs, varkw, defaults = inspect.getargspec(method) #global codeletsUsed #codeletsUsed[methodName] = codeletsUsed.get(methodName,0) + 1 diff --git a/copycat/coderackPressure.py b/copycat/coderackPressure.py index ed85da1..042cbc7 100644 --- a/copycat/coderackPressure.py +++ b/copycat/coderackPressure.py @@ -2,6 +2,7 @@ import logging from formulas import Temperature from slipnet import slipnet + class CoderackPressure(object): def __init__(self, name): self.name = name @@ -11,6 +12,7 @@ class CoderackPressure(object): self.values = [] self.codelets = [] + class CoderackPressures(object): def __init__(self): #logging.debug('coderackPressures.__init__()') @@ -41,7 +43,7 @@ class CoderackPressures(object): def calculatePressures(self): #logging.debug('coderackPressures.calculatePressures()') - scale = ( 100.0 - Temperature + 10.0 ) / 15.0 + scale = (100.0 - Temperature + 10.0) / 15.0 values = [] for pressure in self.pressures: value = sum([c.urgency ** scale for c in pressure.codelets]) @@ -117,7 +119,7 @@ class CoderackPressures(object): if i >= 0: self.pressures[i].codelets += [codelet] if codelet.pressure: - codelet.pressure.codelets += [codelet] # XXX why do this + codelet.pressure.codelets += [codelet] # XXX why do this if i >= 0: codelet.pressure = self.pressures[i] # when following with this ? logging.info('Add %s: %d' % (codelet.name, i)) diff --git a/copycat/conceptMapping.py b/copycat/conceptMapping.py index acbda95..5699582 100644 --- a/copycat/conceptMapping.py +++ b/copycat/conceptMapping.py @@ -1,6 +1,7 @@ import logging from slipnet import slipnet + class ConceptMapping(object): def __init__(self, initialDescriptionType, targetDescriptionType, initialDescriptor, targetDescriptor, initialObject, targetObject): logging.info('make a map: %s-%s' % (initialDescriptionType.get_name(), targetDescriptionType.get_name())) @@ -23,7 +24,7 @@ class ConceptMapping(object): if association == 100.0: return 100.0 depth = self.__conceptualDepth() / 100.0 - return association * ( 1 - depth * depth ) + return association * (1 - depth * depth) def __degreeOfAssociation(self): #assumes the 2 descriptors are connected in the slipnet by at most 1 link @@ -39,10 +40,10 @@ class ConceptMapping(object): if association == 100.0: return 100.0 depth = self.__conceptualDepth() / 100.0 - return association * ( 1 + depth * depth ) + return association * (1 + depth * depth) def __conceptualDepth(self): - return (self.initialDescriptor.conceptualDepth + self.targetDescriptor.conceptualDepth ) / 2.0 + return (self.initialDescriptor.conceptualDepth + self.targetDescriptor.conceptualDepth) / 2.0 def distinguishing(self): if self.initialDescriptor == slipnet.whole and self.targetDescriptor == slipnet.whole: diff --git a/copycat/copycat.py b/copycat/copycat.py index ff75ea4..3e92ea4 100644 --- a/copycat/copycat.py +++ b/copycat/copycat.py @@ -15,6 +15,7 @@ from temperature import temperature from coderack import coderack from coderackPressure import coderackPressures + def updateEverything(): workspace.updateEverything() coderack.updateCodelets() @@ -53,6 +54,7 @@ def runTrial(): for answer, count in answers.iteritems(): print '%s:%d' % (answer, count) + def run(initial, modified, target): workspace.setStrings(initial, modified, target) runTrial() diff --git a/copycat/correspondence.py b/copycat/correspondence.py index 3e7d0d7..931cda7 100644 --- a/copycat/correspondence.py +++ b/copycat/correspondence.py @@ -2,8 +2,9 @@ from workspace import workspace from workspaceStructure import WorkspaceStructure from formulas import getMappings + class Correspondence(WorkspaceStructure): - def __init__(self,objectFromInitial,objectFromTarget,conceptMappings,flipTargetObject): + def __init__(self, objectFromInitial, objectFromTarget, conceptMappings, flipTargetObject): WorkspaceStructure.__init__(self) self.objectFromInitial = objectFromInitial self.objectFromTarget = objectFromTarget @@ -15,13 +16,13 @@ class Correspondence(WorkspaceStructure): return '<%s>' % self.__str__() def __str__(self): - return 'Correspondence between %s and %s' % (self.objectFromInitial,self.objectFromTarget) + return 'Correspondence between %s and %s' % (self.objectFromInitial, self.objectFromTarget) def distinguishingConceptMappings(self): - return [ m for m in self.conceptMappings if m.distinguishing() ] + return [m for m in self.conceptMappings if m.distinguishing()] def relevantDistinguishingConceptMappings(self): - return [ m for m in self.conceptMappings if m.distinguishing() and m.relevant() ] + return [m for m in self.conceptMappings if m.distinguishing() and m.relevant()] def extract_target_bond(self): targetBond = False @@ -63,9 +64,9 @@ class Correspondence(WorkspaceStructure): return None def getIncompatibleCorrespondences(self): - return [ o.correspondence for o in workspace.initial.objects if o and self.incompatible(o.correspondence) ] + return [o.correspondence for o in workspace.initial.objects if o and self.incompatible(o.correspondence)] - def incompatible(self,other): + def incompatible(self, other): if not other: return False if self.objectFromInitial == other.objectFromInitial: @@ -78,7 +79,7 @@ class Correspondence(WorkspaceStructure): return True return False - def supporting(self,other): + def supporting(self, other): if self == other: return False if self.objectFromInitial == other.objectFromInitial: @@ -95,12 +96,12 @@ class Correspondence(WorkspaceStructure): def support(self): from letter import Letter - if isinstance(self.objectFromInitial,Letter) and self.objectFromInitial.spansString(): + if isinstance(self.objectFromInitial, Letter) and self.objectFromInitial.spansString(): return 100.0 - if isinstance(self.objectFromTarget,Letter) and self.objectFromTarget.spansString(): + if isinstance(self.objectFromTarget, Letter) and self.objectFromTarget.spansString(): return 100.0 - total = sum([ c.totalStrength for c in workspace.correspondences() if self.supporting(c) ]) - total = min(total,100.0) + total = sum([c.totalStrength for c in workspace.correspondences() if self.supporting(c)]) + total = min(total, 100.0) return total def updateInternalStrength(self): @@ -110,7 +111,7 @@ class Correspondence(WorkspaceStructure): if numberOfConceptMappings < 1: self.internalStrength = 0.0 return - totalStrength = sum([ m.strength() for m in relevantDistinguishingMappings ]) + totalStrength = sum([m.strength() for m in relevantDistinguishingMappings]) averageStrength = totalStrength / numberOfConceptMappings if numberOfConceptMappings == 1.0: numberOfConceptMappingsFactor = 0.8 @@ -123,7 +124,7 @@ class Correspondence(WorkspaceStructure): else: internalCoherenceFactor = 1.0 internalStrength = averageStrength * internalCoherenceFactor * numberOfConceptMappingsFactor - self.internalStrength = min(internalStrength,100.0) + self.internalStrength = min(internalStrength, 100.0) def updateExternalStrength(self): self.externalStrength = self.support() @@ -131,16 +132,16 @@ class Correspondence(WorkspaceStructure): def internallyCoherent(self): """Whether any pair of relevant distinguishing mappings support each other""" mappings = self.relevantDistinguishingConceptMappings() - for i in range(0,len(mappings)): - for j in range(0,len(mappings)): + for i in range(0, len(mappings)): + for j in range(0, len(mappings)): if i != j: if mappings[i].supports(mappings[j]): return True return False def slippages(self): - mappings = [ m for m in self.conceptMappings if m.slippage() ] - mappings += [ m for m in self.accessoryConceptMappings if m.slippage() ] + mappings = [m for m in self.conceptMappings if m.slippage()] + mappings += [m for m in self.accessoryConceptMappings if m.slippage()] return mappings def reflexive(self): @@ -151,7 +152,7 @@ class Correspondence(WorkspaceStructure): return False def buildCorrespondence(self): - workspace.structures += [ self ] + workspace.structures += [self] if self.objectFromInitial.correspondence: self.objectFromInitial.correspondence.breakCorrespondence() if self.objectFromTarget.correspondence: @@ -162,9 +163,9 @@ class Correspondence(WorkspaceStructure): relevantMappings = self.relevantDistinguishingConceptMappings() for mapping in relevantMappings: if mapping.slippage(): - self.accessoryConceptMappings += [ mapping.symmetricVersion() ] + self.accessoryConceptMappings += [mapping.symmetricVersion()] from group import Group - if isinstance(self.objectFromInitial,Group) and isinstance(self.objectFromTarget,Group): + if isinstance(self.objectFromInitial, Group) and isinstance(self.objectFromTarget, Group): bondMappings = getMappings( self.objectFromInitial, self.objectFromTarget, @@ -172,9 +173,9 @@ class Correspondence(WorkspaceStructure): self.objectFromTarget.bondDescriptions ) for mapping in bondMappings: - self.accessoryConceptMappings += [ mapping ] + self.accessoryConceptMappings += [mapping] if mapping.slippage(): - self.accessoryConceptMappings += [ mapping.symmetricVersion() ] + self.accessoryConceptMappings += [mapping.symmetricVersion()] for mapping in self.conceptMappings: if mapping.label: mapping.label.activation = 100.0 @@ -186,4 +187,3 @@ class Correspondence(WorkspaceStructure): workspace.structures.remove(self) self.objectFromInitial.correspondence = None self.objectFromTarget.correspondence = None - diff --git a/copycat/description.py b/copycat/description.py index 879d0c1..5d9ef40 100644 --- a/copycat/description.py +++ b/copycat/description.py @@ -1,8 +1,9 @@ import logging from workspaceStructure import WorkspaceStructure + class Description(WorkspaceStructure): - def __init__(self,workspaceObject,descriptionType,descriptor): + def __init__(self, workspaceObject, descriptionType, descriptor): WorkspaceStructure.__init__(self) self.object = workspaceObject self.string = workspaceObject.string @@ -13,7 +14,7 @@ class Description(WorkspaceStructure): return '' % self.__str__() def __str__(self): - s = 'description(%s) of %s' % (self.descriptor.get_name(),self.object) + s = 'description(%s) of %s' % (self.descriptor.get_name(), self.object) from workspace import workspace if self.object.string == workspace.initial: s += ' in initial string' @@ -29,13 +30,13 @@ class Description(WorkspaceStructure): def localSupport(self): from workspace import workspace - supporters = 0 # number of objects in the string with a descriptionType like self + supporters = 0 # number of objects in the string with a descriptionType like self for other in workspace.otherObjects(self.object): - if not ( self.object.isWithin(other) or other.isWithin(self.object) ): + if not (self.object.isWithin(other) or other.isWithin(self.object)): for description in other.descriptions: if description.descriptionType == self.descriptionType: supporters += 1 - results = { 0:0.0, 1:20.0, 2:60.0, 3:90.0 } + results = {0: 0.0, 1: 20.0, 2: 60.0, 3: 90.0} if supporters in results: return results[supporters] return 100.0 @@ -45,12 +46,10 @@ class Description(WorkspaceStructure): self.descriptor.buffer = 100.0 if not self.object.hasDescription(self.descriptor): logging.info('Add %s to descriptions' % self) - self.object.descriptions += [ self ] + self.object.descriptions += [self] def breakDescription(self): from workspace import workspace if self in workspace.structures: workspace.structures.remove(self) self.object.descriptions.remove(self) - - diff --git a/copycat/formulas.py b/copycat/formulas.py index 8fe4789..f05f382 100644 --- a/copycat/formulas.py +++ b/copycat/formulas.py @@ -1,4 +1,4 @@ -import math #, random +import math # , random import logging import utils @@ -7,6 +7,7 @@ from temperature import temperature actualTemperature = Temperature = 100.0 + def selectListPosition(probabilities): total = sum(probabilities) #logging.info('total: %s' % total) @@ -22,20 +23,23 @@ def selectListPosition(probabilities): index += 1 return 0 + def weightedAverage(values): total = 0.0 totalWeights = 0.0 - for value,weight in values: + for value, weight in values: total += value * weight totalWeights += weight if not totalWeights: return 0.0 return total / totalWeights + 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) / 30.0) + 0.5) + def temperatureAdjustedProbability(value): if not value or value == 0.5 or not temperature.value: @@ -46,64 +50,73 @@ def temperatureAdjustedProbability(value): a = math.sqrt(coldness) b = 10.0 - a c = b / 100 - d = c * ( 1.0 - ( 1.0 - value ) ) # aka c * value, but we're following the java - e = ( 1.0 - value ) + d + d = c * (1.0 - (1.0 - value)) # aka c * value, but we're following the java + e = (1.0 - value) + d f = 1.0 - e - return max(f,0.5) + return max(f, 0.5) + def coinFlip(chance=0.5): return utils.random() < chance + def blur(value): root = math.sqrt(value) if coinFlip(): return value + root return value - root -def chooseObjectFromList(objects,attribute): + +def chooseObjectFromList(objects, attribute): if not objects: return None probabilities = [] for object in objects: - value = getattr(object,attribute) + value = getattr(object, attribute) probability = temperatureAdjustedValue(value) - logging.info('Object: %s, value: %d, probability: %d' % (object,value,probability)) - probabilities += [ probability ] + logging.info('Object: %s, value: %d, probability: %d' % (object, value, probability)) + probabilities += [probability] index = selectListPosition(probabilities) logging.info("Selected: %d" % index) return objects[index] + def chooseRelevantDescriptionByActivation(workspaceObject): descriptions = workspaceObject.relevantDescriptions() if not descriptions: return None - activations = [ description.descriptor.activation for description in descriptions ] + activations = [description.descriptor.activation for description in descriptions] index = selectListPosition(activations) - return descriptions[ index ] + return descriptions[index] + def similarPropertyLinks(slip_node): result = [] for slip_link in slip_node.propertyLinks: association = slip_link.degreeOfAssociation() / 100.0 - probability = temperatureAdjustedProbability( association ) + probability = temperatureAdjustedProbability(association) if coinFlip(probability): - result += [ slip_link ] + result += [slip_link] return result + def chooseSlipnodeByConceptualDepth(slip_nodes): if not slip_nodes: return None - depths = [ temperatureAdjustedValue(n.conceptualDepth) for n in slip_nodes ] + depths = [temperatureAdjustedValue(n.conceptualDepth) for n in slip_nodes] i = selectListPosition(depths) - return slip_nodes[ i ] + return slip_nodes[i] -def __relevantCategory(objekt,slipnode): + +def __relevantCategory(objekt, slipnode): return objekt.rightBond and objekt.rightBond.category == slipnode -def __relevantDirection(objekt,slipnode): + +def __relevantDirection(objekt, slipnode): return objekt.rightBond and objekt.rightBond.directionCategory == slipnode -def __localRelevance(string,slipnode,relevance): + +def __localRelevance(string, slipnode, relevance): numberOfObjectsNotSpanning = numberOfMatches = 0.0 #logging.info("find relevance for a string: %s" % string); for objekt in string.objects: @@ -111,22 +124,25 @@ def __localRelevance(string,slipnode,relevance): if not objekt.spansString(): #logging.info('non spanner: %s' % objekt) numberOfObjectsNotSpanning += 1.0 - if relevance(objekt,slipnode): + if relevance(objekt, slipnode): numberOfMatches += 1.0 #logging.info("matches: %d, not spanning: %d" % (numberOfMatches,numberOfObjectsNotSpanning)) if numberOfObjectsNotSpanning == 1: return 100.0 * numberOfMatches return 100.0 * numberOfMatches / (numberOfObjectsNotSpanning - 1.0) + def localBondCategoryRelevance(string, category): if len(string.objects) == 1: return 0.0 - return __localRelevance(string,category,__relevantCategory) + return __localRelevance(string, category, __relevantCategory) + def localDirectionCategoryRelevance(string, direction): - return __localRelevance(string,direction,__relevantDirection) + return __localRelevance(string, direction, __relevantDirection) -def getMappings(objectFromInitial,objectFromTarget, initialDescriptions, targetDescriptions): + +def getMappings(objectFromInitial, objectFromTarget, initialDescriptions, targetDescriptions): mappings = [] from conceptMapping import ConceptMapping for initialDescription in initialDescriptions: @@ -141,6 +157,5 @@ def getMappings(objectFromInitial,objectFromTarget, initialDescriptions, targetD objectFromInitial, objectFromTarget ) - mappings += [ mapping ] + mappings += [mapping] return mappings - diff --git a/copycat/group.py b/copycat/group.py index 98dc071..5d39997 100644 --- a/copycat/group.py +++ b/copycat/group.py @@ -1,13 +1,15 @@ -import utils, logging +import utils +import logging from workspace import workspace from workspaceObject import WorkspaceObject from slipnet import slipnet import formulas + class Group(WorkspaceObject): - def __init__(self,string,groupCategory,directionCategory,facet,objectList,bondList): - WorkspaceObject.__init__(self,string) + def __init__(self, string, groupCategory, directionCategory, facet, objectList, bondList): + WorkspaceObject.__init__(self, string) self.groupCategory = groupCategory self.directionCategory = directionCategory self.facet = facet @@ -36,7 +38,6 @@ class Group(WorkspaceObject): self.clampSalience = False self.name = '' - from description import Description if self.bondList and len(self.bondList): firstFacet = self.bondList[0].facet @@ -71,18 +72,18 @@ class Group(WorkspaceObject): s = self.string.__str__() l = self.leftStringPosition - 1 r = self.rightStringPosition - return 'group[%d:%d] == %s' % ( l, r - 1, s[l: r ]) + return 'group[%d:%d] == %s' % (l, r - 1, s[l:r]) def getIncompatibleGroups(self): result = [] for objekt in self.objectList: while objekt.group: - result += [ objekt.group ] + result += [objekt.group] objekt = objekt.group return result - def addBondDescription(self,description): - self.bondDescriptions += [ description ] + def addBondDescription(self, description): + self.bondDescriptions += [description] def singleLetterGroupProbability(self): numberOfSupporters = self.numberOfLocalSupportingGroups() @@ -100,15 +101,15 @@ class Group(WorkspaceObject): return formulas.temperatureAdjustedProbability(supportedActivation) def flippedVersion(self): - flippedBonds = [ b.flippedversion() for b in self.bondList ] + flippedBonds = [b.flippedversion() for b in self.bondList] flippedGroup = self.groupCategory.getRelatedNode(slipnet.flipped) flippedDirection = self.directionCategory.getRelatedNode(slipnet.flipped) return Group(self.string, flippedGroup, flippedDirection, self.facet, self.objectList, flippedBonds) def buildGroup(self): - workspace.objects += [ self ] - workspace.structures += [ self ] - self.string.objects += [ self ] + workspace.objects += [self] + workspace.structures += [self] + self.string.objects += [self] for objekt in self.objectList: objekt.group = self workspace.buildDescriptions(self) @@ -128,7 +129,7 @@ class Group(WorkspaceObject): probability = 0.5 ** fred value = formulas.temperatureAdjustedProbability(probability) if value < 0.06: - value = 0.0 # otherwise 1/20 chance always + value = 0.0 # otherwise 1/20 chance always return value def break_the_structure(self): @@ -168,7 +169,7 @@ class Group(WorkspaceObject): else: lengthFactor = 90.0 lengthWeight = 100.0 - bondWeight - weightList = ( (relatedBondAssociation, bondWeight), (lengthFactor, lengthWeight) ) + weightList = ((relatedBondAssociation, bondWeight), (lengthFactor, lengthWeight)) self.internalStrength = formulas.weightedAverage(weightList) def updateExternalStrength(self): @@ -181,14 +182,14 @@ class Group(WorkspaceObject): numberOfSupporters = self.numberOfLocalSupportingGroups() if numberOfSupporters == 0.0: return 0.0 - supportFactor = min(1.0,0.6 ** (1 / (numberOfSupporters ** 3 ))) + supportFactor = min(1.0, 0.6 ** (1 / (numberOfSupporters ** 3))) densityFactor = 100.0 * ((self.localDensity() / 100.0) ** 0.5) return densityFactor * supportFactor def numberOfLocalSupportingGroups(self): count = 0 for objekt in self.string.objects: - if isinstance(objekt,Group): + if isinstance(objekt, Group): if objekt.rightStringPosition < self.leftStringPosition or objekt.leftStringPosition > self.rightStringPosition: if objekt.groupCategory == self.groupCategory and objekt.directionCategory == self.directionCategory: count += 1 @@ -199,7 +200,7 @@ class Group(WorkspaceObject): halfLength = len(self.string) / 2.0 return 100.0 * numberOfSupporters / halfLength - def sameGroup(self,other): + def sameGroup(self, other): if self.leftStringPosition != other.leftStringPosition: return False if self.rightStringPosition != other.rightStringPosition: @@ -212,26 +213,24 @@ class Group(WorkspaceObject): return False return True - def morePossibleDescriptions(self,node): + def morePossibleDescriptions(self, node): result = [] i = 1 for number in slipnet.numbers: if node == number and len(self.objects) == i: - result += [ node ] + result += [node] i += 1 return result - def distinguishingDescriptor(self,descriptor): + def distinguishingDescriptor(self, descriptor): """Whether no other object of the same type (group) has the same descriptor""" - if not WorkspaceObject.distinguishingDescriptor(self,descriptor): + if not WorkspaceObject.distinguishingDescriptor(self, descriptor): return False for objekt in self.string.objects: # check to see if they are of the same type - if isinstance(objekt,Group) and objekt != self: + if isinstance(objekt, Group) and objekt != self: # check all descriptions for the descriptor for description in objekt.descriptions: if description.descriptor == descriptor: return False return True - - diff --git a/copycat/grouprun.py b/copycat/grouprun.py index df4e554..2b37fd1 100644 --- a/copycat/grouprun.py +++ b/copycat/grouprun.py @@ -1,5 +1,6 @@ from workspace import workspace + class GroupRun(object): def __init__(self): self.name = 'xxx' diff --git a/copycat/letter.py b/copycat/letter.py index 8dd91e4..a65c1da 100644 --- a/copycat/letter.py +++ b/copycat/letter.py @@ -1,26 +1,27 @@ from workspaceObject import WorkspaceObject from slipnet import slipnet + class Letter(WorkspaceObject): - def __init__(self,string,position,length): - WorkspaceObject.__init__(self,string) + def __init__(self, string, position, length): + WorkspaceObject.__init__(self, string) from workspace import workspace - workspace.objects += [ self ] - string.objects += [self ] + workspace.objects += [self] + string.objects += [self] self.leftStringPosition = position self.leftmost = self.leftStringPosition == 1 self.rightStringPosition = position self.rightmost = self.rightStringPosition == length - def describe(self,position,length): + def describe(self, position, length): if length == 1: - self.addDescription(slipnet.stringPositionCategory,slipnet.single) - if self.leftmost and length > 1: # ? why check length ? - self.addDescription(slipnet.stringPositionCategory,slipnet.leftmost) - if self.rightmost and length > 1: # ? why check length ? - self.addDescription(slipnet.stringPositionCategory,slipnet.rightmost) + self.addDescription(slipnet.stringPositionCategory, slipnet.single) + if self.leftmost and length > 1: # ? why check length ? + self.addDescription(slipnet.stringPositionCategory, slipnet.leftmost) + if self.rightmost and length > 1: # ? why check length ? + self.addDescription(slipnet.stringPositionCategory, slipnet.rightmost) if length > 2 and position * 2 == length + 1: - self.addDescription(slipnet.stringPositionCategory,slipnet.middle) + self.addDescription(slipnet.stringPositionCategory, slipnet.middle) def __repr__(self): return '' % self.__str__() @@ -30,19 +31,18 @@ class Letter(WorkspaceObject): return '' i = self.leftStringPosition - 1 if len(self.string) <= i: - raise ValueError, 'len(self.string) <= self.leftStringPosition :: %d <= %d' % (len(self.string),self.leftStringPosition) - return self.string[ i ] + raise ValueError('len(self.string) <= self.leftStringPosition :: %d <= %d' % (len(self.string), self.leftStringPosition)) + return self.string[i] - def distinguishingDescriptor(self,descriptor): + def distinguishingDescriptor(self, descriptor): """Whether no other object of the same type (letter) has the same descriptor""" - if not WorkspaceObject.distinguishingDescriptor(self,descriptor): + if not WorkspaceObject.distinguishingDescriptor(self, descriptor): return False for objekt in self.string.objects: # check to see if they are of the same type - if isinstance(objekt,Letter) and objekt != self: + if isinstance(objekt, Letter) and objekt != self: # check all descriptions for the descriptor for description in objekt.descriptions: if description.descriptor == descriptor: return False return True - diff --git a/copycat/replacement.py b/copycat/replacement.py index a06ca45..562cac8 100644 --- a/copycat/replacement.py +++ b/copycat/replacement.py @@ -1,9 +1,9 @@ from workspaceStructure import WorkspaceStructure + class Replacement(WorkspaceStructure): def __init__(self, objectFromInitial, objectFromModified, relation): WorkspaceStructure.__init__(self) self.objectFromInitial = objectFromInitial self.objectFromModified = objectFromModified self.relation = relation - diff --git a/copycat/rule.py b/copycat/rule.py index c9ea5c4..6bbbf64 100644 --- a/copycat/rule.py +++ b/copycat/rule.py @@ -3,8 +3,9 @@ from workspace import workspace from workspaceStructure import WorkspaceStructure from formulas import * + class Rule(WorkspaceStructure): - def __init__(self,facet,descriptor,category,relation): + def __init__(self, facet, descriptor, category, relation): WorkspaceStructure.__init__(self) self.facet = facet self.descriptor = descriptor @@ -20,15 +21,15 @@ class Rule(WorkspaceStructure): self.externalStrength = self.internalStrength def updateInternalStrength(self): - if not ( self.descriptor and self.relation ): + if not (self.descriptor and self.relation): self.internalStrength = 0.0 return - averageDepth = ( self.descriptor.conceptualDepth + self.relation.conceptualDepth ) / 2.0 + averageDepth = (self.descriptor.conceptualDepth + self.relation.conceptualDepth) / 2.0 averageDepth **= 1.1 # see if the object corresponds to an object # if so, see if the descriptor is present (modulo slippages) in the # corresponding object - changedObjects = [ o for o in workspace.initial.objects if o.changed ] + changedObjects = [o for o in workspace.initial.objects if o.changed] changed = changedObjects[0] sharedDescriptorTerm = 0.0 if changed and changed.correspondence: @@ -36,17 +37,17 @@ class Rule(WorkspaceStructure): slippages = workspace.slippages() slipnode = self.descriptor.applySlippages(slippages) if not targetObject.hasDescription(slipnode): - self.internalStrength = 0.0 + self.internalStrength = 0.0 return sharedDescriptorTerm = 100.0 sharedDescriptorWeight = ((100.0 - self.descriptor.conceptualDepth) / 10.0) ** 1.4 depthDifference = 100.0 - abs(self.descriptor.conceptualDepth - self.relation.conceptualDepth) - weights = ( (depthDifference,12), (averageDepth,18), (sharedDescriptorTerm,sharedDescriptorWeight) ) - self.internalStrength = weightedAverage( weights ) + weights = ((depthDifference, 12), (averageDepth, 18), (sharedDescriptorTerm, sharedDescriptorWeight)) + self.internalStrength = weightedAverage(weights) if self.internalStrength > 100.0: self.internalStrength = 100.0 - def ruleEqual(self,other): + def ruleEqual(self, other): if not other: return False if self.relation != other.relation: @@ -73,18 +74,18 @@ class Rule(WorkspaceStructure): if not correspondence: return False # find changed object - changeds = [ o for o in workspace.initial.objects if o.changed ] + changeds = [o for o in workspace.initial.objects if o.changed] if not changeds: return False changed = changeds[0] if correspondence.objectFromInitial != changed: return False # it is incompatible if the rule descriptor is not in the mapping list - if len([ m for m in correspondence.conceptMappings if m.initialDescriptor == self.descriptor ]): + if len([m for m in correspondence.conceptMappings if m.initialDescriptor == self.descriptor]): return False return True - def __changeString(self,string): + def __changeString(self, string): # applies the changes to self string ie. successor if self.facet == slipnet.length: if self.relation == slipnet.predecessor: @@ -96,11 +97,11 @@ class Rule(WorkspaceStructure): if self.relation == slipnet.predecessor: if 'a' in string: return None - return ''.join([ chr(ord(c) - 1) for c in string]) + return ''.join([chr(ord(c) - 1) for c in string]) elif self.relation == slipnet.successor: if 'z' in string: return None - return ''.join([ chr(ord(c) + 1) for c in string]) + return ''.join([chr(ord(c) + 1) for c in string]) else: return self.relation.name.lower() @@ -112,9 +113,9 @@ class Rule(WorkspaceStructure): self.relation = self.relation.applySlippages(slippages) # generate the final string self.finalAnswer = workspace.targetString - changeds = [ o for o in workspace.target.objects if + changeds = [o for o in workspace.target.objects if o.hasDescription(self.descriptor) and - o.hasDescription(self.category) ] + o.hasDescription(self.category)] changed = changeds and changeds[0] or None logging.debug('changed object = %s' % changed) if changed: @@ -131,4 +132,3 @@ class Rule(WorkspaceStructure): endString = self.finalAnswer[right:] self.finalAnswer = startString + middleString + endString return True - diff --git a/copycat/sliplink.py b/copycat/sliplink.py index fa08802..3814dd2 100644 --- a/copycat/sliplink.py +++ b/copycat/sliplink.py @@ -1,5 +1,6 @@ #from slipnode import Slipnode + class Sliplink(object): def __init__(self, source, destination, label=None, length=0.0): self.source = source @@ -25,4 +26,4 @@ class Sliplink(object): self.destination.buffer += self.intrinsicDegreeOfAssociation() def points_at(self, other): - return self.destination == other \ No newline at end of file + return self.destination == other diff --git a/copycat/slipnet.py b/copycat/slipnet.py index b8710fb..4de8f59 100644 --- a/copycat/slipnet.py +++ b/copycat/slipnet.py @@ -3,6 +3,7 @@ import logging from slipnode import Slipnode from sliplink import Sliplink + class SlipNet(object): def __init__(self): logging.debug("SlipNet.__init__()") @@ -242,7 +243,7 @@ class SlipNet(object): self.slipnodes += [slipnode] return slipnode - def __link_items_to_their_neighbours(self,items): + def __link_items_to_their_neighbours(self, items): previous = items[0] for item in items[1:]: self.__addNonSlipLink(previous, item, label=self.successor) diff --git a/copycat/slipnode.py b/copycat/slipnode.py index 38cf542..b3d200c 100644 --- a/copycat/slipnode.py +++ b/copycat/slipnode.py @@ -2,12 +2,15 @@ import math import utils import logging + def full_activation(): return 100 + def jump_threshold(): return 55.0 + class Slipnode(object): def __init__(self, name, depth, length=0.0): # logging.info('depth to %s for %s' % (depth,name)) @@ -57,7 +60,7 @@ class Slipnode(object): def fully_active(self): """Whether this node has full activation""" - return self.activation > full_activation() - 0.00001 # allow a little leeway for floats + return self.activation > full_activation() - 0.00001 # allow a little leeway for floats def activate_fully(self): """Make this node fully active""" @@ -79,7 +82,7 @@ class Slipnode(object): def update(self): act = self.activation self.oldActivation = act - self.buffer -= self.activation * ( 100.0 - self.conceptual_depth) / 100.0 + self.buffer -= self.activation * (100.0 - self.conceptual_depth) / 100.0 def linked(self, other): """Whether the other is among the outgoing links""" @@ -141,7 +144,7 @@ class Slipnode(object): def spread_activation(self): if self.fully_active(): - [ link.spread_activation() for link in self.outgoingLinks ] + [link.spread_activation() for link in self.outgoingLinks] def addBuffer(self): if not self.clamped: diff --git a/copycat/temperature.py b/copycat/temperature.py index 6e17b4b..b46c63d 100644 --- a/copycat/temperature.py +++ b/copycat/temperature.py @@ -1,5 +1,6 @@ import logging + class Temperature(object): def __init__(self): self.value = 100.0 diff --git a/copycat/utils.py b/copycat/utils.py index 1c3a946..a7e6439 100644 --- a/copycat/utils.py +++ b/copycat/utils.py @@ -1,4 +1,3 @@ - def any(things): """Return True if any of the things are True. @@ -57,6 +56,7 @@ def any(things): return True return False + def all(things): """Return True if all of the things are True. @@ -114,6 +114,8 @@ import logging seed = 999.0 count = 0 testably_random = True + + def random(): global testably_random if testably_random: @@ -130,6 +132,7 @@ def random(): # sys.exit(1) return seed / 2000.0 + def choice(aList): i = int(random() * len(aList)) return aList[i] @@ -137,4 +140,3 @@ def choice(aList): if __name__ == '__main__': import doctest doctest.testmod() - diff --git a/copycat/workspace.py b/copycat/workspace.py index e952e01..b17d9d7 100644 --- a/copycat/workspace.py +++ b/copycat/workspace.py @@ -4,6 +4,7 @@ from workspaceString import WorkspaceString unknownAnswer = '?' + class Workspace(object): def __init__(self): #logging.debug('workspace.__init__()') @@ -155,4 +156,3 @@ class Workspace(object): workspace = Workspace() - diff --git a/copycat/workspaceFormulas.py b/copycat/workspaceFormulas.py index cfd14a3..e38e590 100644 --- a/copycat/workspaceFormulas.py +++ b/copycat/workspaceFormulas.py @@ -5,6 +5,7 @@ from temperature import temperature from slipnet import slipnet import formulas + class WorkspaceFormulas(object): def __init__(self): self.clampTemperature = False @@ -16,7 +17,7 @@ class WorkspaceFormulas(object): if workspace.rule: workspace.rule.updateStrength() ruleWeakness = 100.0 - workspace.rule.totalStrength - values = ( (workspace.totalUnhappiness, 0.8), (ruleWeakness, 0.2), ) + values = ((workspace.totalUnhappiness, 0.8), (ruleWeakness, 0.2)) slightly_above_actual_temperature = formulas.actualTemperature + 0.001 logging.info('actualTemperature: %f' % slightly_above_actual_temperature) formulas.actualTemperature = formulas.weightedAverage(values) @@ -32,14 +33,17 @@ class WorkspaceFormulas(object): workspaceFormulas = WorkspaceFormulas() + def numberOfObjects(): return len(workspace.objects) -def chooseUnmodifiedObject(attribute,inObjects): - objects = [ o for o in inObjects if o.string != workspace.modified ] + +def chooseUnmodifiedObject(attribute, inObjects): + objects = [o for o in inObjects if o.string != workspace.modified] if not len(objects): print 'no objects available in initial or target strings' - return formulas.chooseObjectFromList(objects,attribute) + return formulas.chooseObjectFromList(objects, attribute) + def chooseNeighbour(source): objects = [] @@ -47,50 +51,56 @@ def chooseNeighbour(source): if objekt.string != source.string: continue if objekt.leftStringPosition == source.rightStringPosition + 1: - objects += [ objekt ] + objects += [objekt] elif source.leftStringPosition == objekt.rightStringPosition + 1: - objects += [ objekt ] - return formulas.chooseObjectFromList(objects,"intraStringSalience") + objects += [objekt] + return formulas.chooseObjectFromList(objects, "intraStringSalience") -def chooseDirectedNeighbor(source,direction): + +def chooseDirectedNeighbor(source, direction): if direction == slipnet.left: logging.info('Left') return __chooseLeftNeighbor(source) logging.info('Right') return __chooseRightNeighbor(source) + def __chooseLeftNeighbor(source): objects = [] for o in workspace.objects: - if o.string == source.string : + if o.string == source.string: if source.leftStringPosition == o.rightStringPosition + 1: - logging.info('%s is on left of %s' % (o,source)) - objects += [ o ] + logging.info('%s is on left of %s' % (o, source)) + objects += [o] else: - logging.info('%s is not on left of %s' % (o,source)) + logging.info('%s is not on left of %s' % (o, source)) logging.info('Number of left objects: %s' % len(objects)) - return formulas.chooseObjectFromList(objects,'intraStringSalience') + return formulas.chooseObjectFromList(objects, 'intraStringSalience') + def __chooseRightNeighbor(source): - objects = [ o for o in workspace.objects if + objects = [o for o in workspace.objects if o.string == source.string and o.leftStringPosition == source.rightStringPosition + 1 ] - return formulas.chooseObjectFromList(objects,'intraStringSalience') + return formulas.chooseObjectFromList(objects, 'intraStringSalience') + def chooseBondFacet(source, destination): - sourceFacets = [ d.descriptionType for d in source.descriptions if d.descriptionType in slipnet.bondFacets ] - bondFacets = [ d.descriptionType for d in destination.descriptions if d.descriptionType in sourceFacets ] + sourceFacets = [d.descriptionType for d in source.descriptions if d.descriptionType in slipnet.bondFacets] + bondFacets = [d.descriptionType for d in destination.descriptions if d.descriptionType in sourceFacets] if not bondFacets: return None - supports = [ __supportForDescriptionType(f,source.string) for f in bondFacets ] + supports = [__supportForDescriptionType(f, source.string) for f in bondFacets] i = formulas.selectListPosition(supports) - return bondFacets[ i ] + return bondFacets[i] -def __supportForDescriptionType(descriptionType,string): - return ( descriptionType.activation + __descriptionTypeSupport(descriptionType,string) ) / 2 -def __descriptionTypeSupport(descriptionType,string): +def __supportForDescriptionType(descriptionType, string): + return (descriptionType.activation + __descriptionTypeSupport(descriptionType, string)) / 2 + + +def __descriptionTypeSupport(descriptionType, string): """The proportion of objects in the string that have a description with this descriptionType""" numberOfObjects = totalNumberOfObjects = 0.0 for objekt in workspace.objects: @@ -101,11 +111,12 @@ def __descriptionTypeSupport(descriptionType,string): numberOfObjects += 1.0 return numberOfObjects / totalNumberOfObjects + def probabilityOfPosting(codeletName): if codeletName == 'breaker': return 1.0 if 'description' in codeletName: - result = ( formulas.Temperature / 100.0 ) ** 2 + result = (formulas.Temperature / 100.0) ** 2 else: result = workspace.intraStringUnhappiness / 100.0 if 'correspondence' in codeletName: @@ -126,6 +137,7 @@ def probabilityOfPosting(codeletName): return 1.0 return result + def howManyToPost(codeletName): if codeletName == 'breaker': return 1 @@ -156,5 +168,3 @@ def howManyToPost(codeletName): if number < formulas.blur(4.0): return 2 return 3 - - diff --git a/copycat/workspaceObject.py b/copycat/workspaceObject.py index 79d7360..fe3cec2 100644 --- a/copycat/workspaceObject.py +++ b/copycat/workspaceObject.py @@ -4,8 +4,9 @@ from description import Description from slipnet import slipnet from workspaceStructure import WorkspaceStructure + class WorkspaceObject(WorkspaceStructure): - def __init__(self,workspaceString): + def __init__(self, workspaceString): WorkspaceStructure.__init__(self) self.string = workspaceString #self.string.objects += [ self ] @@ -42,21 +43,21 @@ class WorkspaceObject(WorkspaceStructure): def spansString(self): return self.leftmost and self.rightmost - def addDescription(self,descriptionType,descriptor): - description = Description(self,descriptionType,descriptor) - logging.info("Adding description: %s to %s" % (description,self)) - self.descriptions += [ description ] + def addDescription(self, descriptionType, descriptor): + description = Description(self, descriptionType, descriptor) + logging.info("Adding description: %s to %s" % (description, self)) + self.descriptions += [description] - def addDescriptions(self,descriptions): + def addDescriptions(self, descriptions): #print 'addDescriptions 1' #print 'add %d to %d of %s' % (len(descriptions),len(self.descriptions), self.string.string) - copy = descriptions[:] # in case we add to our own descriptions, which turns the loop infinite + copy = descriptions[:] # in case we add to our own descriptions, which turns the loop infinite for description in copy: #print '%d addDescriptions 2 %s ' % (len(descriptions),description) logging.info('might add: %s' % description) if not self.containsDescription(description): #print '%d addDescriptions 3 %s ' % (len(descriptions),description) - self.addDescription(description.descriptionType,description.descriptor) + self.addDescription(description.descriptionType, description.descriptor) #print '%d addDescriptions 4 %s ' % (len(descriptions),description) else: logging.info("Won't add it") @@ -73,7 +74,7 @@ class WorkspaceObject(WorkspaceStructure): for bond in self.bonds: bondStrength += bond.totalStrength divisor = 6.0 - if self.spansString(): # XXX then we have already returned + if self.spansString(): # XXX then we have already returned divisor = 3.0 return bondStrength / divisor @@ -104,7 +105,7 @@ class WorkspaceObject(WorkspaceStructure): self.interStringUnhappiness = 100.0 - interStringHappiness #logging.info("Unhappy: %s"%self.interStringUnhappiness) - averageHappiness = ( intraStringHappiness + interStringHappiness ) / 2 + averageHappiness = (intraStringHappiness + interStringHappiness) / 2 self.totalUnhappiness = 100.0 - averageHappiness if self.clampSalience: @@ -112,45 +113,45 @@ class WorkspaceObject(WorkspaceStructure): self.interStringSalience = 100.0 else: from formulas import weightedAverage - self.intraStringSalience = weightedAverage( ((self.relativeImportance,0.2), (self.intraStringUnhappiness,0.8)) ) - self.interStringSalience = weightedAverage( ((self.relativeImportance,0.8), (self.interStringUnhappiness,0.2)) ) + self.intraStringSalience = weightedAverage(((self.relativeImportance, 0.2), (self.intraStringUnhappiness, 0.8))) + self.interStringSalience = weightedAverage(((self.relativeImportance, 0.8), (self.interStringUnhappiness, 0.2))) self.totalSalience = (self.intraStringSalience + self.interStringSalience) / 2.0 logging.info('Set salience of %s to %f = (%f + %f)/2' % ( - self.__str__(),self.totalSalience, self.intraStringSalience, self.interStringSalience)) + self.__str__(), self.totalSalience, self.intraStringSalience, self.interStringSalience)) - def isWithin(self,other): + def isWithin(self, other): return self.leftStringPosition >= other.leftStringPosition and self.rightStringPosition <= other.rightStringPosition def relevantDescriptions(self): - return [ d for d in self.descriptions if d.descriptionType.fully_active() ] + return [d for d in self.descriptions if d.descriptionType.fully_active()] - def morePossibleDescriptions(self,node): + def morePossibleDescriptions(self, node): return [] - def getPossibleDescriptions(self,descriptionType): + def getPossibleDescriptions(self, descriptionType): logging.info('getting possible descriptions for %s' % self) - descriptions = [ ] + descriptions = [] from group import Group for link in descriptionType.instanceLinks: node = link.destination if node == slipnet.first and self.hasDescription(slipnet.letters[0]): - descriptions += [ node ] + descriptions += [node] if node == slipnet.last and self.hasDescription(slipnet.letters[-1]): - descriptions += [ node ] + descriptions += [node] i = 1 for number in slipnet.numbers: - if node == number and isinstance(self,Group) and len(self.objectList) == i: - descriptions += [ node ] + if node == number and isinstance(self, Group) and len(self.objectList) == i: + descriptions += [node] i += 1 if node == slipnet.middle and self.middleObject(): - descriptions += [ node ] + descriptions += [node] s = '' for d in descriptions: - s = '%s, %s' % (s,d.get_name()) + s = '%s, %s' % (s, d.get_name()) logging.info(s) return descriptions - def containsDescription(self,sought): + def containsDescription(self, sought): soughtType = sought.descriptionType soughtDescriptor = sought.descriptor for d in self.descriptions: @@ -158,8 +159,8 @@ class WorkspaceObject(WorkspaceStructure): return True return False - def hasDescription(self,slipnode): - return [ d for d in self.descriptions if d.descriptor == slipnode ] and True or False + def hasDescription(self, slipnode): + return [d for d in self.descriptions if d.descriptor == slipnode] and True or False def middleObject(self): # XXX only works if string is 3 chars long @@ -172,7 +173,7 @@ class WorkspaceObject(WorkspaceStructure): objectOnMyRightIsRightmost = True return objectOnMyRightIsRightmost and objectOnMyLeftIsLeftmost - def distinguishingDescriptor(self,descriptor): + def distinguishingDescriptor(self, descriptor): """Whether no other object of the same type (ie. letter or group) has the same descriptor""" if descriptor == slipnet.letter: return False @@ -184,19 +185,19 @@ class WorkspaceObject(WorkspaceStructure): return True def relevantDistinguishingDescriptors(self): - return [ d.descriptor for d in self.relevantDescriptions() if self.distinguishingDescriptor(d.descriptor) ] + return [d.descriptor for d in self.relevantDescriptions() if self.distinguishingDescriptor(d.descriptor)] - def getDescriptor(self,descriptionType): + def getDescriptor(self, descriptionType): """The description attached to this object of the specified description type.""" descriptor = None - logging.info("\nIn %s, trying for type: %s" % (self,descriptionType.get_name())) + logging.info("\nIn %s, trying for type: %s" % (self, descriptionType.get_name())) for description in self.descriptions: logging.info("Trying description: %s" % description) if description.descriptionType == descriptionType: return description.descriptor return descriptor - def getDescriptionType(self,sought_description): + def getDescriptionType(self, sought_description): """The description_type attached to this object of the specified description""" for description in self.descriptions: if description.descriptor == sought_description: @@ -204,10 +205,10 @@ class WorkspaceObject(WorkspaceStructure): description = None return description - def getCommonGroups(self,other): - return [ o for o in self.string.objects if self.isWithin(o) and other.isWithin(o) ] + def getCommonGroups(self, other): + return [o for o in self.string.objects if self.isWithin(o) and other.isWithin(o)] - def letterDistance(self,other): + def letterDistance(self, other): if other.leftStringPosition > self.rightStringPosition: return other.leftStringPosition - self.rightStringPosition if self.leftStringPosition > other.rightStringPosition: @@ -217,10 +218,9 @@ class WorkspaceObject(WorkspaceStructure): def letterSpan(self): return self.rightStringPosition - self.leftStringPosition + 1 - def beside(self,other): + def beside(self, other): if self.string != other.string: return False if self.leftStringPosition == other.rightStringPosition + 1: return True return other.leftStringPosition == self.rightStringPosition + 1 - diff --git a/copycat/workspaceString.py b/copycat/workspaceString.py index ea68d01..3731a13 100644 --- a/copycat/workspaceString.py +++ b/copycat/workspaceString.py @@ -2,6 +2,7 @@ import logging from letter import Letter from slipnet import slipnet + class WorkspaceString(object): def __init__(self, s): self.string = s @@ -60,7 +61,7 @@ class WorkspaceString(object): else: for o in self.objects: logging.info('object: %s, relative: %d = raw: %d / total: %d' % ( - o, o.relativeImportance * 1000, o.rawImportance, total )) + o, o.relativeImportance * 1000, o.rawImportance, total)) o.relativeImportance = o.rawImportance / total def updateIntraStringUnhappiness(self): diff --git a/copycat/workspaceStructure.py b/copycat/workspaceStructure.py index 107e16b..7b2546c 100644 --- a/copycat/workspaceStructure.py +++ b/copycat/workspaceStructure.py @@ -1,5 +1,6 @@ import formulas + class WorkspaceStructure(object): def __init__(self): self.string = None @@ -14,7 +15,7 @@ class WorkspaceStructure(object): def updateTotalStrength(self): """Recalculate the total strength based on internal and external strengths""" - weights = ( (self.internalStrength, self.internalStrength), (self.externalStrength, 100 - self.internalStrength) ) + weights = ((self.internalStrength, self.internalStrength), (self.externalStrength, 100 - self.internalStrength)) strength = formulas.weightedAverage(weights) self.totalStrength = strength @@ -24,14 +25,14 @@ class WorkspaceStructure(object): def updateInternalStrength(self): """How internally cohesive the structure is""" - raise NotImplementedError, 'call of abstract method: WorkspaceStructure.updateInternalStrength()' + raise NotImplementedError('call of abstract method: WorkspaceStructure.updateInternalStrength()') def updateExternalStrength(self): - raise NotImplementedError, 'call of abstract method: WorkspaceStructure.updateExternalStrength()' + raise NotImplementedError('call of abstract method: WorkspaceStructure.updateExternalStrength()') def break_the_structure(self): """Break this workspace structure Exactly what is broken depends on sub-class """ - raise NotImplementedError, 'call of abstract method: WorkspaceStructure.break_the_structure()' + raise NotImplementedError('call of abstract method: WorkspaceStructure.break_the_structure()')