From 94a0ecae48703599535c04b46b08a1d31f9ab986 Mon Sep 17 00:00:00 2001 From: J Alan Brogan Date: Mon, 22 Dec 2014 16:38:10 +0000 Subject: [PATCH] PEP 008, mostly lines too long --- copycat/bond.py | 9 +- copycat/codeletMethods.py | 372 ++++++++++++++++++++++------------ copycat/coderack.py | 144 +++++++------ copycat/coderackPressure.py | 5 +- copycat/conceptMapping.py | 61 +++--- copycat/copycat.py | 16 +- copycat/correspondence.py | 69 ++++--- copycat/description.py | 20 +- copycat/formulas.py | 16 +- copycat/group.py | 22 +- copycat/letter.py | 12 +- copycat/rule.py | 35 ++-- copycat/slipnet.py | 45 ++-- copycat/slipnode.py | 25 ++- copycat/temperature.py | 6 +- copycat/unready.py | 2 - copycat/workspace.py | 67 +++--- copycat/workspaceFormulas.py | 8 +- copycat/workspaceObject.py | 87 ++++---- copycat/workspaceString.py | 11 +- copycat/workspaceStructure.py | 16 +- 21 files changed, 633 insertions(+), 415 deletions(-) delete mode 100644 copycat/unready.py diff --git a/copycat/bond.py b/copycat/bond.py index 666e466..e9b7df9 100644 --- a/copycat/bond.py +++ b/copycat/bond.py @@ -4,7 +4,8 @@ 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 @@ -12,7 +13,7 @@ class Bond(WorkspaceStructure): self.leftObject = self.source self.rightObject = self.destination self.directionCategory = slipnet.right - if self.source.leftStringPosition > self.destination.rightStringPosition: + if self.source.leftIndex > self.destination.rightIndex: self.leftObject = self.destination self.rightObject = self.source self.directionCategory = slipnet.left @@ -94,8 +95,8 @@ class Bond(WorkspaceStructure): def updateInternalStrength(self): # bonds between objects of same type(ie. letter or group) are # stronger than bonds between different types - sourceGap = self.get_source().leftStringPosition != self.get_source().rightStringPosition - destinationGap = self.destination.leftStringPosition != self.destination.rightStringPosition + sourceGap = self.get_source().leftIndex != self.get_source().rightIndex + destinationGap = self.destination.leftIndex != self.destination.rightIndex if sourceGap == destinationGap: memberCompatibility = 1.0 else: diff --git a/copycat/codeletMethods.py b/copycat/codeletMethods.py index 0e210ac..b3ea53b 100644 --- a/copycat/codeletMethods.py +++ b/copycat/codeletMethods.py @@ -28,14 +28,22 @@ def __getScoutSource(slipnode, relevanceMethod, typeName): 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 random.random() * (initialRelevance + initialUnhappiness + targetRelevance + targetUnhappiness) > (initialRelevance + initialUnhappiness): + relevances = initialRelevance + targetRelevance + unhappinesses = initialUnhappiness + targetUnhappiness + randomized = random.random() * (relevances + unhappinesses) + initials = initialRelevance + initialUnhappiness + if randomized > initials: 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)) + logging.info('initial string selected: %s for %s' % ( + workspace.initial, typeName)) source = chooseUnmodifiedObject('intraStringSalience', string.objects) return source @@ -60,27 +68,32 @@ def __allOppositeMappings(mappings): def __structureVsStructure(structure1, weight1, structure2, weight2): structure1.updateStrength() structure2.updateStrength() - weightedStrength1 = temperatureAdjustedValue(structure1.totalStrength * weight1) - weightedStrength2 = temperatureAdjustedValue(structure2.totalStrength * weight2) + weightedStrength1 = temperatureAdjustedValue( + structure1.totalStrength * weight1) + weightedStrength2 = temperatureAdjustedValue( + structure2.totalStrength * weight2) rhs = (weightedStrength1 + weightedStrength2) * random.random() logging.info('%d > %d' % (weightedStrength1, rhs)) return weightedStrength1 > rhs -def __fightItOut(structure, structureWeight, incompatibles, incompatibleWeight): +def __fight(structure, structureWeight, incompatibles, incompatibleWeight): if not (incompatibles and len(incompatibles)): return True for incompatible in incompatibles: - if not __structureVsStructure(structure, structureWeight, incompatible, incompatibleWeight): + if not __structureVsStructure(structure, structureWeight, + incompatible, incompatibleWeight): logging.info('lost fight with %s' % incompatible) return False 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 __fight(structure, structureWeight, + incompatibles, incompatibleWeight): logging.info('broke the %s' % name) return True logging.info('failed to break %s: Fizzle' % name) @@ -104,19 +117,19 @@ def breaker(): 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)] + isinstance(s, (Group, Bond, Correspondence))] assert len(structures) structure = random.choice(structures) __showWhichStringObjectIsFrom(structure) breakObjects = [structure] if isinstance(structure, Bond): - if structure.source.group and structure.source.group == structure.destination.group: - breakObjects += [structure.source.group] + if structure.source.group: + if structure.source.group == structure.destination.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: @@ -131,11 +144,13 @@ def bottom_up_description_scout(codelet): 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] chosenProperty = chosen.destination - coderack.proposeDescription(chosenObject, chosenProperty.category(), chosenProperty, codelet) + coderack.proposeDescription(chosenObject, chosenProperty.category(), + chosenProperty, codelet) def top_down_description_scout(codelet): @@ -148,7 +163,8 @@ def top_down_description_scout(codelet): values = [n.activation for n in descriptions] i = selectListPosition(values) chosenProperty = descriptions[i] - coderack.proposeDescription(chosenObject, chosenProperty.category(), chosenProperty, codelet) + coderack.proposeDescription(chosenObject, chosenProperty.category(), + chosenProperty, codelet) def description_strength_tester(codelet): @@ -164,7 +180,7 @@ def description_strength_tester(codelet): def description_builder(codelet): description = codelet.arguments[0] assert description.object in workspace.objects - if description.object.hasDescription(description.descriptor): + if description.object.described(description.descriptor): description.descriptionType.buffer = 100.0 description.descriptor.buffer = 100.0 else: @@ -180,15 +196,18 @@ def bottom_up_bond_scout(codelet): 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 descriptor: " + sourceDescriptor.name.upper()) - logging.info("destination descriptior: " + destinationDescriptor.name.upper()) + bond_descriptors = __getDescriptors(bondFacet, source, destination) + sourceDescriptor, destinationDescriptor = bond_descriptors + logging.info("source descriptor: %s", sourceDescriptor.name.upper()) + logging.info("destination descriptor: %s", + destinationDescriptor.name.upper()) category = sourceDescriptor.getBondCategory(destinationDescriptor) assert category 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): @@ -201,15 +220,17 @@ def rule_scout(codelet): changed = changedObjects[-1] # generate a list of distinguishing descriptions for the first object - # ie. string-position (leftmost,rightmost,middle or whole) or letter category + # ie. string-position (left-,right-most,middle or whole) or letter category # if it is the only one of its type in the string objectList = [] position = changed.getDescriptor(slipnet.stringPositionCategory) if 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 + otherObjectsOfSameLetter = [o for o in workspace.initial.objects + if not o != changed + and o.getDescriptionType(letter)] + if not len(otherObjectsOfSameLetter): objectList += [letter] # if this object corresponds to another object in the workspace # objectList = the union of this and the distingushing descriptors @@ -219,9 +240,11 @@ def rule_scout(codelet): slippages = workspace.slippages() 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") + if targetObject.described(node): + if targetObject.distinguishingDescriptor(node): + newList += [node] + objectList = newList # XXX surely this should be += + # "union of this and distinguishing descriptors" assert objectList and len(objectList) # use conceptual depth to choose a description valueList = [] @@ -231,11 +254,12 @@ def rule_scout(codelet): valueList += [value] i = selectListPosition(valueList) descriptor = objectList[i] - # choose the relation (change the letmost object to..xxxx) i.e. "successor" or "d" + # choose the relation (change the letmost object to "successor" or "d" objectList = [] if changed.replacement.relation: objectList += [changed.replacement.relation] - objectList += [changed.replacement.objectFromModified.getDescriptor(slipnet.letterCategory)] + objectList += [changed.replacement.objectFromModified.getDescriptor( + slipnet.letterCategory)] # use conceptual depth to choose a relation valueList = [] for node in objectList: @@ -244,7 +268,8 @@ def rule_scout(codelet): valueList += [value] i = selectListPosition(valueList) relation = objectList[i] - coderack.proposeRule(slipnet.letterCategory, descriptor, slipnet.letter, relation, codelet) + coderack.proposeRule(slipnet.letterCategory, descriptor, + slipnet.letter, relation, codelet) def rule_strength_tester(codelet): @@ -259,12 +284,15 @@ def replacement_finder(): # choose random letter in initial string letters = [o for o in workspace.initial.objects if isinstance(o, Letter)] letterOfInitialString = random.choice(letters) - logging.info('selected letter in initial string = %s' % letterOfInitialString) + logging.info('selected letter in initial string = %s', + letterOfInitialString) if letterOfInitialString.replacement: - logging.info("Replacement already found for %s, so fizzling" % letterOfInitialString) + 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] + position = letterOfInitialString.leftIndex + moreLetters = [o for o in workspace.modified.objects + if isinstance(o, Letter) and o.leftIndex == position] letterOfModifiedString = moreLetters and moreLetters[0] or None assert letterOfModifiedString position -= 1 @@ -272,13 +300,17 @@ 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 @@ -293,7 +325,8 @@ def top_down_bond_scout__category(codelet): logging.info('source: %s, destination: %s' % (source, destination)) assert destination bondFacet = __getBondFacet(source, destination) - sourceDescriptor, destinationDescriptor = __getDescriptors(bondFacet, source, destination) + sourceDescriptor, destinationDescriptor = __getDescriptors( + bondFacet, source, destination) forwardBond = sourceDescriptor.getBondCategory(destinationDescriptor) if forwardBond == slipnet.identity: forwardBond = slipnet.sameness @@ -302,24 +335,31 @@ 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') + 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) + 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): @@ -341,7 +381,8 @@ def bond_builder(codelet): bond = codelet.arguments[0] __showWhichStringObjectIsFrom(bond) bond.updateStrength() - assert (bond.source in workspace.objects or bond.destination in workspace.objects) + assert (bond.source in workspace.objects or + bond.destination in workspace.objects) for stringBond in bond.string.bonds: if bond.sameNeighbours(stringBond) and bond.sameCategories(stringBond): if bond.directionCategory: @@ -363,8 +404,9 @@ 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 __fightIncompatibles(incompatibleCorrespondences,bond,'correspondences',2.0,3.0) + assert __fight(bond, 2.0, incompatibleCorrespondences, 3.0) + #assert __fightIncompatibles(incompatibleCorrespondences, + # bond, 'correspondences', 2.0, 3.0) for incompatible in incompatibleBonds: incompatible.break_the_structure() for incompatible in incompatibleGroups: @@ -404,7 +446,8 @@ def top_down_group_scout__category(codelet): 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], []) + group = Group(source.string, slipnet.samenessGroup, + None, slipnet.letterCategory, [source], []) probability = group.singleLetterGroupProbability() assert random.random() >= probability coderack.proposeSingleLetterGroup(source, codelet) @@ -415,27 +458,35 @@ def top_down_group_scout__category(codelet): # find leftmost object in group with these bonds while search: search = False - if source.leftBond: - if source.leftBond.category == category: - if not source.leftBond.directionCategory or source.leftBond.directionCategory == direction: - if not bondFacet or bondFacet == source.leftBond.facet: - bondFacet = source.leftBond.facet - direction = source.leftBond.directionCategory - source = source.leftBond.leftObject - search = True + if not source.leftBond: + continue + if source.leftBond.category != category: + continue + if source.leftBond.directionCategory != direction: + if source.leftBond.directionCategory: + continue + if not bondFacet or bondFacet == source.leftBond.facet: + bondFacet = source.leftBond.facet + direction = source.leftBond.directionCategory + source = source.leftBond.leftObject + search = True # find rightmost object in group with these bonds search = True destination = source while search: search = False - if destination.rightBond: - if destination.rightBond.category == category: - if not destination.rightBond.directionCategory or destination.rightBond.directionCategory == direction: - if not bondFacet or bondFacet == destination.rightBond.facet: - bondFacet = destination.rightBond.facet - direction = source.rightBond.directionCategory - destination = destination.rightBond.rightObject - search = True + if not destination.rightBond: + continue + if destination.rightBond.category != category: + continue + if destination.rightBond.directionCategory != direction: + if destination.rightBond.directionCategory: + continue + if not bondFacet or bondFacet == destination.rightBond.facet: + bondFacet = destination.rightBond.facet + direction = source.rightBond.directionCategory + destination = destination.rightBond.rightObject + search = True assert destination != source objects = [source] bonds = [] @@ -443,12 +494,14 @@ def top_down_group_scout__category(codelet): 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: @@ -494,26 +547,34 @@ def top_down_group_scout__direction(codelet): search = True while search: search = False - if source.leftBond: - if source.leftBond.category == category: - if not source.leftBond.directionCategory or source.leftBond.directionCategory == direction: - if not bondFacet or bondFacet == source.leftBond.facet: - bondFacet = source.leftBond.facet - direction = source.leftBond.directionCategory - source = source.leftBond.leftObject - search = True + if not source.leftBond: + continue + if source.leftBond.category != category: + continue + if source.leftBond.directionCategory != direction: + if source.leftBond.directionCategory: + continue + if not bondFacet or bondFacet == source.leftBond.facet: + bondFacet = source.leftBond.facet + direction = source.leftBond.directionCategory + source = source.leftBond.leftObject + search = True destination = source search = True while search: search = False - if destination.rightBond: - if destination.rightBond.category == category: - if not destination.rightBond.directionCategory or destination.rightBond.directionCategory == direction: - if not bondFacet or bondFacet == destination.rightBond.facet: - bondFacet = destination.rightBond.facet - direction = source.rightBond.directionCategory - destination = destination.rightBond.rightObject - search = True + if not destination.rightBond: + continue + if destination.rightBond.category != category: + continue + if destination.rightBond.directionCategory != direction: + if destination.rightBond.directionCategory: + continue + if not bondFacet or bondFacet == destination.rightBond.facet: + bondFacet = destination.rightBond.facet + direction = source.rightBond.directionCategory + destination = destination.rightBond.rightObject + search = True assert destination != source logging.info('proposing group from %s to %s' % (source, destination)) objects = [source] @@ -522,7 +583,8 @@ def top_down_group_scout__direction(codelet): 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 @@ -543,7 +605,9 @@ 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] @@ -560,7 +624,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): @@ -600,17 +665,21 @@ def group_builder(codelet): #print 770 leftBond = objekt.leftBond if leftBond: - lefty = leftBond.leftObject - if lefty != previous or leftBond.directionCategory != group.directionCategory: - incompatibleBonds += [leftBond] + if leftBond.leftObject == previous: + continue + if leftBond.directionCategory == group.directionCategory: + continue + incompatibleBonds += [leftBond] previous = objekt next = group.objectList[-1] for objekt in reversed(group.objectList[:-1]): rightBond = objekt.rightBond if rightBond: - righty = rightBond.rightObject - if righty != next or rightBond.directionCategory != group.directionCategory: - incompatibleBonds += [rightBond] + if rightBond.rightObject == next: + continue + if rightBond.directionCategory == group.directionCategory: + continue + incompatibleBonds += [rightBond] next = objekt # if incompatible bonds exist - fight group.updateStrength() @@ -636,7 +705,9 @@ 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] for incompatible in incompatibleGroups: @@ -684,7 +755,8 @@ def rule_translator(): if len(workspace.initial) == 1 and len(workspace.target) == 1: bondDensity = 1.0 else: - numberOfBonds = len(workspace.initial.bonds) + len(workspace.target.bonds) + numberOfBonds = (len(workspace.initial.bonds) + + len(workspace.target.bonds)) nearlyTotalLength = len(workspace.initial) + len(workspace.target) - 2 bondDensity = numberOfBonds / nearlyTotalLength if bondDensity > 1.0: @@ -700,31 +772,43 @@ def rule_translator(): 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()] 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] + opposites = [m for m in distinguishingMappings + if m.initialDescriptionType == slipnet.stringPositionCategory + and m.initialDescriptionType != slipnet.bondFacet] + initialDescriptionTypes = [m.initialDescriptionType for m in opposites] flipTargetObject = False - if objectFromInitial.spansString() and objectFromTarget.spansString() and slipnet.directionCategory in initialDescriptionTypes and __allOppositeMappings(oppositeMappings) and slipnet.opposite.activation != 100.0: + 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 @@ -738,31 +822,47 @@ def important_object_correspondence_scout(codelet): if description.descriptor == initialDescriptor: 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()] 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] + opposites = [m for m in distinguishingMappings + if m.initialDescriptionType == slipnet.stringPositionCategory + and m.initialDescriptionType != slipnet.bondFacet] + initialDescriptionTypes = [m.initialDescriptionType for m in opposites] flipTargetObject = False - if objectFromInitial.spansString() and objectFromTarget.spansString() and slipnet.directionCategory in initialDescriptionTypes and __allOppositeMappings(oppositeMappings) and slipnet.opposite.activation != 100.0: + 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] objectFromInitial = correspondence.objectFromInitial objectFromTarget = correspondence.objectFromTarget - assert objectFromInitial in workspace.objects and (objectFromTarget in workspace.objects or correspondence.flipTargetObject and not workspace.target.equivalentGroup(objectFromTarget.flipped_version())) + 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) @@ -773,7 +873,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): @@ -788,7 +889,8 @@ def correspondence_builder(codelet): targetNotFlipped = False initialInObjects = objectFromInitial in workspace.objects targetInObjects = objectFromTarget in workspace.objects - assert (initialInObjects or (not targetInObjects and (not (wantFlip and targetNotFlipped)))) + assert (initialInObjects or ( + not targetInObjects and (not (wantFlip and targetNotFlipped)))) if correspondence.reflexive(): # if the correspondence exists, activate concept mappings # and add new ones to the existing corr. @@ -799,32 +901,42 @@ def correspondence_builder(codelet): if not mapping.isContainedBy(existing.conceptMappings): existing.conceptMappings += [mapping] return - incompatibleCorrespondences = correspondence.getIncompatibleCorrespondences() + incompatibles = correspondence.getIncompatibleCorrespondences() # fight against all correspondences - if incompatibleCorrespondences: - correspondenceSpans = correspondence.objectFromInitial.letterSpan() + correspondence.objectFromTarget.letterSpan() - for incompatible in incompatibleCorrespondences: - incompatibleSpans = incompatible.objectFromInitial.letterSpan() + incompatible.objectFromTarget.letterSpan() - assert __structureVsStructure(correspondence, correspondenceSpans, incompatible, incompatibleSpans) + if incompatibles: + correspondenceSpans = (correspondence.objectFromInitial.letterSpan() + + correspondence.objectFromTarget.letterSpan()) + for incompatible in incompatibles: + incompatibleSpans = (incompatible.objectFromInitial.letterSpan() + + incompatible.objectFromTarget.letterSpan()) + assert __structureVsStructure(correspondence, correspondenceSpans, + incompatible, incompatibleSpans) incompatibleBond = None incompatibleGroup = None # if there is an incompatible bond then fight against it - if correspondence.objectFromInitial.leftmost or correspondence.objectFromInitial.rightmost and correspondence.objectFromTarget.leftmost or correspondence.objectFromTarget.rightmost: + initial = correspondence.objectFromInitial + target = correspondence.objectFromTarget + if (initial.leftmost or initial.rightmost and + target.leftmost or target.rightmost): # search for the incompatible bond 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 + incompatibleGroup = target.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) - for incompatible in incompatibleCorrespondences: + if workspace.rule: + if workspace.rule.incompatibleRuleCorrespondence(correspondence): + incompatibleRule = workspace.rule + assert __structureVsStructure(correspondence, 1.0, + incompatibleRule, 1.0) + for incompatible in incompatibles: incompatible.break_the_structure() # break incompatible group and bond if they exist if incompatibleBond: diff --git a/copycat/coderack.py b/copycat/coderack.py index f525aea..71d6f3d 100644 --- a/copycat/coderack.py +++ b/copycat/coderack.py @@ -25,7 +25,9 @@ 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 = {} @@ -52,7 +54,6 @@ class CodeRack(object): return bin + 1 def post(self, codelet): - #logging.info('Posting codelet called: %s, with urgency %f' % (codelet.name,codelet.urgency)) self.postings[codelet.name] = self.postings.get(codelet.name, 0) + 1 self.pressures.addCodelet(codelet) self.codelets += [codelet] @@ -63,20 +64,23 @@ class CodeRack(object): def postTopDownCodelets(self): for node in slipnet.slipnodes: #logging.info('Trying slipnode: %s' % node.get_name()) - if node.activation == 100.0: - #logging.info('using slipnode: %s' % node.get_name()) - for codeletName in node.codelets: - probability = workspaceFormulas.probabilityOfPosting(codeletName) - howMany = workspaceFormulas.howManyToPost(codeletName) - #print '%s:%d' % (codeletName,howMany) - for unused in range(0, howMany): - if random.random() < probability: - urgency = self.getUrgencyBin(node.activation * node.conceptualDepth / 100.0) - codelet = Codelet(codeletName, urgency, self.codeletsRun) - codelet.arguments += [node] - logging.info('Post top down: %s, with urgency: %d' % (codelet.name, urgency)) - #logging.info("From slipnode %s, activation: %s, depth: %s" %(node.get_name(),node.activation,node.conceptualDepth) ) - self.post(codelet) + if node.activation != 100.0: + continue + #logging.info('using slipnode: %s' % node.get_name()) + for codeletName in node.codelets: + probability = workspaceFormulas.probabilityOfPosting( + codeletName) + howMany = workspaceFormulas.howManyToPost(codeletName) + for unused in range(0, howMany): + if random.random() >= probability: + continue + urgency = self.getUrgencyBin( + node.activation * node.conceptualDepth / 100.0) + codelet = Codelet(codeletName, urgency, self.codeletsRun) + codelet.arguments += [node] + logging.info('Post top down: %s, with urgency: %d', + codelet.name, urgency) + self.post(codelet) def postBottomUpCodelets(self): logging.info("posting bottom up codelets") @@ -127,7 +131,8 @@ class CodeRack(object): def proposeRule(self, facet, description, category, relation, oldCodelet): """Creates a proposed rule, and posts a rule-strength-tester codelet. - The new codelet has urgency a function of the degree of conceptual-depth of the descriptions in the rule + The new codelet has urgency a function of + the degree of conceptual-depth of the descriptions in the rule """ from rule import Rule @@ -141,10 +146,12 @@ class CodeRack(object): urgency = 0 self.newCodelet('rule-strength-tester', oldCodelet, urgency, rule) - def proposeCorrespondence(self, initialObject, targetObject, conceptMappings, flipTargetObject, oldCodelet): + def proposeCorrespondence(self, initialObject, targetObject, + conceptMappings, flipTargetObject, oldCodelet): from correspondence import Correspondence - correspondence = Correspondence(initialObject, targetObject, conceptMappings, flipTargetObject) + correspondence = Correspondence(initialObject, targetObject, + conceptMappings, flipTargetObject) for mapping in conceptMappings: mapping.initialDescriptionType.buffer = 100.0 mapping.initialDescriptor.buffer = 100.0 @@ -156,38 +163,46 @@ class CodeRack(object): if urgency: urgency /= numberOfMappings bin = self.getUrgencyBin(urgency) - logging.info('urgency: %s, number: %d, bin: %d' % (urgency, numberOfMappings, bin)) - self.newCodelet('correspondence-strength-tester', oldCodelet, urgency, correspondence) + logging.info('urgency: %s, number: %d, bin: %d', + urgency, numberOfMappings, bin) + self.newCodelet('correspondence-strength-tester', + oldCodelet, urgency, correspondence) - def proposeDescription(self, objekt, descriptionType, descriptor, oldCodelet): + def proposeDescription(self, objekt, type_, descriptor, oldCodelet): from description import Description - description = Description(objekt, descriptionType, descriptor) + description = Description(objekt, type_, descriptor) descriptor.buffer = 100.0 - urgency = descriptionType.activation - self.newCodelet('description-strength-tester', oldCodelet, urgency, description) + urgency = type_.activation + self.newCodelet('description-strength-tester', + oldCodelet, urgency, description) def proposeSingleLetterGroup(self, source, codelet): - self.proposeGroup([source], [], slipnet.samenessGroup, None, slipnet.letterCategory, 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) bondCategory.buffer = 100.0 if directionCategory: directionCategory.buffer = 100.0 - group = Group(objects[0].string, groupCategory, directionCategory, bondFacet, objects, bondList) + group = Group(objects[0].string, groupCategory, directionCategory, + bondFacet, objects, bondList) 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 sourceDescriptor.buffer = 100.0 destinationDescriptor.buffer = 100.0 - bond = Bond(source, destination, bondCategory, bondFacet, sourceDescriptor, destinationDescriptor) + bond = Bond(source, destination, bondCategory, bondFacet, + sourceDescriptor, destinationDescriptor) urgency = bondCategory.bondDegreeOfAssociation() self.newCodelet('bond-strength-tester', oldCodelet, urgency, bond) @@ -198,7 +213,8 @@ class CodeRack(object): return None urgencies = [] for codelet in self.codelets: - urgency = (coderack.codeletsRun - codelet.timeStamp) * (7.5 - codelet.urgency) + urgency = ((coderack.codeletsRun - codelet.timeStamp) * + (7.5 - codelet.urgency)) urgencies += [urgency] threshold = random.random() * sum(urgencies) sumOfUrgencies = 0.0 @@ -209,9 +225,6 @@ class CodeRack(object): return self.codelets[0] def postInitialCodelets(self): - #logging.debug('Posting initial codelets') - #logging.debug('Number of inital codelets: %d' % len(self.initialCodeletNames)) - #logging.debug('Number of workspaceObjects: %d' % workspace.numberOfObjects()) for name in self.initialCodeletNames: for unused in range(0, workspaceFormulas.numberOfObjects()): codelet = Codelet(name, 1, self.codeletsRun) @@ -230,36 +243,36 @@ class CodeRack(object): self.codeletMethodsDir = dir(codeletMethods) knownCodeletNames = ( - 'breaker', - 'bottom-up-description-scout', - 'top-down-description-scout', - 'description-strength-tester', - 'description-builder', - 'bottom-up-bond-scout', - 'top-down-bond-scout--category', - 'top-down-bond-scout--direction', - 'bond-strength-tester', - 'bond-builder', - 'top-down-group-scout--category', - 'top-down-group-scout--direction', - 'group-scout--whole-string', - 'group-strength-tester', - 'group-builder', - 'replacement-finder', - 'rule-scout', - 'rule-strength-tester', - 'rule-builder', - 'rule-translator', - 'bottom-up-correspondence-scout', - 'important-object-correspondence-scout', - 'correspondence-strength-tester', - 'correspondence-builder', - ) + 'breaker', + 'bottom-up-description-scout', + 'top-down-description-scout', + 'description-strength-tester', + 'description-builder', + 'bottom-up-bond-scout', + 'top-down-bond-scout--category', + 'top-down-bond-scout--direction', + 'bond-strength-tester', + 'bond-builder', + 'top-down-group-scout--category', + 'top-down-group-scout--direction', + 'group-scout--whole-string', + 'group-strength-tester', + 'group-builder', + 'replacement-finder', + 'rule-scout', + 'rule-strength-tester', + 'rule-builder', + 'rule-translator', + 'bottom-up-correspondence-scout', + 'important-object-correspondence-scout', + 'correspondence-strength-tester', + 'correspondence-builder',) self.methods = {} for codeletName in knownCodeletNames: methodName = re.sub('[ -]', '_', codeletName) if methodName not in self.codeletMethodsDir: - raise NotImplementedError('Cannot find %s in codeletMethods' % methodName) + raise NotImplementedError( + 'Cannot find %s in codeletMethods' % methodName) method = getattr(codeletMethods, methodName) self.methods[methodName] = method @@ -275,7 +288,6 @@ class CodeRack(object): return None temp = formulas.Temperature scale = (100.0 - temp + 10.0) / 15.0 - # threshold = sum( [ c.urgency ** scale for c in self.codelets ] ) * random.random() urgsum = 0.0 for codelet in self.codelets: urg = codelet.urgency ** scale @@ -288,7 +300,9 @@ class CodeRack(object): logging.info('actualTemperature: %f' % formulas.actualTemperature) logging.info('Slipnet:') for node in slipnet.slipnodes: - logging.info("\tnode %s, activation: %d, buffer: %d, depth: %s" % (node.get_name(), node.activation, node.buffer, node.conceptualDepth)) + logging.info("\tnode %s, activation: %d, buffer: %d, depth: %s", + node.get_name(), node.activation, node.buffer, + node.conceptualDepth) logging.info('Coderack:') for codelet in self.codelets: logging.info('\t%s, %d' % (codelet.name, codelet.urgency)) @@ -304,7 +318,8 @@ class CodeRack(object): if not chosen: chosen = self.codelets[0] self.removeCodelet(chosen) - logging.info('chosen codelet\n\t%s, urgency = %s' % (chosen.name, chosen.urgency)) + logging.info('chosen codelet\n\t%s, urgency = %s', + chosen.name, chosen.urgency) return chosen def run(self, codelet): @@ -325,7 +340,8 @@ 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) args, varargs, varkw, defaults = inspect.getargspec(method) diff --git a/copycat/coderackPressure.py b/copycat/coderackPressure.py index 042cbc7..fc2cc99 100644 --- a/copycat/coderackPressure.py +++ b/copycat/coderackPressure.py @@ -38,7 +38,8 @@ class CoderackPressures(object): self.pressures += [CoderackPressure('Rule Codelets')] self.pressures += [CoderackPressure('Rule Translator')] self.pressures += [CoderackPressure('Bottom Up Correspondences')] - self.pressures += [CoderackPressure('Important Object Correspondences')] + self.pressures += [CoderackPressure( + 'Important Object Correspondences')] self.pressures += [CoderackPressure('Breakers')] def calculatePressures(self): @@ -121,7 +122,7 @@ class CoderackPressures(object): if codelet.pressure: codelet.pressure.codelets += [codelet] # XXX why do this if i >= 0: - codelet.pressure = self.pressures[i] # when following with this ? + codelet.pressure = self.pressures[i] # when this is next? logging.info('Add %s: %d' % (codelet.name, i)) if node: logging.info('Node: %s' % node.name) diff --git a/copycat/conceptMapping.py b/copycat/conceptMapping.py index 5699582..71dc3a5 100644 --- a/copycat/conceptMapping.py +++ b/copycat/conceptMapping.py @@ -3,8 +3,11 @@ 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())) + def __init__(self, initialDescriptionType, targetDescriptionType, + initialDescriptor, targetDescriptor, + initialObject, targetObject): + logging.info('make a map: %s-%s' % (initialDescriptionType.get_name(), + targetDescriptionType.get_name())) self.initialDescriptionType = initialDescriptionType self.targetDescriptionType = targetDescriptionType self.initialDescriptor = initialDescriptor @@ -14,7 +17,8 @@ class ConceptMapping(object): self.label = initialDescriptor.getBondCategory(targetDescriptor) def __repr__(self): - return '' % (self.__str__(), self.initialDescriptor, self.targetDescriptor) + return '' % ( + self.__str__(), self.initialDescriptor, self.targetDescriptor) def __str__(self): return self.label and self.label.name or 'anonymous' @@ -27,7 +31,7 @@ class ConceptMapping(object): return association * (1 - depth * depth) def __degreeOfAssociation(self): - #assumes the 2 descriptors are connected in the slipnet by at most 1 link + # Assumes the 2 descriptors are connected in the slipnet by <= 1 link if self.initialDescriptor == self.targetDescriptor: return 100.0 for link in self.initialDescriptor.lateralSlipLinks: @@ -43,14 +47,18 @@ class ConceptMapping(object): 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: + if self.initialDescriptor == slipnet.whole: + if self.targetDescriptor == slipnet.whole: + return False + if not self.initialObject.distinguishingDescriptor( + self.initialDescriptor): return False - if not self.initialObject.distinguishingDescriptor(self.initialDescriptor): - return False - return self.targetObject.distinguishingDescriptor(self.targetDescriptor) + return self.targetObject.distinguishingDescriptor( + self.targetDescriptor) def sameInitialType(self, other): return self.initialDescriptionType == other.initialDescriptionType @@ -68,7 +76,8 @@ class ConceptMapping(object): return self.targetDescriptor == other.targetDescriptor def sameDescriptors(self, other): - return self.sameInitialDescriptor(other) and self.sameTargetDescriptor(other) + if self.sameInitialDescriptor(other): + return self.sameTargetDescriptor(other) def sameKind(self, other): return self.sameTypes(other) and self.sameDescriptors(other) @@ -92,9 +101,9 @@ class ConceptMapping(object): # related to c or if b is related to d, and the a -> b relationship is # different from the c -> d relationship. E.g., rightmost -> leftmost # is incompatible with right -> right, since rightmost is linked - # to right, but the relationships (opposite and identity) are different. - # Notice that slipnet distances are not looked at, only slipnet links. This - # should be changed eventually. + # to right, but the relationships (opposite and identity) are different + # Notice that slipnet distances are not looked at, only slipnet links. + # This should be changed eventually. if not self.related(other): return False if not self.label or not other.label: @@ -102,18 +111,20 @@ class ConceptMapping(object): return self.label != other.label def supports(self, other): - # Concept-mappings (a -> b) and (c -> d) support each other if a is related - # to c and if b is related to d and the a -> b relationship is the same as the - # c -> d relationship. E.g., rightmost -> rightmost supports right -> right - # and leftmost -> leftmost. Notice that slipnet distances are not looked - # at, only slipnet links. This should be changed eventually. + # Concept-mappings (a -> b) and (c -> d) support each other if a is + # related to c and if b is related to d and the a -> b relationship is + # the same as the c -> d relationship. E.g., rightmost -> rightmost + # supports right -> right and leftmost -> leftmost. + # Notice that slipnet distances are not looked at, only slipnet links. + # This should be changed eventually. # If the two concept-mappings are the same, then return t. This # means that letter->group supports letter->group, even though these # concept-mappings have no label. - if self.initialDescriptor == other.initialDescriptor and self.targetDescriptor == other.targetDescriptor: - return True + if self.initialDescriptor == other.initialDescriptor: + if self.targetDescriptor == other.targetDescriptor: + return True # if the descriptors are not related return false if not self.related(other): return False @@ -122,15 +133,18 @@ class ConceptMapping(object): return self.label == other.label def relevant(self): - return self.initialDescriptionType.fully_active() and self.targetDescriptionType.fully_active() + if self.initialDescriptionType.fully_active(): + return self.targetDescriptionType.fully_active() def slippage(self): - return self.label != slipnet.sameness and self.label != slipnet.identity + if self.label != slipnet.sameness: + return self.label != slipnet.identity def symmetricVersion(self): if not self.slippage(): return self - if self.targetDescriptor.getBondCategory(self.initialDescriptor) == self.label: + bond = self.targetDescriptor.getBondCategory(self.initialDescriptor) + if bond == self.label: return self return ConceptMapping( self.targetDescriptionType, @@ -140,4 +154,3 @@ class ConceptMapping(object): self.initialObject, self.targetObject ) - diff --git a/copycat/copycat.py b/copycat/copycat.py index 3e92ea4..f814a2d 100644 --- a/copycat/copycat.py +++ b/copycat/copycat.py @@ -1,11 +1,6 @@ import logging -logging.basicConfig( - level=logging.INFO, - #format='%(asctime)s %(filename)s:%(lineno)d %(message)s', - format='%(message)s', - filename='./copycat.log', - filemode='w' -) +logging.basicConfig(level=logging.INFO, format='%(message)s', + filename='./copycat.log', filemode='w') from workspace import workspace @@ -27,10 +22,13 @@ def updateEverything(): def mainLoop(lastUpdate): temperature.tryUnclamp() result = lastUpdate - if coderack.codeletsRun - lastUpdate >= slipnet.timeStepLength or not coderack.codeletsRun: + if not coderack.codeletsRun: updateEverything() result = coderack.codeletsRun - logging.debug('Number of codelets: %d' % len(coderack.codelets)) + elif coderack.codeletsRun - lastUpdate >= slipnet.timeStepLength: + updateEverything() + result = coderack.codeletsRun + logging.debug('Number of codelets: %d', len(coderack.codelets)) coderack.chooseAndRunCodelet() return result diff --git a/copycat/correspondence.py b/copycat/correspondence.py index 7eb3440..92edc44 100644 --- a/copycat/correspondence.py +++ b/copycat/correspondence.py @@ -4,7 +4,8 @@ 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 @@ -16,13 +17,15 @@ 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()] 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 @@ -64,7 +67,8 @@ 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): if not other: @@ -96,22 +100,27 @@ class Correspondence(WorkspaceStructure): def support(self): from letter import Letter - if isinstance(self.objectFromInitial, Letter) and self.objectFromInitial.spansString(): - return 100.0 - 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)]) + if isinstance(self.objectFromInitial, Letter): + if self.objectFromInitial.spansString(): + return 100.0 + if isinstance(self.objectFromTarget, Letter): + if self.objectFromTarget.spansString(): + return 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): - """A function of how many conceptMappings there are, their strength and how well they cohere""" - relevantDistinguishingMappings = self.relevantDistinguishingConceptMappings() - numberOfConceptMappings = len(relevantDistinguishingMappings) + """A function of how many concept mappings there are + + Also considered: their strength and how well they cohere""" + distinguishingMappings = self.relevantDistinguishingConceptMappings() + numberOfConceptMappings = len(distinguishingMappings) if numberOfConceptMappings < 1: self.internalStrength = 0.0 return - totalStrength = sum([m.strength() for m in relevantDistinguishingMappings]) + totalStrength = sum([m.strength() for m in distinguishingMappings]) averageStrength = totalStrength / numberOfConceptMappings if numberOfConceptMappings == 1.0: numberOfConceptMappingsFactor = 0.8 @@ -123,14 +132,15 @@ class Correspondence(WorkspaceStructure): internalCoherenceFactor = 2.5 else: internalCoherenceFactor = 1.0 - internalStrength = averageStrength * internalCoherenceFactor * numberOfConceptMappingsFactor + internalStrength = (averageStrength * internalCoherenceFactor * + numberOfConceptMappingsFactor) self.internalStrength = min(internalStrength, 100.0) def updateExternalStrength(self): self.externalStrength = self.support() def internallyCoherent(self): - """Whether any pair of relevant distinguishing mappings support each other""" + """Whether any pair of distinguishing mappings support each other""" mappings = self.relevantDistinguishingConceptMappings() for i in range(0, len(mappings)): for j in range(0, len(mappings)): @@ -145,9 +155,10 @@ class Correspondence(WorkspaceStructure): return mappings def reflexive(self): - if not self.objectFromInitial.correspondence: + initial = self.objectFromInitial + if not initial.correspondence: return False - if self.objectFromInitial.correspondence.objectFromTarget == self.objectFromTarget: + if initial.correspondence.objectFromTarget == self.objectFromTarget: return True return False @@ -165,17 +176,19 @@ class Correspondence(WorkspaceStructure): if mapping.slippage(): self.accessoryConceptMappings += [mapping.symmetricVersion()] from group import Group - if isinstance(self.objectFromInitial, Group) and isinstance(self.objectFromTarget, Group): - bondMappings = getMappings( - self.objectFromInitial, - self.objectFromTarget, - self.objectFromInitial.bondDescriptions, - self.objectFromTarget.bondDescriptions - ) - for mapping in bondMappings: - self.accessoryConceptMappings += [mapping] - if mapping.slippage(): - self.accessoryConceptMappings += [mapping.symmetricVersion()] + if isinstance(self.objectFromInitial, Group): + if isinstance(self.objectFromTarget, Group): + bondMappings = getMappings( + self.objectFromInitial, + self.objectFromTarget, + self.objectFromInitial.bondDescriptions, + self.objectFromTarget.bondDescriptions + ) + for mapping in bondMappings: + self.accessoryConceptMappings += [mapping] + if mapping.slippage(): + self.accessoryConceptMappings += [ + mapping.symmetricVersion()] for mapping in self.conceptMappings: if mapping.label: mapping.label.activation = 100.0 diff --git a/copycat/description.py b/copycat/description.py index 5d9ef40..fe95d50 100644 --- a/copycat/description.py +++ b/copycat/description.py @@ -26,25 +26,27 @@ class Description(WorkspaceStructure): self.internalStrength = self.descriptor.conceptualDepth def updateExternalStrength(self): - self.externalStrength = (self.localSupport() + self.descriptionType.activation) / 2 + self.externalStrength = (self.localSupport() + + self.descriptionType.activation) / 2 def localSupport(self): from workspace import workspace - supporters = 0 # number of objects in the string with a descriptionType like self + described_like_self = 0 for other in workspace.otherObjects(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 + if self.object.isWithin(other) or other.isWithin(self.object): + continue + for description in other.descriptions: + if description.descriptionType == self.descriptionType: + described_like_self += 1 results = {0: 0.0, 1: 20.0, 2: 60.0, 3: 90.0} - if supporters in results: - return results[supporters] + if described_like_self in results: + return results[described_like_self] return 100.0 def build(self): self.descriptionType.buffer = 100.0 self.descriptor.buffer = 100.0 - if not self.object.hasDescription(self.descriptor): + if not self.object.described(self.descriptor): logging.info('Add %s to descriptions' % self) self.object.descriptions += [self] diff --git a/copycat/formulas.py b/copycat/formulas.py index b3fb011..9da8bdb 100644 --- a/copycat/formulas.py +++ b/copycat/formulas.py @@ -14,12 +14,12 @@ def selectListPosition(probabilities): stopPosition = total * r #logging.info('stopPosition: %s' % stopPosition) total = 0 - index = 0 + i = 0 for probability in probabilities: total += probability if total > stopPosition: - return index - index += 1 + return i + i += 1 return 0 @@ -75,9 +75,9 @@ def chooseObjectFromList(objects, attribute): probability = temperatureAdjustedValue(value) logging.info('Object: %s, value: %d, probability: %d' % (object, value, probability)) probabilities += [probability] - index = selectListPosition(probabilities) - logging.info("Selected: %d" % index) - return objects[index] + i = selectListPosition(probabilities) + logging.info("Selected: %d" % i) + return objects[i] def chooseRelevantDescriptionByActivation(workspaceObject): @@ -85,8 +85,8 @@ def chooseRelevantDescriptionByActivation(workspaceObject): if not descriptions: return None activations = [description.descriptor.activation for description in descriptions] - index = selectListPosition(activations) - return descriptions[index] + i = selectListPosition(activations) + return descriptions[i] def similarPropertyLinks(slip_node): diff --git a/copycat/group.py b/copycat/group.py index 03ccb94..6849521 100644 --- a/copycat/group.py +++ b/copycat/group.py @@ -19,10 +19,10 @@ class Group(WorkspaceObject): leftObject = objectList[0] rightObject = objectList[-1] - self.leftStringPosition = leftObject.leftStringPosition - self.leftmost = self.leftStringPosition == 1 - self.rightStringPosition = rightObject.rightStringPosition - self.rightmost = self.rightStringPosition == len(self.string) + self.leftIndex = leftObject.leftIndex + self.leftmost = self.leftIndex == 1 + self.rightIndex = rightObject.rightIndex + self.rightmost = self.rightIndex == len(self.string) self.descriptions = [] self.bondDescriptions = [] @@ -54,9 +54,9 @@ class Group(WorkspaceObject): self.addDescription(slipnet.directionCategory, self.directionCategory) if self.spansString(): self.addDescription(slipnet.stringPositionCategory, slipnet.whole) - elif self.leftStringPosition == 1: + elif self.leftIndex == 1: self.addDescription(slipnet.stringPositionCategory, slipnet.leftmost) - elif self.rightStringPosition == self.string.length: + elif self.rightIndex == self.string.length: self.addDescription(slipnet.stringPositionCategory, slipnet.rightmost) elif self.middleObject(): self.addDescription(slipnet.stringPositionCategory, slipnet.middle) @@ -70,8 +70,8 @@ class Group(WorkspaceObject): def __str__(self): s = self.string.__str__() - l = self.leftStringPosition - 1 - r = self.rightStringPosition + l = self.leftIndex - 1 + r = self.rightIndex return 'group[%d:%d] == %s' % (l, r - 1, s[l:r]) def getIncompatibleGroups(self): @@ -190,7 +190,7 @@ class Group(WorkspaceObject): count = 0 for objekt in self.string.objects: if isinstance(objekt, Group): - if objekt.rightStringPosition < self.leftStringPosition or objekt.leftStringPosition > self.rightStringPosition: + if objekt.rightIndex < self.leftIndex or objekt.leftIndex > self.rightIndex: if objekt.groupCategory == self.groupCategory and objekt.directionCategory == self.directionCategory: count += 1 return count @@ -201,9 +201,9 @@ class Group(WorkspaceObject): return 100.0 * numberOfSupporters / halfLength def sameGroup(self, other): - if self.leftStringPosition != other.leftStringPosition: + if self.leftIndex != other.leftIndex: return False - if self.rightStringPosition != other.rightStringPosition: + if self.rightIndex != other.rightIndex: return False if self.groupCategory != other.groupCategory: return False diff --git a/copycat/letter.py b/copycat/letter.py index a65c1da..1e6e445 100644 --- a/copycat/letter.py +++ b/copycat/letter.py @@ -8,10 +8,10 @@ class Letter(WorkspaceObject): from workspace import workspace workspace.objects += [self] string.objects += [self] - self.leftStringPosition = position - self.leftmost = self.leftStringPosition == 1 - self.rightStringPosition = position - self.rightmost = self.rightStringPosition == length + self.leftIndex = position + self.leftmost = self.leftIndex == 1 + self.rightIndex = position + self.rightmost = self.rightIndex == length def describe(self, position, length): if length == 1: @@ -29,9 +29,9 @@ class Letter(WorkspaceObject): def __str__(self): if not self.string: return '' - i = self.leftStringPosition - 1 + i = self.leftIndex - 1 if len(self.string) <= i: - raise ValueError('len(self.string) <= self.leftStringPosition :: %d <= %d' % (len(self.string), self.leftStringPosition)) + raise ValueError('len(self.string) <= self.leftIndex :: %d <= %d' % (len(self.string), self.leftIndex)) return self.string[i] def distinguishingDescriptor(self, descriptor): diff --git a/copycat/rule.py b/copycat/rule.py index 6bbbf64..4e792db 100644 --- a/copycat/rule.py +++ b/copycat/rule.py @@ -15,7 +15,9 @@ class Rule(WorkspaceStructure): def __str__(self): if not self.facet: return 'Empty rule' - return 'replace %s of %s %s by %s' % (self.facet.name, self.descriptor.name, self.category.name, self.relation.name) + return 'replace %s of %s %s by %s' % ( + self.facet.name, self.descriptor.name, + self.category.name, self.relation.name) def updateExternalStrength(self): self.externalStrength = self.internalStrength @@ -24,7 +26,8 @@ class Rule(WorkspaceStructure): 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 @@ -36,13 +39,17 @@ class Rule(WorkspaceStructure): targetObject = changed.correspondence.objectFromTarget slippages = workspace.slippages() slipnode = self.descriptor.applySlippages(slippages) - if not targetObject.hasDescription(slipnode): + if not targetObject.described(slipnode): 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)) + conceptual_height = (100.0 - self.descriptor.conceptualDepth) / 10.0 + sharedDescriptorWeight = conceptual_height ** 1.4 + depthDifference = 100.0 - abs(self.descriptor.conceptualDepth - + self.relation.conceptualDepth) + weights = ((depthDifference, 12), + (averageDepth, 18), + (sharedDescriptorTerm, sharedDescriptorWeight)) self.internalStrength = weightedAverage(weights) if self.internalStrength > 100.0: self.internalStrength = 100.0 @@ -81,9 +88,8 @@ class Rule(WorkspaceStructure): 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]): - return False - return True + return bool([m for m in correspondence.conceptMappings + if m.initialDescriptor == self.descriptor]) def __changeString(self, string): # applies the changes to self string ie. successor @@ -114,17 +120,18 @@ class Rule(WorkspaceStructure): # generate the final string self.finalAnswer = workspace.targetString changeds = [o for o in workspace.target.objects if - o.hasDescription(self.descriptor) and - o.hasDescription(self.category)] + o.described(self.descriptor) and + o.described(self.category)] changed = changeds and changeds[0] or None logging.debug('changed object = %s' % changed) if changed: - left = changed.leftStringPosition + left = changed.leftIndex startString = '' if left > 1: startString = self.finalAnswer[0: left - 1] - right = changed.rightStringPosition - middleString = self.__changeString(self.finalAnswer[left - 1: right]) + right = changed.rightIndex + middleString = self.__changeString( + self.finalAnswer[left - 1: right]) if not middleString: return False endString = '' diff --git a/copycat/slipnet.py b/copycat/slipnet.py index 4de8f59..6ace0c5 100644 --- a/copycat/slipnet.py +++ b/copycat/slipnet.py @@ -38,8 +38,6 @@ class SlipNet(object): if self.numberOfUpdates == 50: [node.unclamp() for node in self.initiallyClampedSlipnodes] [node.update() for node in self.slipnodes] - # Note - spreadActivation() affects more than one node, so the following - # cannot go in a general "for node" loop with the other node actions for node in self.slipnodes: node.spread_activation() for node in self.slipnodes: @@ -103,10 +101,13 @@ class SlipNet(object): # categories self.letterCategory = self.__addNode('letterCategory', 30.0) - self.stringPositionCategory = self.__addNode('stringPositionCategory', 70.0) + self.stringPositionCategory = self.__addNode( + 'stringPositionCategory', 70.0) self.stringPositionCategory.codelets += ['top-down-description-scout'] - self.alphabeticPositionCategory = self.__addNode('alphabeticPositionCategory', 80.0) - self.alphabeticPositionCategory.codelets += ['top-down-description-scout'] + self.alphabeticPositionCategory = self.__addNode( + 'alphabeticPositionCategory', 80.0) + self.alphabeticPositionCategory.codelets += [ + 'top-down-description-scout'] self.directionCategory = self.__addNode('directionCategory', 70.0) self.bondCategory = self.__addNode('bondCategory', 80.0) self.groupCategory = self.__addNode('groupCategory', 80.0) @@ -151,14 +152,18 @@ class SlipNet(object): self.__addInstanceLink(self.objectCategory, self.letter, 100.0) self.__addInstanceLink(self.objectCategory, self.group, 100.0) # string positions - self.__addInstanceLink(self.stringPositionCategory, self.leftmost, 100.0) - self.__addInstanceLink(self.stringPositionCategory, self.rightmost, 100.0) + self.__addInstanceLink( + self.stringPositionCategory, self.leftmost, 100.0) + self.__addInstanceLink( + self.stringPositionCategory, self.rightmost, 100.0) self.__addInstanceLink(self.stringPositionCategory, self.middle, 100.0) self.__addInstanceLink(self.stringPositionCategory, self.single, 100.0) self.__addInstanceLink(self.stringPositionCategory, self.whole, 100.0) # alphabetic positions - self.__addInstanceLink(self.alphabeticPositionCategory, self.first, 100.0) - self.__addInstanceLink(self.alphabeticPositionCategory, self.last, 100.0) + self.__addInstanceLink( + self.alphabeticPositionCategory, self.first, 100.0) + self.__addInstanceLink( + self.alphabeticPositionCategory, self.last, 100.0) # direction categories self.__addInstanceLink(self.directionCategory, self.left, 100.0) self.__addInstanceLink(self.directionCategory, self.right, 100.0) @@ -167,17 +172,25 @@ class SlipNet(object): self.__addInstanceLink(self.bondCategory, self.successor, 100.0) self.__addInstanceLink(self.bondCategory, self.sameness, 100.0) # group categories - self.__addInstanceLink(self.groupCategory, self.predecessorGroup, 100.0) + self.__addInstanceLink( + self.groupCategory, self.predecessorGroup, 100.0) self.__addInstanceLink(self.groupCategory, self.successorGroup, 100.0) self.__addInstanceLink(self.groupCategory, self.samenessGroup, 100.0) # link bonds to their groups - self.__addNonSlipLink(self.sameness, self.samenessGroup, label=self.groupCategory, length=30.0) - self.__addNonSlipLink(self.successor, self.successorGroup, label=self.groupCategory, length=60.0) - self.__addNonSlipLink(self.predecessor, self.predecessorGroup, label=self.groupCategory, length=60.0) + self.__addNonSlipLink( + self.sameness, self.samenessGroup, label=self.groupCategory, + length=30.0) + self.__addNonSlipLink(self.successor, self.successorGroup, + label=self.groupCategory, length=60.0) + self.__addNonSlipLink(self.predecessor, self.predecessorGroup, + label=self.groupCategory, length=60.0) # link bond groups to their bonds - self.__addNonSlipLink(self.samenessGroup, self.sameness, label=self.bondCategory, length=90.0) - self.__addNonSlipLink(self.successorGroup, self.successor, label=self.bondCategory, length=90.0) - self.__addNonSlipLink(self.predecessorGroup, self.predecessor, label=self.bondCategory, length=90.0) + self.__addNonSlipLink(self.samenessGroup, self.sameness, + label=self.bondCategory, length=90.0) + self.__addNonSlipLink(self.successorGroup, self.successor, + label=self.bondCategory, length=90.0) + self.__addNonSlipLink(self.predecessorGroup, self.predecessor, + label=self.bondCategory, length=90.0) # bond facets self.__addInstanceLink(self.bondFacet, self.letterCategory, 100.0) self.__addInstanceLink(self.bondFacet, self.length, 100.0) diff --git a/copycat/slipnode.py b/copycat/slipnode.py index 6c3db17..a1ea6d3 100644 --- a/copycat/slipnode.py +++ b/copycat/slipnode.py @@ -1,6 +1,6 @@ import math import logging -import random +from random import random def full_activation(): @@ -48,6 +48,9 @@ class Slipnode(object): def unclamp(self): self.clamped = False + def unclamped(self): + return not self.clamped + def setConceptualDepth(self, depth): logging.info('set depth to %s for %s' % (depth, self.name)) self.conceptualDepth = depth @@ -60,7 +63,8 @@ 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 + float_margin = 0.00001 + return self.activation > full_activation() - float_margin def activate_fully(self): """Make this node fully active""" @@ -115,7 +119,8 @@ class Slipnode(object): if relation == slipnet.identity: return self - destinations = [l.destination for l in self.outgoingLinks if l.label == relation] + destinations = [l.destination + for l in self.outgoingLinks if l.label == relation] if destinations: return destinations[0] node = None @@ -147,15 +152,21 @@ class Slipnode(object): [link.spread_activation() for link in self.outgoingLinks] def addBuffer(self): - if not self.clamped: + if self.unclamped(): self.activation += self.buffer self.activation = min(self.activation, 100) self.activation = max(self.activation, 0) - def jump(self): + def can_jump(): + if self.activation <= jump_threshold(): + return False + if self.clamped: + return False value = (self.activation / 100.0) ** 3 - #logging.info('jumping for %s at activation %s' % (self.name,self.activation)) - if self.activation > jump_threshold() and random.random() < value and not self.clamped: + return random() < value + + def jump(self): + if self.can_jump(): self.activate_fully() def get_name(self): diff --git a/copycat/temperature.py b/copycat/temperature.py index b46c63d..d144301 100644 --- a/copycat/temperature.py +++ b/copycat/temperature.py @@ -8,17 +8,17 @@ class Temperature(object): self.clampTime = 30 def update(self, value): - logging.debug('update to %s' % value) + logging.debug('update to %s', value) self.value = value def tryUnclamp(self): from coderack import coderack if self.clamped and coderack.codeletsRun >= self.clampTime: - logging.info('unclamp temperature at %d' % coderack.codeletsRun) + logging.info('unclamp temperature at %d', coderack.codeletsRun) self.clamped = False def log(self): - logging.debug('temperature.value: %f' % self.value) + logging.debug('temperature.value: %f', self.value) temperature = Temperature() diff --git a/copycat/unready.py b/copycat/unready.py deleted file mode 100644 index d472e23..0000000 --- a/copycat/unready.py +++ /dev/null @@ -1,2 +0,0 @@ -from exceptions import NotImplementedError -raise NotImplementedError diff --git a/copycat/workspace.py b/copycat/workspace.py index b17d9d7..d79da46 100644 --- a/copycat/workspace.py +++ b/copycat/workspace.py @@ -5,6 +5,13 @@ from workspaceString import WorkspaceString unknownAnswer = '?' +def __adjustUnhappiness(values): + result = sum(values) / 2 + if result > 100.0: + result = 100.0 + return result + + class Workspace(object): def __init__(self): #logging.debug('workspace.__init__()') @@ -15,7 +22,8 @@ class Workspace(object): self.interStringUnhappiness = 0.0 def __repr__(self): - return '' % (self.initialString, self.modifiedString, self.targetString) + return '' % ( + self.initialString, self.modifiedString, self.targetString) def setStrings(self, initial, modified, target): self.targetString = target @@ -33,16 +41,15 @@ class Workspace(object): self.modified = WorkspaceString(self.modifiedString) self.target = WorkspaceString(self.targetString) - def __adjustUnhappiness(self, values): - result = sum(values) / 2 - if result > 100.0: - result = 100.0 - return result - def assessUnhappiness(self): - self.intraStringUnhappiness = self.__adjustUnhappiness([o.relativeImportance * o.intraStringUnhappiness for o in self.objects]) - self.interStringUnhappiness = self.__adjustUnhappiness([o.relativeImportance * o.interStringUnhappiness for o in self.objects]) - self.totalUnhappiness = self.__adjustUnhappiness([o.relativeImportance * o.totalUnhappiness for o in self.objects]) + self.intraStringUnhappiness = __adjustUnhappiness([ + o.relativeImportance * o.intraStringUnhappiness + for o in self.objects]) + self.interStringUnhappiness = __adjustUnhappiness([ + o.relativeImportance * o.interStringUnhappiness + for o in self.objects]) + self.totalUnhappiness = __adjustUnhappiness([ + o.relativeImportance * o.totalUnhappiness for o in self.objects]) def assessTemperature(self): self.calculateIntraStringUnhappiness() @@ -50,20 +57,23 @@ class Workspace(object): self.calculateTotalUnhappiness() def calculateIntraStringUnhappiness(self): - values = [o.relativeImportance * o.intraStringUnhappiness for o in self.objects] + values = [o.relativeImportance * o.intraStringUnhappiness + for o in self.objects] value = sum(values) / 2.0 self.intraStringUnhappiness = min(value, 100.0) def calculateInterStringUnhappiness(self): - values = [o.relativeImportance * o.interStringUnhappiness for o in self.objects] + values = [o.relativeImportance * o.interStringUnhappiness + for o in self.objects] value = sum(values) / 2.0 self.interStringUnhappiness = min(value, 100.0) def calculateTotalUnhappiness(self): for o in self.objects: - logging.info("object: %s, totalUnhappiness: %d, relativeImportance: %d" % ( - o, o.totalUnhappiness, o.relativeImportance * 1000)) - values = [o.relativeImportance * o.totalUnhappiness for o in self.objects] + logging.info("%s, totalUnhappiness: %d, relativeImportance: %d", + o, o.totalUnhappiness, o.relativeImportance * 1000) + values = [o.relativeImportance * o.totalUnhappiness + for o in self.objects] value = sum(values) / 2.0 self.totalUnhappiness = min(value, 100.0) @@ -81,12 +91,15 @@ class Workspace(object): return [o for o in self.objects if o != anObject] def numberOfUnrelatedObjects(self): - """A list of all objects in the workspace that have at least one bond slot open.""" - objects = [o for o in self.objects if o.string == self.initial or o.string == self.target] + """A list of all objects in the workspace with >= 1 open bond slots""" + objects = [o for o in self.objects + if o.string == self.initial or o.string == self.target] #print 'A: %d' % len(objects) objects = [o for o in objects if not o.spansString()] #print 'B: %d' % len(objects) - objects = [o for o in objects if (not o.leftBond and not o.leftmost) or (not o.rightBond and not o.rightmost)] + objects = [o for o in objects + if (not o.leftBond and not o.leftmost) or + (not o.rightBond and not o.rightmost)] #print 'C: %d' % len(objects) #objects = [ o for o in objects if ] #print 'D: %d' % len(objects) @@ -94,22 +107,25 @@ class Workspace(object): def numberOfUngroupedObjects(self): """A list of all objects in the workspace that have no group.""" - objects = [o for o in self.objects if o.string == self.initial or o.string == self.target] + objects = [o for o in self.objects if + o.string == self.initial or o.string == self.target] objects = [o for o in objects if not o.spansString()] objects = [o for o in objects if not o.group] return len(objects) def numberOfUnreplacedObjects(self): - """A list of all objects in the inital string that have not been replaced.""" + """A list of all unreplaced objects in the inital string""" from letter import Letter - objects = [o for o in self.objects if o.string == self.initial and isinstance(o, Letter)] + objects = [o for o in self.objects + if o.string == self.initial and isinstance(o, Letter)] objects = [o for o in objects if not o.replacement] return len(objects) def numberOfUncorrespondingObjects(self): - """A list of all objects in the inital string that have not been replaced.""" - objects = [o for o in self.objects if o.string == self.initial or o.string == self.target] + """A list of all uncorresponded objects in the inital string""" + objects = [o for o in self.objects + if o.string == self.initial or o.string == self.target] objects = [o for o in objects if not o.correspondence] return len(objects) @@ -127,7 +143,8 @@ class Workspace(object): def slippages(self): result = [] if self.changedObject and self.changedObject.correspondence: - result = [m for m in self.changedObject.correspondence.conceptMappings] + result = [m for m in + self.changedObject.correspondence.conceptMappings] for objekt in workspace.initial.objects: if objekt.correspondence: for mapping in objekt.correspondence.slippages(): @@ -148,9 +165,7 @@ class Workspace(object): def buildDescriptions(self, objekt): for description in objekt.descriptions: description.descriptionType.buffer = 100.0 - #logging.info("Set buffer to 100 for " + description.descriptionType.get_name()); description.descriptor.buffer = 100.0 - #logging.info("Set buffer to 100 for " + description.descriptor.get_name()); if description not in self.structures: self.structures += [description] diff --git a/copycat/workspaceFormulas.py b/copycat/workspaceFormulas.py index e38e590..799c7f1 100644 --- a/copycat/workspaceFormulas.py +++ b/copycat/workspaceFormulas.py @@ -50,9 +50,9 @@ def chooseNeighbour(source): for objekt in workspace.objects: if objekt.string != source.string: continue - if objekt.leftStringPosition == source.rightStringPosition + 1: + if objekt.leftIndex == source.rightIndex + 1: objects += [objekt] - elif source.leftStringPosition == objekt.rightStringPosition + 1: + elif source.leftIndex == objekt.rightIndex + 1: objects += [objekt] return formulas.chooseObjectFromList(objects, "intraStringSalience") @@ -69,7 +69,7 @@ def __chooseLeftNeighbor(source): objects = [] for o in workspace.objects: if o.string == source.string: - if source.leftStringPosition == o.rightStringPosition + 1: + if source.leftIndex == o.rightIndex + 1: logging.info('%s is on left of %s' % (o, source)) objects += [o] else: @@ -81,7 +81,7 @@ def __chooseLeftNeighbor(source): def __chooseRightNeighbor(source): objects = [o for o in workspace.objects if o.string == source.string and - o.leftStringPosition == source.rightStringPosition + 1 + o.leftIndex == source.rightIndex + 1 ] return formulas.chooseObjectFromList(objects, 'intraStringSalience') diff --git a/copycat/workspaceObject.py b/copycat/workspaceObject.py index fe3cec2..59a1335 100644 --- a/copycat/workspaceObject.py +++ b/copycat/workspaceObject.py @@ -26,8 +26,8 @@ class WorkspaceObject(WorkspaceStructure): self.newAnswerLetter = False self.name = '' self.replacement = None - self.rightStringPosition = 0 - self.leftStringPosition = 0 + self.rightIndex = 0 + self.leftIndex = 0 self.leftmost = False self.rightmost = False self.intraStringSalience = 0.0 @@ -49,19 +49,14 @@ class WorkspaceObject(WorkspaceStructure): self.descriptions += [description] 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 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) - #print '%d addDescriptions 4 %s ' % (len(descriptions),description) + self.addDescription(description.descriptionType, + description.descriptor) else: logging.info("Won't add it") - #print '%d added, have %d ' % (len(descriptions),len(self.descriptions)) from workspace import workspace workspace.buildDescriptions(self) @@ -113,17 +108,25 @@ 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.totalSalience = (self.intraStringSalience + self.interStringSalience) / 2.0 + 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): - return self.leftStringPosition >= other.leftStringPosition and self.rightStringPosition <= other.rightStringPosition + return (self.leftIndex >= other.leftIndex and + self.rightIndex <= other.rightIndex) 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): return [] @@ -134,14 +137,15 @@ class WorkspaceObject(WorkspaceStructure): from group import Group for link in descriptionType.instanceLinks: node = link.destination - if node == slipnet.first and self.hasDescription(slipnet.letters[0]): + if node == slipnet.first and self.described(slipnet.letters[0]): descriptions += [node] - if node == slipnet.last and self.hasDescription(slipnet.letters[-1]): + if node == slipnet.last and self.described(slipnet.letters[-1]): 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): + if len(self.objectList) == i: + descriptions += [node] i += 1 if node == slipnet.middle and self.middleObject(): descriptions += [node] @@ -155,26 +159,27 @@ class WorkspaceObject(WorkspaceStructure): soughtType = sought.descriptionType soughtDescriptor = sought.descriptor for d in self.descriptions: - if soughtType == d.descriptionType and soughtDescriptor == d.descriptor: - return True + if soughtType == d.descriptionType: + if soughtDescriptor == d.descriptor: + return True return False - def hasDescription(self, slipnode): - return [d for d in self.descriptions if d.descriptor == slipnode] and True or False + def described(self, slipnode): + return bool([d for d in self.descriptions if d.descriptor == slipnode]) def middleObject(self): # XXX only works if string is 3 chars long # as we have access to the string, why not just " == len / 2" ? objectOnMyRightIsRightmost = objectOnMyLeftIsLeftmost = False for objekt in self.string.objects: - if objekt.leftmost and objekt.rightStringPosition == self.leftStringPosition - 1: + if objekt.leftmost and objekt.rightIndex == self.leftIndex - 1: objectOnMyLeftIsLeftmost = True - if objekt.rightmost and objekt.leftStringPosition == self.rightStringPosition + 1: + if objekt.rightmost and objekt.leftIndex == self.rightIndex + 1: objectOnMyRightIsRightmost = True return objectOnMyRightIsRightmost and objectOnMyLeftIsLeftmost def distinguishingDescriptor(self, descriptor): - """Whether no other object of the same type (ie. letter or group) has the same descriptor""" + """Whether no other object of the same type has the same descriptor""" if descriptor == slipnet.letter: return False if descriptor == slipnet.group: @@ -185,12 +190,15 @@ 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): - """The description attached to this object of the specified description type.""" + """The description attached to this object of the 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: @@ -198,7 +206,7 @@ class WorkspaceObject(WorkspaceStructure): return descriptor def getDescriptionType(self, sought_description): - """The description_type attached to this object of the specified description""" + """The description_type attached to this object of that description""" for description in self.descriptions: if description.descriptor == sought_description: return description.descriptionType @@ -206,21 +214,22 @@ class WorkspaceObject(WorkspaceStructure): return description def getCommonGroups(self, other): - return [o for o in self.string.objects if self.isWithin(o) and other.isWithin(o)] + return [o for o in self.string.objects + if self.isWithin(o) and other.isWithin(o)] def letterDistance(self, other): - if other.leftStringPosition > self.rightStringPosition: - return other.leftStringPosition - self.rightStringPosition - if self.leftStringPosition > other.rightStringPosition: - return self.leftStringPosition - other.rightStringPosition + if other.leftIndex > self.rightIndex: + return other.leftIndex - self.rightIndex + if self.leftIndex > other.rightIndex: + return self.leftIndex - other.rightIndex return 0 def letterSpan(self): - return self.rightStringPosition - self.leftStringPosition + 1 + return self.rightIndex - self.leftIndex + 1 def beside(self, other): if self.string != other.string: return False - if self.leftStringPosition == other.rightStringPosition + 1: + if self.leftIndex == other.rightIndex + 1: return True - return other.leftStringPosition == self.rightStringPosition + 1 + return other.leftIndex == self.rightIndex + 1 diff --git a/copycat/workspaceString.py b/copycat/workspaceString.py index 3731a13..4157f14 100644 --- a/copycat/workspaceString.py +++ b/copycat/workspaceString.py @@ -21,7 +21,8 @@ class WorkspaceString(object): letter = Letter(self, position + 1, self.length) letter.workspaceString = self letter.addDescription(slipnet.objectCategory, slipnet.letter) - letter.addDescription(slipnet.letterCategory, slipnet.letters[value]) + letter.addDescription(slipnet.letterCategory, + slipnet.letters[value]) letter.describe(position + 1, self.length) workspace.buildDescriptions(letter) self.letters += [letter] @@ -31,7 +32,8 @@ class WorkspaceString(object): return '' % self.string def __str__(self): - return '%s with %d letters, %d objects, %d bonds' % (self.string, len(self.letters), len(self.objects), len(self.bonds)) + return '%s with %d letters, %d objects, %d bonds' % ( + self.string, len(self.letters), len(self.objects), len(self.bonds)) def log(self, heading): s = '%s: %s - ' % (heading, self) @@ -60,8 +62,9 @@ class WorkspaceString(object): o.relativeImportance = 0.0 else: for o in self.objects: - logging.info('object: %s, relative: %d = raw: %d / total: %d' % ( - o, o.relativeImportance * 1000, o.rawImportance, total)) + logging.info('object: %s, relative: %d = raw: %d / total: %d', + 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 7b2546c..2970407 100644 --- a/copycat/workspaceStructure.py +++ b/copycat/workspaceStructure.py @@ -1,6 +1,11 @@ import formulas +def abstract_call(objekt, name): + raise NotImplementedError('call of abstract method: %s.%s()' % + (objekt.__class__.__name__, name)) + + class WorkspaceStructure(object): def __init__(self): self.string = None @@ -14,8 +19,9 @@ class WorkspaceStructure(object): self.updateTotalStrength() def updateTotalStrength(self): - """Recalculate the total strength based on internal and external strengths""" - weights = ((self.internalStrength, self.internalStrength), (self.externalStrength, 100 - self.internalStrength)) + """Recalculate the strength from internal and external strengths""" + weights = ((self.internalStrength, self.internalStrength), + (self.externalStrength, 100 - self.internalStrength)) strength = formulas.weightedAverage(weights) self.totalStrength = strength @@ -25,14 +31,14 @@ class WorkspaceStructure(object): def updateInternalStrength(self): """How internally cohesive the structure is""" - raise NotImplementedError('call of abstract method: WorkspaceStructure.updateInternalStrength()') + abstract_call(self, 'updateInternalStrength') def updateExternalStrength(self): - raise NotImplementedError('call of abstract method: WorkspaceStructure.updateExternalStrength()') + abstract_call(self, '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()') + abstract_call(self, 'break_the_structure')