238 lines
7.7 KiB
Python
238 lines
7.7 KiB
Python
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
|
|
|
|
|