Files
copycat/bond.py
2012-10-26 17:35:08 +01:00

183 lines
6.5 KiB
Python

from workspaceStructure import WorkspaceStructure
from slipnet import slipnet
from workspace import workspace
class Bond(WorkspaceStructure):
def __init__(self,source, destination, bondCategory, bondFacet, sourceDescriptor, destinationDescriptor):
WorkspaceStructure.__init__(self)
self.source = source
self.string = self.source.string
self.destination = destination
self.leftObject = self.source
self.rightObject = self.destination
self.directionCategory = slipnet.right
if self.source.leftStringPosition > self.destination.rightStringPosition:
self.leftObject = self.destination
self.rightObject = self.source
self.directionCategory = slipnet.left
self.facet = bondFacet
self.sourceDescriptor = sourceDescriptor
self.destinationDescriptor = destinationDescriptor
self.category = bondCategory
self.destinationIsOnRight = self.destination == self.rightObject
self.bidirectional = self.sourceDescriptor == self.destinationDescriptor
if self.bidirectional:
self.directionCategory = None
def flippedVersion(self):
"""
"""
return Bond(
self.destination, self.get_source(), self.category.getRelatedNode(slipnet.opposite),
self.facet, self.destinationDescriptor, self.sourceDescriptor
)
def __repr__(self):
return '<Bond: %s>' % self.__str__()
def __str__(self):
return '%s bond between %s and %s' % ( self.category.name, self.leftObject, self.rightObject)
def buildBond(self):
workspace.structures += [ self ]
self.string.bonds += [ self ]
self.category.buffer = 100.0
if self.directionCategory:
self.directionCategory.buffer = 100.0
self.leftObject.rightBond = self
self.rightObject.leftBond = self
self.leftObject.bonds += [ self ]
self.rightObject.bonds += [ self ]
def break_the_structure(self):
self.breakBond()
def breakBond(self):
if self in workspace.structures:
workspace.structures.remove(self)
if self in self.string.bonds:
self.string.bonds.remove(self)
self.leftObject.rightBond = None
self.rightObject.leftBond = None
if self in self.leftObject.bonds:
self.leftObject.bonds.remove(self)
if self in self.rightObject.bonds:
self.rightObject.bonds.remove(self)
def getIncompatibleCorrespondences(self):
# returns a list of correspondences that are incompatible with
# self bond
incompatibles = []
if self.leftObject.leftmost and self.leftObject.correspondence:
correspondence = self.leftObject.correspondence
if self.string == workspace.initial:
objekt = self.leftObject.correspondence.objectFromTarget
else:
objekt = self.leftObject.correspondence.objectFromInitial
if objekt.leftmost and objekt.rightBond:
if objekt.rightBond.directionCategory and objekt.rightBond.directionCategory != self.directionCategory:
incompatibles += [ correspondence ]
if self.rightObject.rightmost and self.rightObject.correspondence:
correspondence = self.rightObject.correspondence
if self.string == workspace.initial:
objekt = self.rightObject.correspondence.objectFromTarget
else:
objekt = self.rightObject.correspondence.objectFromInitial
if objekt.rightmost and objekt.leftBond:
if objekt.leftBond.directionCategory and objekt.leftBond.directionCategory != self.directionCategory:
incompatibles += [ correspondence ]
return incompatibles
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
if sourceGap == destinationGap:
memberCompatibility = 1.0
else:
memberCompatibility = 0.7
# letter category bonds are stronger
if self.facet == slipnet.letterCategory:
facetFactor = 1.0
else:
facetFactor = 0.7
strength = min(100.0,memberCompatibility * facetFactor * self.category.bondDegreeOfAssociation())
self.internalStrength = strength
def updateExternalStrength(self):
self.externalStrength = 0.0
supporters = self.numberOfLocalSupportingBonds()
if supporters > 0.0:
density = self.localDensity() / 100.0
density = density ** 0.5 * 100.0
supportFactor = 0.6 ** (1.0 / supporters ** 3)
supportFactor = max(1.0,supportFactor)
strength = supportFactor * density
self.externalStrength = strength
def numberOfLocalSupportingBonds(self):
return len([ b for b in self.string.bonds if b.string == self.get_source().string and
self.leftObject.letterDistance(b.leftObject) != 0 and
self.rightObject.letterDistance(b.rightObject) != 0 and
self.category == b.category and
self.directionCategory == b.directionCategory ])
def sameCategories(self,other):
return self.category == other.category and self.directionCategory == other.directionCategory
def myEnds(self,object1,object2):
if self.get_source() == object1 and self.destination == object2:
return True
return self.get_source() == object2 and self.destination == object1
def localDensity(self):
# returns a rough measure of the density in the string
# of the same bond-category and the direction-category of
# the given bond
slotSum = supportSum = 0.0
for object1 in workspace.objects:
if object1.string == self.string:
for object2 in workspace.objects:
if object1.beside(object2):
slotSum += 1.0
for bond in self.string.bonds:
if bond != self and self.sameCategories(bond) and self.myEnds(object1,object2):
supportSum += 1.0
if slotSum == 0.0:
return 0.0
return 100.0 * supportSum / slotSum
def sameNeighbours(self,other):
if self.leftObject == other.leftObject:
return True
return self.rightObject == other.rightObject
def getIncompatibleBonds(self):
return [ b for b in self.string.bonds if self.sameNeighbours(b) ]
def get_source(self):
return self.source
def set_source(self, value):
self.source = value
def possibleGroupBonds(bondCategory, directionCategory, bondFacet, bonds):
result = []
for bond in bonds:
if bond.category == bondCategory and bond.directionCategory == directionCategory:
result += [ bond ]
else:
# a modified bond might be made
if bondCategory == slipnet.sameness:
return None # a different bond cannot be made here
if bond.category == bondCategory or bond.directionCategory == directionCategory:
return None # a different bond cannot be made here
if bond.category == slipnet.sameness:
return None
bond = Bond(bond.destination, bond.get_source(), bondCategory, bondFacet, bond.destinationDescriptor, bond.sourceDescriptor)
result += [ bond ]
return result