diff --git a/copycat/codeletMethods.py b/copycat/codeletMethods.py index 1dd93e0..750e084 100644 --- a/copycat/codeletMethods.py +++ b/copycat/codeletMethods.py @@ -77,11 +77,12 @@ def __getDescriptors(bondFacet, source, destination): def __structureVsStructure(structure1, weight1, structure2, weight2): ctx = structure1.ctx + temperature = ctx.temperature structure1.updateStrength() structure2.updateStrength() - weightedStrength1 = formulas.temperatureAdjustedValue(ctx, + weightedStrength1 = temperature.getAdjustedValue( structure1.totalStrength * weight1) - weightedStrength2 = formulas.temperatureAdjustedValue(ctx, + weightedStrength2 = temperature.getAdjustedValue( structure2.totalStrength * weight2) rhs = (weightedStrength1 + weightedStrength2) * random.random() logging.info('%d > %d', weightedStrength1, rhs) @@ -114,10 +115,10 @@ def __fightIncompatibles(incompatibles, structure, name, def __slippability(ctx, conceptMappings): + temperature = ctx.temperature for mapping in conceptMappings: slippiness = mapping.slippability() / 100.0 - probabilityOfSlippage = formulas.temperatureAdjustedProbability(ctx, - slippiness) + probabilityOfSlippage = temperature.getAdjustedProbability(slippiness) if formulas.coinFlip(probabilityOfSlippage): return True return False @@ -143,7 +144,7 @@ def breaker(ctx, codelet): breakObjects += [structure.source.group] # Break all the objects or none of them; this matches the Java for structure in breakObjects: - breakProbability = formulas.temperatureAdjustedProbability(ctx, + breakProbability = temperature.getAdjustedProbability( structure.totalStrength / 100.0) if formulas.coinFlip(breakProbability): return @@ -191,11 +192,12 @@ def top_down_description_scout(ctx, codelet): @codelet('description-strength-tester') def description_strength_tester(ctx, codelet): coderack = ctx.coderack + temperature = ctx.temperature description = codelet.arguments[0] description.descriptor.buffer = 100.0 description.updateStrength() strength = description.totalStrength - probability = formulas.temperatureAdjustedProbability(ctx, strength / 100.0) + probability = temperature.getAdjustedProbability(strength / 100.0) assert formulas.coinFlip(probability) coderack.newCodelet('description-builder', codelet, strength) @@ -243,6 +245,7 @@ def bottom_up_bond_scout(ctx, codelet): def rule_scout(ctx, codelet): coderack = ctx.coderack slipnet = ctx.slipnet + temperature = ctx.temperature workspace = ctx.workspace assert workspace.numberOfUnreplacedObjects() == 0 changedObjects = [o for o in workspace.initial.objects if o.changed] @@ -283,7 +286,7 @@ def rule_scout(ctx, codelet): valueList = [] for node in objectList: depth = node.conceptualDepth - value = formulas.temperatureAdjustedValue(ctx, depth) + value = temperature.getAdjustedValue(depth) valueList += [value] i = formulas.selectListPosition(valueList) descriptor = objectList[i] @@ -297,7 +300,7 @@ def rule_scout(ctx, codelet): valueList = [] for node in objectList: depth = node.conceptualDepth - value = formulas.temperatureAdjustedValue(ctx, depth) + value = temperature.getAdjustedValue(depth) valueList += [value] i = formulas.selectListPosition(valueList) relation = objectList[i] @@ -308,9 +311,10 @@ def rule_scout(ctx, codelet): @codelet('rule-strength-tester') def rule_strength_tester(ctx, codelet): coderack = ctx.coderack + temperature = ctx.temperature rule = codelet.arguments[0] rule.updateStrength() - probability = formulas.temperatureAdjustedProbability(ctx, rule.totalStrength / 100.0) + probability = temperature.getAdjustedProbability(rule.totalStrength / 100.0) if formulas.coinFlip(probability): coderack.newCodelet('rule-builder', codelet, rule.totalStrength, rule) @@ -412,11 +416,12 @@ def top_down_bond_scout__direction(ctx, codelet): @codelet('bond-strength-tester') def bond_strength_tester(ctx, codelet): coderack = ctx.coderack + temperature = ctx.temperature bond = codelet.arguments[0] __showWhichStringObjectIsFrom(bond) bond.updateStrength() strength = bond.totalStrength - probability = formulas.temperatureAdjustedProbability(ctx, strength / 100.0) + probability = temperature.getAdjustedProbability(strength / 100.0) logging.info('bond strength = %d for %s', strength, bond) assert formulas.coinFlip(probability) bond.facet.buffer = 100.0 @@ -698,12 +703,13 @@ def group_scout__whole_string(ctx, codelet): def group_strength_tester(ctx, codelet): coderack = ctx.coderack slipnet = ctx.slipnet + temperature = ctx.temperature # update strength value of the group group = codelet.arguments[0] __showWhichStringObjectIsFrom(group) group.updateStrength() strength = group.totalStrength - probability = formulas.temperatureAdjustedProbability(ctx, strength / 100.0) + probability = temperature.getAdjustedProbability(strength / 100.0) if formulas.coinFlip(probability): # it is strong enough - post builder & activate nodes group.groupCategory.getRelatedNode(slipnet.bondCategory).buffer = 100.0 @@ -945,6 +951,7 @@ def important_object_correspondence_scout(ctx, codelet): @codelet('correspondence-strength-tester') def correspondence_strength_tester(ctx, codelet): coderack = ctx.coderack + temperature = ctx.temperature workspace = ctx.workspace correspondence = codelet.arguments[0] objectFromInitial = correspondence.objectFromInitial @@ -956,7 +963,7 @@ def correspondence_strength_tester(ctx, codelet): objectFromTarget.flipped_version()))) correspondence.updateStrength() strength = correspondence.totalStrength - probability = formulas.temperatureAdjustedProbability(ctx, strength / 100.0) + probability = temperature.getAdjustedProbability(strength / 100.0) if formulas.coinFlip(probability): # activate some concepts for mapping in correspondence.conceptMappings: diff --git a/copycat/formulas.py b/copycat/formulas.py index d23c0c7..48c4147 100644 --- a/copycat/formulas.py +++ b/copycat/formulas.py @@ -32,22 +32,6 @@ def weightedAverage(values): return total / totalWeights -def temperatureAdjustedValue(ctx, value): - return value ** (((100.0 - ctx.temperature.value()) / 30.0) + 0.5) - - -def temperatureAdjustedProbability(ctx, value): - if value == 0 or value == 0.5 or ctx.temperature.value() == 0: - return value - if value < 0.5: - return 1.0 - temperatureAdjustedProbability(ctx, 1.0 - value) - coldness = 100.0 - ctx.temperature.value() - a = math.sqrt(coldness) - c = (10 - a) / 100 - f = (c + 1) * value - return max(f, 0.5) - - def coinFlip(chance=0.5): return random.random() < chance @@ -61,12 +45,13 @@ def blur(value): def chooseObjectFromList(objects, attribute): from context import context as ctx + temperature = ctx.temperature if not objects: return None probabilities = [] for objekt in objects: value = getattr(objekt, attribute) - probability = temperatureAdjustedValue(ctx, value) + probability = temperature.getAdjustedValue(value) logging.info('Object: %s, value: %d, probability: %d', objekt, value, probability) probabilities += [probability] @@ -87,10 +72,11 @@ def chooseRelevantDescriptionByActivation(workspaceObject): def similarPropertyLinks(slip_node): from context import context as ctx + temperature = ctx.temperature result = [] for slip_link in slip_node.propertyLinks: association = slip_link.degreeOfAssociation() / 100.0 - probability = temperatureAdjustedProbability(ctx, association) + probability = temperature.getAdjustedProbability(association) if coinFlip(probability): result += [slip_link] return result @@ -98,9 +84,10 @@ def similarPropertyLinks(slip_node): def chooseSlipnodeByConceptualDepth(slip_nodes): from context import context as ctx + temperature = ctx.temperature if not slip_nodes: return None - depths = [temperatureAdjustedValue(ctx, n.conceptualDepth) for n in slip_nodes] + depths = [temperature.getAdjustedValue(n.conceptualDepth) for n in slip_nodes] i = selectListPosition(depths) return slip_nodes[i] diff --git a/copycat/group.py b/copycat/group.py index ac02d37..c182f67 100644 --- a/copycat/group.py +++ b/copycat/group.py @@ -100,6 +100,7 @@ class Group(WorkspaceObject): def singleLetterGroupProbability(self): slipnet = self.ctx.slipnet + temperature = self.ctx.temperature numberOfSupporters = self.numberOfLocalSupportingGroups() if not numberOfSupporters: return 0.0 @@ -112,7 +113,7 @@ class Group(WorkspaceObject): support = self.localSupport() / 100.0 activation = slipnet.length.activation / 100.0 supportedActivation = (support * activation) ** exp - return formulas.temperatureAdjustedProbability(self.ctx, supportedActivation) + return temperature.getAdjustedProbability(supportedActivation) def flippedVersion(self): slipnet = self.ctx.slipnet @@ -140,13 +141,14 @@ class Group(WorkspaceObject): def lengthDescriptionProbability(self): slipnet = self.ctx.slipnet + temperature = self.ctx.temperature 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(self.ctx, probability) + value = temperature.getAdjustedProbability(probability) if value < 0.06: value = 0.0 # otherwise 1/20 chance always return value diff --git a/copycat/temperature.py b/copycat/temperature.py index c5b8c1f..99727f1 100644 --- a/copycat/temperature.py +++ b/copycat/temperature.py @@ -1,3 +1,4 @@ +import math class Temperature(object): def __init__(self): @@ -27,3 +28,17 @@ class Temperature(object): def value(self): return 100.0 if self.clamped else self.actual_value + + def getAdjustedValue(self, value): + return value ** (((100.0 - self.value()) / 30.0) + 0.5) + + def getAdjustedProbability(self, value): + if value == 0 or value == 0.5 or self.value() == 0: + return value + if value < 0.5: + return 1.0 - self.getAdjustedProbability(1.0 - value) + coldness = 100.0 - self.value() + a = math.sqrt(coldness) + c = (10 - a) / 100 + f = (c + 1) * value + return max(f, 0.5)