import utils, logging from workspace import workspace from workspaceObject import WorkspaceObject from slipnet import slipnet import formulas class Group(WorkspaceObject): def __init__(self,string,groupCategory,directionCategory,facet,objectList,bondList): WorkspaceObject.__init__(self,string) self.groupCategory = groupCategory self.directionCategory = directionCategory self.facet = facet self.objectList = objectList self.bondList = bondList self.bondCategory = self.groupCategory.getRelatedNode(slipnet.bondCategory) 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.descriptions = [] self.bondDescriptions = [] self.extrinsicDescriptions = [] self.outgoingBonds = [] self.incomingBonds = [] self.bonds = [] self.leftBond = None self.rightBond = None self.correspondence = None self.changed = False self.newAnswerLetter = False self.clampSalience = False self.name = '' from description import Description if self.bondList and len(self.bondList): firstFacet = self.bondList[0].facet self.addBondDescription(Description(self, slipnet.bondFacet, firstFacet)) self.addBondDescription(Description(self, slipnet.bondCategory, self.bondCategory)) self.addDescription(slipnet.objectCategory, slipnet.group) self.addDescription(slipnet.groupCategory, self.groupCategory) if not self.directionCategory: # sameness group - find letterCategory letter = self.objectList[0].getDescriptor(self.facet) self.addDescription(self.facet, letter) if self.directionCategory: self.addDescription(slipnet.directionCategory, self.directionCategory) if self.spansString(): self.addDescription(slipnet.stringPositionCategory, slipnet.whole) elif self.leftStringPosition == 1: self.addDescription(slipnet.stringPositionCategory, slipnet.leftmost) elif self.rightStringPosition == self.string.length: self.addDescription(slipnet.stringPositionCategory, slipnet.rightmost) elif self.middleObject(): self.addDescription(slipnet.stringPositionCategory, slipnet.middle) #check whether or not to add length description category probability = self.lengthDescriptionProbability() if utils.random() < probability: length = len(self.objectList) if length < 6: self.addDescription(slipnet.length, slipnet.numbers[length - 1]) def __str__(self): s = self.string.__str__() l = self.leftStringPosition - 1 r = self.rightStringPosition return 'group[%d:%d] == %s' % ( l, r - 1, s[l: r ]) def getIncompatibleGroups(self): result = [] for objekt in self.objectList: while objekt.group: result += [ objekt.group ] objekt = objekt.group return result def addBondDescription(self,description): self.bondDescriptions += [ description ] def singleLetterGroupProbability(self): numberOfSupporters = self.numberOfLocalSupportingGroups() if not numberOfSupporters: return 0.0 if numberOfSupporters == 1: exp = 4.0 elif numberOfSupporters == 2: exp = 2.0 else: exp = 1.0 support = self.localSupport() / 100.0 activation = slipnet.length.activation / 100.0 supportedActivation = (support * activation) ** exp return formulas.temperatureAdjustedProbability(supportedActivation) def flippedVersion(self): flippedBonds = [ b.flippedversion() for b in self.bondList ] flippedGroup = self.groupCategory.getRelatedNode(slipnet.flipped) flippedDirection = self.directionCategory.getRelatedNode(slipnet.flipped) return Group(self.string, flippedGroup, flippedDirection, self.facet, self.objectList, flippedBonds) def buildGroup(self): workspace.objects += [ self ] workspace.structures += [ self ] self.string.objects += [ self ] for objekt in self.objectList: objekt.group = self workspace.buildDescriptions(self) self.activateDescriptions() def activateDescriptions(self): for description in self.descriptions: logging.info('Activate: %s' % description) description.descriptor.buffer = 100.0 def lengthDescriptionProbability(self): length = len(self.objectList) if length > 5: return 0.0 cubedlength = length ** 3 fred = cubedlength * (100.0 - slipnet.length.activation) / 100.0 probability = 0.5 ** fred value = formulas.temperatureAdjustedProbability(probability) if value < 0.06: value = 0.0 # otherwise 1/20 chance always return value def break_the_structure(self): self.breakGroup() def breakGroup(self): while len(self.descriptions): description = self.descriptions[-1] description.breakDescription() for objekt in self.objectList: objekt.group = None if self.group: self.group.breakGroup() if self in workspace.structures: workspace.structures.remove(self) if self in workspace.objects: workspace.objects.remove(self) if self in self.string.objects: self.string.objects.remove(self) if self.correspondence: self.correspondence.breakCorrespondence() if self.leftBond: self.leftBond.breakBond() if self.rightBond: self.rightBond.breakBond() def updateInternalStrength(self): relatedBondAssociation = self.groupCategory.getRelatedNode(slipnet.bondCategory).degreeOfAssociation() bondWeight = relatedBondAssociation ** 0.98 length = len(self.objectList) if length == 1: lengthFactor = 5.0 elif length == 2: lengthFactor = 20.0 elif length == 3: lengthFactor = 60.0 else: lengthFactor = 90.0 lengthWeight = 100.0 - bondWeight weightList = ( (relatedBondAssociation, bondWeight), (lengthFactor, lengthWeight) ) self.internalStrength = formulas.weightedAverage(weightList) def updateExternalStrength(self): if self.spansString(): self.externalStrength = 100.0 else: self.externalStrength = self.localSupport() def localSupport(self): numberOfSupporters = self.numberOfLocalSupportingGroups() if numberOfSupporters == 0.0: return 0.0 supportFactor = min(1.0,0.6 ** (1 / (numberOfSupporters ** 3 ))) densityFactor = 100.0 * ((self.localDensity() / 100.0) ** 0.5) return densityFactor * supportFactor def numberOfLocalSupportingGroups(self): count = 0 for objekt in self.string.objects: if isinstance(objekt,Group): if objekt.rightStringPosition < self.leftStringPosition or objekt.leftStringPosition > self.rightStringPosition: if objekt.groupCategory == self.groupCategory and objekt.directionCategory == self.directionCategory: count += 1 return count def localDensity(self): numberOfSupporters = self.numberOfLocalSupportingGroups() halfLength = len(self.string) / 2.0 return 100.0 * numberOfSupporters / halfLength def sameGroup(self,other): if self.leftStringPosition != other.leftStringPosition: return False if self.rightStringPosition != other.rightStringPosition: return False if self.groupCategory != other.groupCategory: return False if self.directionCategory != other.directionCategory: return False if self.facet != other.facet: return False return True def morePossibleDescriptions(self,node): result = [] i = 1 for number in slipnet.numbers: if node == number and len(self.objects) == i: result += [ node ] i += 1 return result def distinguishingDescriptor(self,descriptor): """Whether no other object of the same type (group) has the same descriptor""" if not WorkspaceObject.distinguishingDescriptor(self,descriptor): return False for objekt in self.string.objects: # check to see if they are of the same type if isinstance(objekt,Group) and objekt != self: # check all descriptions for the descriptor for description in objekt.descriptions: if description.descriptor == descriptor: return False return True