Major overhaul of "randomness" throughout.
- Nobody does `import random` anymore. - Random numbers are gotten from `ctx.random`, which is an object of type `Randomness` with all the convenience methods that used to be obnoxious functions in the `formulas` module. - Every place that was using `random.random()` to implement the equivalent of Python3 `random.choices(seq, weights)` has been updated to use `ctx.random.weighted_choice(seq, weights)`. This has a functional effect, since the details of random number generation have changed. The *statistical* effect should be small. I do observe that Copycat is having trouble inventing the "mrrjjjj" solution right now (even in 1000 test runs), so maybe something is slightly broken.
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
import inspect
|
||||
import logging
|
||||
import random
|
||||
|
||||
import formulas
|
||||
from workspaceFormulas import chooseDirectedNeighbor
|
||||
@ -37,7 +36,9 @@ def __showWhichStringObjectIsFrom(structure):
|
||||
#print 'object chosen = %s from %s string' % (structure, whence)
|
||||
|
||||
|
||||
def __getScoutSource(workspace, slipnode, relevanceMethod, typeName):
|
||||
def __getScoutSource(ctx, slipnode, relevanceMethod, typeName):
|
||||
random = ctx.random
|
||||
workspace = ctx.workspace
|
||||
initialRelevance = relevanceMethod(workspace.initial, slipnode)
|
||||
targetRelevance = relevanceMethod(workspace.target, slipnode)
|
||||
initialUnhappiness = workspace.initial.intraStringUnhappiness
|
||||
@ -47,11 +48,9 @@ def __getScoutSource(workspace, slipnode, relevanceMethod, typeName):
|
||||
logging.info('target : relevance = %d, unhappiness=%d',
|
||||
targetRelevance, int(targetUnhappiness))
|
||||
string = workspace.initial
|
||||
relevances = initialRelevance + targetRelevance
|
||||
unhappinesses = initialUnhappiness + targetUnhappiness
|
||||
randomized = random.random() * (relevances + unhappinesses)
|
||||
initials = initialRelevance + initialUnhappiness
|
||||
if randomized > initials:
|
||||
targets = targetRelevance + targetUnhappiness
|
||||
if random.weighted_greater_than(targets, initials):
|
||||
string = workspace.target
|
||||
logging.info('target string selected: %s for %s',
|
||||
workspace.target, typeName)
|
||||
@ -76,7 +75,9 @@ def __getDescriptors(bondFacet, source, destination):
|
||||
|
||||
|
||||
def __structureVsStructure(structure1, weight1, structure2, weight2):
|
||||
"""Return true if the first structure comes out stronger than the second."""
|
||||
ctx = structure1.ctx
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
structure1.updateStrength()
|
||||
structure2.updateStrength()
|
||||
@ -84,9 +85,7 @@ def __structureVsStructure(structure1, weight1, structure2, weight2):
|
||||
structure1.totalStrength * weight1)
|
||||
weightedStrength2 = temperature.getAdjustedValue(
|
||||
structure2.totalStrength * weight2)
|
||||
rhs = (weightedStrength1 + weightedStrength2) * random.random()
|
||||
logging.info('%d > %d', weightedStrength1, rhs)
|
||||
return weightedStrength1 > rhs
|
||||
return random.weighted_greater_than(weightedStrength1, weightedStrength2)
|
||||
|
||||
|
||||
def __fight(structure, structureWeight, incompatibles, incompatibleWeight):
|
||||
@ -115,21 +114,23 @@ def __fightIncompatibles(incompatibles, structure, name,
|
||||
|
||||
|
||||
def __slippability(ctx, conceptMappings):
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
for mapping in conceptMappings:
|
||||
slippiness = mapping.slippability() / 100.0
|
||||
probabilityOfSlippage = temperature.getAdjustedProbability(slippiness)
|
||||
if formulas.coinFlip(probabilityOfSlippage):
|
||||
if random.coinFlip(probabilityOfSlippage):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@codelet('breaker')
|
||||
def breaker(ctx, codelet):
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
probabilityOfFizzle = (100.0 - temperature.value()) / 100.0
|
||||
if formulas.coinFlip(probabilityOfFizzle):
|
||||
if random.coinFlip(probabilityOfFizzle):
|
||||
return
|
||||
# choose a structure at random
|
||||
structures = [s for s in workspace.structures if
|
||||
@ -146,18 +147,28 @@ def breaker(ctx, codelet):
|
||||
for structure in breakObjects:
|
||||
breakProbability = temperature.getAdjustedProbability(
|
||||
structure.totalStrength / 100.0)
|
||||
if formulas.coinFlip(breakProbability):
|
||||
if random.coinFlip(breakProbability):
|
||||
return
|
||||
for structure in breakObjects:
|
||||
structure.break_the_structure()
|
||||
|
||||
|
||||
def similarPropertyLinks(slip_node, temperature):
|
||||
def chooseRelevantDescriptionByActivation(ctx, workspaceObject):
|
||||
random = ctx.random
|
||||
descriptions = workspaceObject.relevantDescriptions()
|
||||
weights = [description.descriptor.activation
|
||||
for description in descriptions]
|
||||
return random.weighted_choice(descriptions, weights)
|
||||
|
||||
|
||||
def similarPropertyLinks(ctx, slip_node):
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
result = []
|
||||
for slip_link in slip_node.propertyLinks:
|
||||
association = slip_link.degreeOfAssociation() / 100.0
|
||||
probability = temperature.getAdjustedProbability(association)
|
||||
if formulas.coinFlip(probability):
|
||||
if random.coinFlip(probability):
|
||||
result += [slip_link]
|
||||
return result
|
||||
|
||||
@ -165,19 +176,21 @@ def similarPropertyLinks(slip_node, temperature):
|
||||
@codelet('bottom-up-description-scout')
|
||||
def bottom_up_description_scout(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
temperature = ctx.temperature
|
||||
random = ctx.random
|
||||
workspace = ctx.workspace
|
||||
chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects)
|
||||
assert chosenObject
|
||||
__showWhichStringObjectIsFrom(chosenObject)
|
||||
description = formulas.chooseRelevantDescriptionByActivation(chosenObject)
|
||||
# choose relevant description by activation
|
||||
descriptions = chosenObject.relevantDescriptions()
|
||||
weights = [d.descriptor.activation for d in descriptions]
|
||||
description = random.weighted_choice(descriptions, weights)
|
||||
assert description
|
||||
sliplinks = similarPropertyLinks(description.descriptor, temperature)
|
||||
sliplinks = similarPropertyLinks(ctx, description.descriptor)
|
||||
assert sliplinks
|
||||
values = [sliplink.degreeOfAssociation() * sliplink.destination.activation
|
||||
weights = [sliplink.degreeOfAssociation() * sliplink.destination.activation
|
||||
for sliplink in sliplinks]
|
||||
i = formulas.selectListPosition(values)
|
||||
chosen = sliplinks[i]
|
||||
chosen = random.weighted_choice(sliplinks, weights)
|
||||
chosenProperty = chosen.destination
|
||||
coderack.proposeDescription(chosenObject, chosenProperty.category(),
|
||||
chosenProperty, codelet)
|
||||
@ -186,6 +199,7 @@ def bottom_up_description_scout(ctx, codelet):
|
||||
@codelet('top-down-description-scout')
|
||||
def top_down_description_scout(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
workspace = ctx.workspace
|
||||
descriptionType = codelet.arguments[0]
|
||||
chosenObject = chooseUnmodifiedObject('totalSalience', workspace.objects)
|
||||
@ -193,9 +207,8 @@ def top_down_description_scout(ctx, codelet):
|
||||
__showWhichStringObjectIsFrom(chosenObject)
|
||||
descriptions = chosenObject.getPossibleDescriptions(descriptionType)
|
||||
assert descriptions and len(descriptions)
|
||||
values = [n.activation for n in descriptions]
|
||||
i = formulas.selectListPosition(values)
|
||||
chosenProperty = descriptions[i]
|
||||
weights = [n.activation for n in descriptions]
|
||||
chosenProperty = random.weighted_choice(descriptions, weights)
|
||||
coderack.proposeDescription(chosenObject, chosenProperty.category(),
|
||||
chosenProperty, codelet)
|
||||
|
||||
@ -203,13 +216,14 @@ def top_down_description_scout(ctx, codelet):
|
||||
@codelet('description-strength-tester')
|
||||
def description_strength_tester(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
description = codelet.arguments[0]
|
||||
description.descriptor.buffer = 100.0
|
||||
description.updateStrength()
|
||||
strength = description.totalStrength
|
||||
probability = temperature.getAdjustedProbability(strength / 100.0)
|
||||
assert formulas.coinFlip(probability)
|
||||
assert random.coinFlip(probability)
|
||||
coderack.newCodelet('description-builder', codelet, strength)
|
||||
|
||||
|
||||
@ -255,6 +269,7 @@ def bottom_up_bond_scout(ctx, codelet):
|
||||
@codelet('rule-scout')
|
||||
def rule_scout(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
@ -292,15 +307,13 @@ def rule_scout(ctx, codelet):
|
||||
newList += [node]
|
||||
objectList = newList # surely this should be +=
|
||||
# "union of this and distinguishing descriptors"
|
||||
assert objectList and len(objectList)
|
||||
assert objectList
|
||||
# use conceptual depth to choose a description
|
||||
valueList = []
|
||||
for node in objectList:
|
||||
depth = node.conceptualDepth
|
||||
value = temperature.getAdjustedValue(depth)
|
||||
valueList += [value]
|
||||
i = formulas.selectListPosition(valueList)
|
||||
descriptor = objectList[i]
|
||||
weights = [
|
||||
temperature.getAdjustedValue(node.conceptualDepth)
|
||||
for node in objectList
|
||||
]
|
||||
descriptor = random.weighted_choice(objectList, weights)
|
||||
# choose the relation (change the letmost object to "successor" or "d"
|
||||
objectList = []
|
||||
if changed.replacement.relation:
|
||||
@ -308,13 +321,11 @@ def rule_scout(ctx, codelet):
|
||||
objectList += [changed.replacement.objectFromModified.getDescriptor(
|
||||
slipnet.letterCategory)]
|
||||
# use conceptual depth to choose a relation
|
||||
valueList = []
|
||||
for node in objectList:
|
||||
depth = node.conceptualDepth
|
||||
value = temperature.getAdjustedValue(depth)
|
||||
valueList += [value]
|
||||
i = formulas.selectListPosition(valueList)
|
||||
relation = objectList[i]
|
||||
weights = [
|
||||
temperature.getAdjustedValue(node.conceptualDepth)
|
||||
for node in objectList
|
||||
]
|
||||
relation = random.weighted_choice(objectList, weights)
|
||||
coderack.proposeRule(slipnet.letterCategory, descriptor,
|
||||
slipnet.letter, relation, codelet)
|
||||
|
||||
@ -322,16 +333,18 @@ def rule_scout(ctx, codelet):
|
||||
@codelet('rule-strength-tester')
|
||||
def rule_strength_tester(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
rule = codelet.arguments[0]
|
||||
rule.updateStrength()
|
||||
probability = temperature.getAdjustedProbability(rule.totalStrength / 100.0)
|
||||
if formulas.coinFlip(probability):
|
||||
if random.coinFlip(probability):
|
||||
coderack.newCodelet('rule-builder', codelet, rule.totalStrength, rule)
|
||||
|
||||
|
||||
@codelet('replacement-finder')
|
||||
def replacement_finder(ctx, codelet):
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
workspace = ctx.workspace
|
||||
# choose random letter in initial string
|
||||
@ -374,10 +387,9 @@ def replacement_finder(ctx, codelet):
|
||||
def top_down_bond_scout__category(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
slipnet = ctx.slipnet
|
||||
workspace = ctx.workspace
|
||||
logging.info('top_down_bond_scout__category')
|
||||
category = codelet.arguments[0]
|
||||
source = __getScoutSource(workspace, category, formulas.localBondCategoryRelevance,
|
||||
source = __getScoutSource(ctx, category, formulas.localBondCategoryRelevance,
|
||||
'bond')
|
||||
destination = chooseNeighbor(source)
|
||||
logging.info('source: %s, destination: %s', source, destination)
|
||||
@ -406,9 +418,8 @@ def top_down_bond_scout__category(ctx, codelet):
|
||||
def top_down_bond_scout__direction(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
slipnet = ctx.slipnet
|
||||
workspace = ctx.workspace
|
||||
direction = codelet.arguments[0]
|
||||
source = __getScoutSource(workspace,
|
||||
source = __getScoutSource(ctx,
|
||||
direction, formulas.localDirectionCategoryRelevance, 'bond')
|
||||
destination = chooseDirectedNeighbor(source, direction)
|
||||
assert destination
|
||||
@ -427,6 +438,7 @@ def top_down_bond_scout__direction(ctx, codelet):
|
||||
@codelet('bond-strength-tester')
|
||||
def bond_strength_tester(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
bond = codelet.arguments[0]
|
||||
__showWhichStringObjectIsFrom(bond)
|
||||
@ -434,7 +446,7 @@ def bond_strength_tester(ctx, codelet):
|
||||
strength = bond.totalStrength
|
||||
probability = temperature.getAdjustedProbability(strength / 100.0)
|
||||
logging.info('bond strength = %d for %s', strength, bond)
|
||||
assert formulas.coinFlip(probability)
|
||||
assert random.coinFlip(probability)
|
||||
bond.facet.buffer = 100.0
|
||||
bond.sourceDescriptor.buffer = 100.0
|
||||
bond.destinationDescriptor.buffer = 100.0
|
||||
@ -489,12 +501,12 @@ def bond_builder(ctx, codelet):
|
||||
@codelet('top-down-group-scout--category')
|
||||
def top_down_group_scout__category(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
workspace = ctx.workspace
|
||||
groupCategory = codelet.arguments[0]
|
||||
category = groupCategory.getRelatedNode(slipnet.bondCategory)
|
||||
assert category
|
||||
source = __getScoutSource(workspace, category, formulas.localBondCategoryRelevance,
|
||||
source = __getScoutSource(ctx, category, formulas.localBondCategoryRelevance,
|
||||
'group')
|
||||
assert source and not source.spansString()
|
||||
if source.leftmost:
|
||||
@ -502,11 +514,10 @@ def top_down_group_scout__category(ctx, codelet):
|
||||
elif source.rightmost:
|
||||
direction = slipnet.left
|
||||
else:
|
||||
activations = [slipnet.left.activation, slipnet.right.activation]
|
||||
if not formulas.selectListPosition(activations):
|
||||
direction = slipnet.left
|
||||
else:
|
||||
direction = slipnet.right
|
||||
direction = random.weighted_choice(
|
||||
[slipnet.left, slipnet.right],
|
||||
[slipnet.left.activation, slipnet.right.activation]
|
||||
)
|
||||
if direction == slipnet.left:
|
||||
firstBond = source.leftBond
|
||||
else:
|
||||
@ -522,7 +533,7 @@ def top_down_group_scout__category(ctx, codelet):
|
||||
group = Group(source.string, slipnet.samenessGroup,
|
||||
None, slipnet.letterCategory, [source], [])
|
||||
probability = group.singleLetterGroupProbability()
|
||||
if formulas.coinFlip(probability):
|
||||
if random.coinFlip(probability):
|
||||
coderack.proposeSingleLetterGroup(source, codelet)
|
||||
return
|
||||
direction = firstBond.directionCategory
|
||||
@ -574,10 +585,10 @@ def top_down_group_scout__category(ctx, codelet):
|
||||
@codelet('top-down-group-scout--direction')
|
||||
def top_down_group_scout__direction(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
workspace = ctx.workspace
|
||||
direction = codelet.arguments[0]
|
||||
source = __getScoutSource(workspace, direction,
|
||||
source = __getScoutSource(ctx, direction,
|
||||
formulas.localDirectionCategoryRelevance,
|
||||
'direction')
|
||||
logging.info('source chosen = %s', source)
|
||||
@ -587,12 +598,10 @@ def top_down_group_scout__direction(ctx, codelet):
|
||||
elif source.rightmost:
|
||||
mydirection = slipnet.left
|
||||
else:
|
||||
activations = [slipnet.left.activation]
|
||||
activations += [slipnet.right.activation]
|
||||
if not formulas.selectListPosition(activations):
|
||||
mydirection = slipnet.left
|
||||
else:
|
||||
mydirection = slipnet.right
|
||||
mydirection = random.weighted_choice(
|
||||
[slipnet.left, slipnet.right],
|
||||
[slipnet.left.activation, slipnet.right.activation]
|
||||
)
|
||||
if mydirection == slipnet.left:
|
||||
firstBond = source.leftBond
|
||||
else:
|
||||
@ -669,9 +678,10 @@ def top_down_group_scout__direction(ctx, codelet):
|
||||
@codelet('group-scout--whole-string')
|
||||
def group_scout__whole_string(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
workspace = ctx.workspace
|
||||
if formulas.coinFlip():
|
||||
if random.coinFlip():
|
||||
string = workspace.target
|
||||
logging.info('target string selected: %s', workspace.target)
|
||||
else:
|
||||
@ -713,6 +723,7 @@ def group_scout__whole_string(ctx, codelet):
|
||||
@codelet('group-strength-tester')
|
||||
def group_strength_tester(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
temperature = ctx.temperature
|
||||
# update strength value of the group
|
||||
@ -721,7 +732,7 @@ def group_strength_tester(ctx, codelet):
|
||||
group.updateStrength()
|
||||
strength = group.totalStrength
|
||||
probability = temperature.getAdjustedProbability(strength / 100.0)
|
||||
if formulas.coinFlip(probability):
|
||||
if random.coinFlip(probability):
|
||||
# it is strong enough - post builder & activate nodes
|
||||
group.groupCategory.getRelatedNode(slipnet.bondCategory).buffer = 100.0
|
||||
if group.directionCategory:
|
||||
@ -821,29 +832,23 @@ def rule_builder(ctx, codelet):
|
||||
workspace.buildRule(rule)
|
||||
|
||||
|
||||
def __getCutOff(density):
|
||||
if density > 0.8:
|
||||
distribution = [5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
|
||||
elif density > 0.6:
|
||||
distribution = [2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0]
|
||||
elif density > 0.4:
|
||||
distribution = [1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0]
|
||||
elif density > 0.2:
|
||||
distribution = [1.0, 1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0]
|
||||
def __getCutoffWeights(bondDensity):
|
||||
if bondDensity > 0.8:
|
||||
return [5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]
|
||||
elif bondDensity > 0.6:
|
||||
return [2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0]
|
||||
elif bondDensity > 0.4:
|
||||
return [1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0, 1.0]
|
||||
elif bondDensity > 0.2:
|
||||
return [1.0, 1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0, 1.0]
|
||||
else:
|
||||
distribution = [1.0, 1.0, 1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0]
|
||||
stop = sum(distribution) * random.random()
|
||||
total = 0.0
|
||||
for i in xrange(len(distribution)):
|
||||
total += distribution[i]
|
||||
if total >= stop:
|
||||
return i + 1
|
||||
return len(distribution)
|
||||
return [1.0, 1.0, 1.0, 2.0, 5.0, 150.0, 5.0, 2.0, 1.0, 1.0]
|
||||
|
||||
|
||||
@codelet('rule-translator')
|
||||
def rule_translator(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
assert workspace.rule
|
||||
@ -854,9 +859,9 @@ def rule_translator(ctx, codelet):
|
||||
len(workspace.target.bonds))
|
||||
nearlyTotalLength = len(workspace.initial) + len(workspace.target) - 2
|
||||
bondDensity = numberOfBonds / nearlyTotalLength
|
||||
if bondDensity > 1.0:
|
||||
bondDensity = 1.0
|
||||
cutoff = __getCutOff(bondDensity) * 10.0
|
||||
bondDensity = min(bondDensity, 1.0)
|
||||
weights = __getCutoffWeights(bondDensity)
|
||||
cutoff = 10.0 * random.weighted_choice(range(1, 11), weights)
|
||||
if cutoff >= temperature.actual_value:
|
||||
if workspace.rule.buildTranslatedRule():
|
||||
workspace.foundAnswer = True
|
||||
@ -905,24 +910,19 @@ def bottom_up_correspondence_scout(ctx, codelet):
|
||||
conceptMappings, flipTargetObject, codelet)
|
||||
|
||||
|
||||
def chooseSlipnodeByConceptualDepth(slip_nodes, temperature):
|
||||
if not slip_nodes:
|
||||
return None
|
||||
depths = [temperature.getAdjustedValue(n.conceptualDepth) for n in slip_nodes]
|
||||
i = formulas.selectListPosition(depths)
|
||||
return slip_nodes[i]
|
||||
|
||||
|
||||
@codelet('important-object-correspondence-scout')
|
||||
def important_object_correspondence_scout(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
objectFromInitial = chooseUnmodifiedObject('relativeImportance',
|
||||
workspace.initial.objects)
|
||||
descriptors = objectFromInitial.relevantDistinguishingDescriptors()
|
||||
slipnode = chooseSlipnodeByConceptualDepth(descriptors, temperature)
|
||||
# choose descriptor by conceptual depth
|
||||
weights = [temperature.getAdjustedValue(n.conceptualDepth) for n in descriptors]
|
||||
slipnode = random.weighted_choice(descriptors, weights)
|
||||
assert slipnode
|
||||
initialDescriptor = slipnode
|
||||
for mapping in workspace.slippages():
|
||||
@ -971,6 +971,7 @@ def important_object_correspondence_scout(ctx, codelet):
|
||||
@codelet('correspondence-strength-tester')
|
||||
def correspondence_strength_tester(ctx, codelet):
|
||||
coderack = ctx.coderack
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
correspondence = codelet.arguments[0]
|
||||
@ -984,7 +985,7 @@ def correspondence_strength_tester(ctx, codelet):
|
||||
correspondence.updateStrength()
|
||||
strength = correspondence.totalStrength
|
||||
probability = temperature.getAdjustedProbability(strength / 100.0)
|
||||
if formulas.coinFlip(probability):
|
||||
if random.coinFlip(probability):
|
||||
# activate some concepts
|
||||
for mapping in correspondence.conceptMappings:
|
||||
mapping.initialDescriptionType.buffer = 100.0
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import math
|
||||
import logging
|
||||
import random
|
||||
|
||||
import codeletMethods
|
||||
import formulas
|
||||
from bond import Bond
|
||||
from codelet import Codelet
|
||||
from correspondence import Correspondence
|
||||
@ -95,6 +93,7 @@ class Coderack(object):
|
||||
return result
|
||||
|
||||
def howManyToPost(self, codeletName):
|
||||
random = self.ctx.random
|
||||
workspace = self.ctx.workspace
|
||||
if codeletName == 'breaker' or 'description' in codeletName:
|
||||
return 1
|
||||
@ -117,9 +116,9 @@ class Coderack(object):
|
||||
number = workspace.numberOfUnreplacedObjects()
|
||||
if 'correspondence' in codeletName:
|
||||
number = workspace.numberOfUncorrespondingObjects()
|
||||
if number < formulas.blur(2.0):
|
||||
if number < random.sqrtBlur(2.0):
|
||||
return 1
|
||||
if number < formulas.blur(4.0):
|
||||
if number < random.sqrtBlur(4.0):
|
||||
return 2
|
||||
return 3
|
||||
|
||||
@ -131,6 +130,7 @@ class Coderack(object):
|
||||
self.removeCodelet(oldCodelet)
|
||||
|
||||
def postTopDownCodelets(self):
|
||||
random = self.ctx.random
|
||||
slipnet = self.ctx.slipnet
|
||||
for node in slipnet.slipnodes:
|
||||
#logging.info('Trying slipnode: %s' % node.get_name())
|
||||
@ -141,7 +141,7 @@ class Coderack(object):
|
||||
probability = self.probabilityOfPosting(codeletName)
|
||||
howMany = self.howManyToPost(codeletName)
|
||||
for _ in xrange(howMany):
|
||||
if not formulas.coinFlip(probability):
|
||||
if not random.coinFlip(probability):
|
||||
continue
|
||||
urgency = getUrgencyBin(
|
||||
node.activation * node.conceptualDepth / 100.0)
|
||||
@ -164,6 +164,7 @@ class Coderack(object):
|
||||
self.__postBottomUpCodelets('breaker')
|
||||
|
||||
def __postBottomUpCodelets(self, codeletName):
|
||||
random = self.ctx.random
|
||||
temperature = self.ctx.temperature
|
||||
probability = self.probabilityOfPosting(codeletName)
|
||||
howMany = self.howManyToPost(codeletName)
|
||||
@ -173,7 +174,7 @@ class Coderack(object):
|
||||
if temperature.value() < 25.0 and 'translator' in codeletName:
|
||||
urgency = 5
|
||||
for _ in xrange(howMany):
|
||||
if formulas.coinFlip(probability):
|
||||
if random.coinFlip(probability):
|
||||
codelet = Codelet(codeletName, urgency, self.codeletsRun)
|
||||
self.post(codelet)
|
||||
|
||||
@ -264,20 +265,13 @@ class Coderack(object):
|
||||
def chooseOldCodelet(self):
|
||||
# selects an old codelet to remove from the coderack
|
||||
# more likely to select lower urgency codelets
|
||||
if not len(self.codelets):
|
||||
return None
|
||||
urgencies = []
|
||||
for codelet in self.codelets:
|
||||
urgency = ((self.codeletsRun - codelet.birthdate) *
|
||||
(7.5 - codelet.urgency))
|
||||
urgencies += [urgency]
|
||||
threshold = random.random() * sum(urgencies)
|
||||
sumOfUrgencies = 0.0
|
||||
for i in xrange(len(self.codelets)):
|
||||
sumOfUrgencies += urgencies[i]
|
||||
if sumOfUrgencies > threshold:
|
||||
return self.codelets[i]
|
||||
return self.codelets[0]
|
||||
random = self.ctx.random
|
||||
return random.weighted_choice(self.codelets, urgencies)
|
||||
|
||||
def postInitialCodelets(self):
|
||||
workspace = self.ctx.workspace
|
||||
@ -300,22 +294,12 @@ class Coderack(object):
|
||||
self.run(codelet)
|
||||
|
||||
def chooseCodeletToRun(self):
|
||||
random = self.ctx.random
|
||||
temperature = self.ctx.temperature
|
||||
assert self.codelets
|
||||
scale = (100.0 - temperature.value() + 10.0) / 15.0
|
||||
urgsum = sum(codelet.urgency ** scale for codelet in self.codelets)
|
||||
threshold = random.random() * urgsum
|
||||
chosen = self.codelets[0]
|
||||
urgencySum = 0.0
|
||||
|
||||
for codelet in self.codelets:
|
||||
urgencySum += codelet.urgency ** scale
|
||||
if urgencySum > threshold:
|
||||
chosen = codelet
|
||||
break
|
||||
chosen = random.weighted_choice(self.codelets, [codelet.urgency ** scale for codelet in self.codelets])
|
||||
self.removeCodelet(chosen)
|
||||
logging.info('chosen codelet\n\t%s, urgency = %s',
|
||||
chosen.name, chosen.urgency)
|
||||
return chosen
|
||||
|
||||
def run(self, codelet):
|
||||
|
||||
@ -3,10 +3,11 @@ import logging
|
||||
|
||||
class Context(object):
|
||||
def __init__(self):
|
||||
self.temperature = None
|
||||
self.coderack = None
|
||||
self.workspace = None
|
||||
self.random = None
|
||||
self.slipnet = None
|
||||
self.temperature = None
|
||||
self.workspace = None
|
||||
|
||||
def mainLoop(self, lastUpdate):
|
||||
currentTime = self.coderack.codeletsRun
|
||||
@ -15,7 +16,7 @@ class Context(object):
|
||||
if currentTime >= lastUpdate + 15:
|
||||
self.workspace.updateEverything()
|
||||
self.coderack.updateCodelets()
|
||||
self.slipnet.update()
|
||||
self.slipnet.update(self.random)
|
||||
self.temperature.update(self.workspace.getUpdatedTemperature())
|
||||
lastUpdate = currentTime
|
||||
logging.debug('Number of codelets: %d', len(self.coderack.codelets))
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import logging
|
||||
|
||||
from workspace import Workspace
|
||||
from coderack import Coderack
|
||||
from randomness import Randomness
|
||||
from slipnet import Slipnet
|
||||
from temperature import Temperature
|
||||
from coderack import Coderack
|
||||
from workspace import Workspace
|
||||
|
||||
from context import context
|
||||
|
||||
|
||||
context.coderack = Coderack(context)
|
||||
context.random = Randomness(42)
|
||||
context.slipnet = Slipnet()
|
||||
context.temperature = Temperature()
|
||||
context.coderack = Coderack(context)
|
||||
context.workspace = Workspace(context)
|
||||
|
||||
|
||||
|
||||
@ -1,25 +1,6 @@
|
||||
import math
|
||||
import random
|
||||
|
||||
from conceptMapping import ConceptMapping
|
||||
|
||||
|
||||
def selectListPosition(probabilities):
|
||||
total = sum(probabilities)
|
||||
#logging.info('total: %s' % total)
|
||||
r = random.random()
|
||||
stopPosition = total * r
|
||||
#logging.info('stopPosition: %s' % stopPosition)
|
||||
total = 0
|
||||
i = 0
|
||||
for probability in probabilities:
|
||||
total += probability
|
||||
if total > stopPosition:
|
||||
return i
|
||||
i += 1
|
||||
return 0
|
||||
|
||||
|
||||
def weightedAverage(values):
|
||||
total = 0.0
|
||||
totalWeights = 0.0
|
||||
@ -31,27 +12,6 @@ def weightedAverage(values):
|
||||
return total / totalWeights
|
||||
|
||||
|
||||
def coinFlip(chance=0.5):
|
||||
return random.random() < chance
|
||||
|
||||
|
||||
def blur(value):
|
||||
root = math.sqrt(value)
|
||||
if coinFlip():
|
||||
return value + root
|
||||
return value - root
|
||||
|
||||
|
||||
def chooseRelevantDescriptionByActivation(workspaceObject):
|
||||
descriptions = workspaceObject.relevantDescriptions()
|
||||
if not descriptions:
|
||||
return None
|
||||
activations = [description.descriptor.activation
|
||||
for description in descriptions]
|
||||
i = selectListPosition(activations)
|
||||
return descriptions[i]
|
||||
|
||||
|
||||
def __relevantCategory(objekt, slipnode):
|
||||
return objekt.rightBond and objekt.rightBond.category == slipnode
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import logging
|
||||
import random
|
||||
|
||||
from workspaceObject import WorkspaceObject
|
||||
import formulas
|
||||
@ -73,9 +72,10 @@ class Group(WorkspaceObject):
|
||||
|
||||
def add_length_description_category(self):
|
||||
#check whether or not to add length description category
|
||||
random = self.ctx.random
|
||||
slipnet = self.ctx.slipnet
|
||||
probability = self.lengthDescriptionProbability()
|
||||
if random.random() < probability:
|
||||
if random.coinFlip(probability):
|
||||
length = len(self.objectList)
|
||||
if length < 6:
|
||||
self.addDescription(slipnet.length,
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
"""Run the copycat program"""
|
||||
|
||||
import logging
|
||||
import random
|
||||
import sys
|
||||
|
||||
random.seed(42)
|
||||
|
||||
import copycat
|
||||
|
||||
|
||||
|
||||
41
copycat/randomness.py
Normal file
41
copycat/randomness.py
Normal file
@ -0,0 +1,41 @@
|
||||
import bisect
|
||||
import math
|
||||
import random
|
||||
|
||||
def accumulate(iterable):
|
||||
total = 0
|
||||
for v in iterable:
|
||||
total += v
|
||||
yield total
|
||||
|
||||
class Randomness(object):
|
||||
def __init__(self, seed=None):
|
||||
self.rng = random.Random(seed)
|
||||
|
||||
def coinFlip(self, p=0.5):
|
||||
return self.rng.random() < p
|
||||
|
||||
def choice(self, seq):
|
||||
return self.rng.choice(seq)
|
||||
|
||||
def weighted_choice(self, seq, weights):
|
||||
if not seq:
|
||||
# Many callers rely on this behavior.
|
||||
return None
|
||||
else:
|
||||
cum_weights = list(accumulate(weights))
|
||||
total = cum_weights[-1]
|
||||
return seq[bisect.bisect_left(cum_weights, self.rng.random() * total)]
|
||||
|
||||
def weighted_greater_than(self, first, second):
|
||||
total = first + second
|
||||
if total == 0:
|
||||
return False
|
||||
return self.coinFlip(float(first) / total)
|
||||
|
||||
def sqrtBlur(self, value):
|
||||
# This is exceedingly dumb, but it matches the Java code.
|
||||
root = math.sqrt(value)
|
||||
if self.coinFlip():
|
||||
return value + root
|
||||
return value - root
|
||||
@ -32,7 +32,7 @@ class Slipnet(object):
|
||||
for node in self.initiallyClampedSlipnodes:
|
||||
node.clampHigh()
|
||||
|
||||
def update(self):
|
||||
def update(self, random):
|
||||
logging.debug('slipnet.update()')
|
||||
self.numberOfUpdates += 1
|
||||
if self.numberOfUpdates == 50:
|
||||
@ -44,7 +44,7 @@ class Slipnet(object):
|
||||
node.spread_activation()
|
||||
for node in self.slipnodes:
|
||||
node.addBuffer()
|
||||
node.jump()
|
||||
node.jump(random)
|
||||
node.buffer = 0.0
|
||||
|
||||
def isDistinguishingDescriptor(self, descriptor):
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
import math
|
||||
import logging
|
||||
import random
|
||||
|
||||
|
||||
def full_activation():
|
||||
return 100
|
||||
|
||||
|
||||
def jump_threshold():
|
||||
@ -65,11 +60,7 @@ class Slipnode(object):
|
||||
def fully_active(self):
|
||||
"""Whether this node has full activation"""
|
||||
float_margin = 0.00001
|
||||
return self.activation > full_activation() - float_margin
|
||||
|
||||
def activate_fully(self):
|
||||
"""Make this node fully active"""
|
||||
self.activation = full_activation()
|
||||
return self.activation > 100.0 - float_margin
|
||||
|
||||
def bondDegreeOfAssociation(self):
|
||||
linkLength = self.intrinsicLinkLength
|
||||
@ -112,7 +103,8 @@ class Slipnode(object):
|
||||
|
||||
If no linked node is found, return None
|
||||
"""
|
||||
if relation == self.slipnet.identity:
|
||||
slipnet = self.slipnet
|
||||
if relation == slipnet.identity:
|
||||
return self
|
||||
destinations = [l.destination
|
||||
for l in self.outgoingLinks if l.label == relation]
|
||||
@ -125,9 +117,10 @@ class Slipnode(object):
|
||||
|
||||
If it does not exist return None
|
||||
"""
|
||||
slipnet = self.slipnet
|
||||
result = None
|
||||
if self == destination:
|
||||
result = self.slipnet.identity
|
||||
result = slipnet.identity
|
||||
else:
|
||||
for link in self.outgoingLinks:
|
||||
if link.destination == destination:
|
||||
@ -149,17 +142,14 @@ class Slipnode(object):
|
||||
self.activation += self.buffer
|
||||
self.activation = min(max(0, self.activation), 100)
|
||||
|
||||
def can_jump(self):
|
||||
def jump(self, random):
|
||||
if self.activation <= jump_threshold():
|
||||
return False
|
||||
return
|
||||
if self.clamped:
|
||||
return False
|
||||
return
|
||||
value = (self.activation / 100.0) ** 3
|
||||
return random.random() < value
|
||||
|
||||
def jump(self):
|
||||
if self.can_jump():
|
||||
self.activate_fully()
|
||||
if random.coinFlip(value):
|
||||
self.activation = 100.0
|
||||
|
||||
def get_name(self):
|
||||
if len(self.name) == 1:
|
||||
|
||||
@ -1,34 +1,29 @@
|
||||
import logging
|
||||
|
||||
import formulas
|
||||
|
||||
|
||||
def __chooseObjectFromList(temperature, objects, attribute):
|
||||
if not objects:
|
||||
return None
|
||||
def __chooseObjectFromList(ctx, objects, attribute):
|
||||
random = ctx.random
|
||||
temperature = ctx.temperature
|
||||
weights = [
|
||||
temperature.getAdjustedValue(
|
||||
getattr(o, attribute)
|
||||
)
|
||||
for o in objects
|
||||
]
|
||||
i = formulas.selectListPosition(weights)
|
||||
return objects[i]
|
||||
return random.weighted_choice(objects, weights)
|
||||
|
||||
|
||||
def chooseUnmodifiedObject(attribute, inObjects):
|
||||
from context import context as ctx
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
objects = [o for o in inObjects if o.string != workspace.modified]
|
||||
if not len(objects):
|
||||
print 'no objects available in initial or target strings'
|
||||
return __chooseObjectFromList(temperature, objects, attribute)
|
||||
return __chooseObjectFromList(ctx, objects, attribute)
|
||||
|
||||
|
||||
def chooseNeighbor(source):
|
||||
from context import context as ctx
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
objects = []
|
||||
for objekt in workspace.objects:
|
||||
@ -38,7 +33,7 @@ def chooseNeighbor(source):
|
||||
objects += [objekt]
|
||||
elif source.leftIndex == objekt.rightIndex + 1:
|
||||
objects += [objekt]
|
||||
return __chooseObjectFromList(temperature, objects, "intraStringSalience")
|
||||
return __chooseObjectFromList(ctx, objects, "intraStringSalience")
|
||||
|
||||
|
||||
def chooseDirectedNeighbor(source, direction):
|
||||
@ -53,7 +48,6 @@ def chooseDirectedNeighbor(source, direction):
|
||||
|
||||
def __chooseLeftNeighbor(source):
|
||||
from context import context as ctx
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
objects = []
|
||||
for o in workspace.objects:
|
||||
@ -64,32 +58,29 @@ def __chooseLeftNeighbor(source):
|
||||
else:
|
||||
logging.info('%s is not on left of %s', o, source)
|
||||
logging.info('Number of left objects: %s', len(objects))
|
||||
return __chooseObjectFromList(temperature, objects, 'intraStringSalience')
|
||||
return __chooseObjectFromList(ctx, objects, 'intraStringSalience')
|
||||
|
||||
|
||||
def __chooseRightNeighbor(source):
|
||||
from context import context as ctx
|
||||
temperature = ctx.temperature
|
||||
workspace = ctx.workspace
|
||||
objects = [o for o in workspace.objects
|
||||
if o.string == source.string
|
||||
and o.leftIndex == source.rightIndex + 1]
|
||||
return __chooseObjectFromList(temperature, objects, 'intraStringSalience')
|
||||
return __chooseObjectFromList(ctx, objects, 'intraStringSalience')
|
||||
|
||||
|
||||
def chooseBondFacet(source, destination):
|
||||
from context import context as ctx
|
||||
random = ctx.random
|
||||
slipnet = ctx.slipnet
|
||||
sourceFacets = [d.descriptionType for d in source.descriptions
|
||||
if d.descriptionType in slipnet.bondFacets]
|
||||
bondFacets = [d.descriptionType for d in destination.descriptions
|
||||
if d.descriptionType in sourceFacets]
|
||||
if not bondFacets:
|
||||
return None
|
||||
supports = [__supportForDescriptionType(f, source.string)
|
||||
for f in bondFacets]
|
||||
i = formulas.selectListPosition(supports)
|
||||
return bondFacets[i]
|
||||
return random.weighted_choice(bondFacets, supports)
|
||||
|
||||
|
||||
def __supportForDescriptionType(descriptionType, string):
|
||||
|
||||
Reference in New Issue
Block a user