Ports to Python3

This commit is contained in:
LSaldyt
2017-07-31 17:08:26 -06:00
parent 318d0e2349
commit bc848e8f2d
22 changed files with 158 additions and 92 deletions

63
copycat.log Normal file
View File

@ -0,0 +1,63 @@
object chosen = j from target string
destination: k
chosen bond facet: letterCategory
Source: j, destination: k
source descriptor: J
destination descriptor: K
proposing successor bond
urgency: 100.0, number: 1, bin: 7
object chosen = j from target string
destination: i
chosen bond facet: letterCategory
Source: j, destination: i
source descriptor: J
destination descriptor: I
proposing predecessor bond
object chosen = successor bond between j and k from other string
bond strength = 48 for successor bond between j and k
object chosen = a from initial string
destination: b
chosen bond facet: letterCategory
Source: a, destination: b
source descriptor: A
destination descriptor: B
proposing successor bond
object chosen = successor bond between a and b from other string
bond strength = 48 for successor bond between a and b
succeeded: posting bond-builder
object chosen = successor bond between a and b from other string
number of incompatibleBonds: 0
no incompatible bonds
no incompatible groups
building bond successor bond between a and b
object chosen = a from initial string
destination: b
chosen bond facet: letterCategory
Source: a, destination: b
source descriptor: A
destination descriptor: B
proposing successor bond
object chosen = a from initial string
destination: b
chosen bond facet: letterCategory
Source: a, destination: b
source descriptor: A
destination descriptor: B
proposing successor bond
Post top down: top-down-description-scout, with urgency: 5
posting bottom up codelets
object chosen = a from initial string
object chosen = j from target string
destination: i
chosen bond facet: letterCategory
Source: j, destination: i
source descriptor: J
destination descriptor: I
proposing predecessor bond
object chosen = a from initial string
destination: b
chosen bond facet: letterCategory
Source: a, destination: b
source descriptor: A
destination descriptor: B
proposing successor bond

View File

@ -1 +1 @@
from copycat import Copycat, Reporter # noqa
from .copycat import Copycat, Reporter # noqa

View File

@ -1,4 +1,4 @@
from workspaceStructure import WorkspaceStructure
from .workspaceStructure import WorkspaceStructure
class Bond(WorkspaceStructure):

View File

@ -1,16 +1,16 @@
import inspect
import logging
import formulas
from workspaceFormulas import chooseDirectedNeighbor
from workspaceFormulas import chooseNeighbor
from workspaceFormulas import chooseUnmodifiedObject
from workspaceObject import WorkspaceObject
from letter import Letter
from replacement import Replacement
from group import Group
from bond import Bond
from correspondence import Correspondence
from . import formulas
from .workspaceFormulas import chooseDirectedNeighbor
from .workspaceFormulas import chooseNeighbor
from .workspaceFormulas import chooseUnmodifiedObject
from .workspaceObject import WorkspaceObject
from .letter import Letter
from .replacement import Replacement
from .group import Group
from .bond import Bond
from .correspondence import Correspondence
def codelet(name):
@ -804,7 +804,7 @@ def group_builder(ctx, codelet):
incompatible.break_the_structure()
# create new bonds
group.bondList = []
for i in xrange(1, len(group.objectList)):
for i in range(1, len(group.objectList)):
object1 = group.objectList[i - 1]
object2 = group.objectList[i]
if not object1.rightBond:
@ -871,7 +871,7 @@ def rule_translator(ctx, codelet):
bondDensity = numberOfBonds / nearlyTotalLength
bondDensity = min(bondDensity, 1.0)
weights = __getCutoffWeights(bondDensity)
cutoff = 10.0 * random.weighted_choice(range(1, 11), weights)
cutoff = 10.0 * random.weighted_choice(list(range(1, 11)), weights)
if cutoff >= temperature.actual_value:
result = workspace.rule.buildTranslatedRule()
if result is not None:

View File

@ -1,13 +1,13 @@
import math
import logging
import codeletMethods
from bond import Bond
from codelet import Codelet
from correspondence import Correspondence
from description import Description
from group import Group
from rule import Rule
from . import codeletMethods
from .bond import Bond
from .codelet import Codelet
from .correspondence import Correspondence
from .description import Description
from .group import Group
from .rule import Rule
NUMBER_OF_BINS = 7
@ -131,7 +131,7 @@ class Coderack(object):
for codeletName in node.codelets:
probability = self.probabilityOfPosting(codeletName)
howMany = self.howManyToPost(codeletName)
for _ in xrange(howMany):
for _ in range(howMany):
if not random.coinFlip(probability):
continue
urgency = getUrgencyBin(
@ -163,7 +163,7 @@ class Coderack(object):
urgency = 1
if temperature.value() < 25.0 and 'translator' in codeletName:
urgency = 5
for _ in xrange(howMany):
for _ in range(howMany):
if random.coinFlip(probability):
codelet = Codelet(codeletName, urgency, [], self.codeletsRun)
self.post(codelet)
@ -272,7 +272,7 @@ class Coderack(object):
('bottom-up-correspondence-scout', 2 * n),
]
for name, count in codeletsToPost:
for _ in xrange(count):
for _ in range(count):
codelet = Codelet(name, 1, [], self.codeletsRun)
self.post(codelet)

View File

@ -1,8 +1,8 @@
from coderack import Coderack
from randomness import Randomness
from slipnet import Slipnet
from temperature import Temperature
from workspace import Workspace
from .coderack import Coderack
from .randomness import Randomness
from .slipnet import Slipnet
from .temperature import Temperature
from .workspace import Workspace
class Reporter(object):
@ -69,7 +69,7 @@ class Copycat(object):
def run(self, initial, modified, target, iterations):
self.workspace.resetWithStrings(initial, modified, target)
answers = {}
for i in xrange(iterations):
for i in range(iterations):
answer = self.runTrial()
d = answers.setdefault(answer['answer'], {
'count': 0,
@ -80,7 +80,7 @@ class Copycat(object):
d['sumtemp'] += answer['temp']
d['sumtime'] += answer['time']
for answer, d in answers.iteritems():
for answer, d in answers.items():
d['avgtemp'] = d.pop('sumtemp') / d['count']
d['avgtime'] = d.pop('sumtime') / d['count']
return answers

View File

@ -1,8 +1,8 @@
from conceptMapping import ConceptMapping
from group import Group
from letter import Letter
from workspaceStructure import WorkspaceStructure
import formulas
from .conceptMapping import ConceptMapping
from .group import Group
from .letter import Letter
from .workspaceStructure import WorkspaceStructure
from . import formulas
class Correspondence(WorkspaceStructure):
@ -143,8 +143,8 @@ class Correspondence(WorkspaceStructure):
def internallyCoherent(self):
"""Whether any pair of distinguishing mappings support each other"""
mappings = self.relevantDistinguishingConceptMappings()
for i in xrange(len(mappings)):
for j in xrange(len(mappings)):
for i in range(len(mappings)):
for j in range(len(mappings)):
if i != j:
if mappings[i].supports(mappings[j]):
return True

View File

@ -1,13 +1,13 @@
import curses
import time
from copycat import Reporter
from bond import Bond
from correspondence import Correspondence
from description import Description
from group import Group
from letter import Letter
from rule import Rule
from .copycat import Reporter
from .bond import Bond
from .correspondence import Correspondence
from .description import Description
from .group import Group
from .letter import Letter
from .rule import Rule
class SafeSubwindow(object):
@ -122,7 +122,7 @@ class CursesReporter(Reporter):
d['answer'], d['count'], d['avgtime'], d['avgtemp'],
)
answersToPrint = sorted(self.answers.itervalues(), key=fitness, reverse=True)
answersToPrint = sorted(iter(self.answers.values()), key=fitness, reverse=True)
w = self.answersWindow
pageWidth = w.getmaxyx()[1]
@ -175,7 +175,7 @@ class CursesReporter(Reporter):
# Sort the most common and highest-urgency codelets to the top.
entries = sorted(
(count, key[0], key[1])
for key, count in counts.iteritems()
for key, count in counts.items()
)
# Figure out how we'd like to render each codelet's name.
@ -193,10 +193,10 @@ class CursesReporter(Reporter):
w.erase()
for u, string in printable_entries:
# Find the highest point on the page where we could place this entry.
start_column = (u - 1) * columnWidth
start_column = int((u - 1) * columnWidth)
end_column = start_column + len(string)
for r in range(pageHeight):
if all(w.is_vacant(r, c) for c in xrange(start_column, end_column+20)):
if all(w.is_vacant(r, c) for c in range(start_column, end_column+20)):
w.addstr(r, start_column, string)
break
w.refresh()
@ -308,7 +308,7 @@ class CursesReporter(Reporter):
else:
w.addstr(firstrow, column, '\\', curses.A_NORMAL)
w.addstr(lastrow, column, '/', curses.A_NORMAL)
for r in xrange(firstrow + 1, lastrow):
for r in range(firstrow + 1, lastrow):
w.addstr(r, column, '|', curses.A_NORMAL)
def report_workspace(self, workspace):
@ -410,12 +410,12 @@ class CursesReporter(Reporter):
end = endrow_for_group[group]
# Place this group's graphical depiction.
depiction_width = 3 + self.length_of_workspace_object_depiction(group, description_structures)
for firstcolumn in xrange(max_column, 1000):
for firstcolumn in range(max_column, 1000):
lastcolumn = firstcolumn + depiction_width
okay = all(
w.is_vacant(r, c)
for c in xrange(firstcolumn, lastcolumn + 1)
for r in xrange(start, end + 1)
for c in range(firstcolumn, lastcolumn + 1)
for r in range(start, end + 1)
)
if okay:
self.depict_grouping_brace(w, start, end, firstcolumn + 1)

View File

@ -1,4 +1,4 @@
from workspaceStructure import WorkspaceStructure
from .workspaceStructure import WorkspaceStructure
class Description(WorkspaceStructure):

View File

@ -1,4 +1,4 @@
from conceptMapping import ConceptMapping
from .conceptMapping import ConceptMapping
def weightedAverage(values):

View File

@ -1,6 +1,6 @@
from description import Description
from workspaceObject import WorkspaceObject
import formulas
from .description import Description
from .workspaceObject import WorkspaceObject
from . import formulas
class Group(WorkspaceObject):

View File

@ -1,4 +1,4 @@
from workspaceObject import WorkspaceObject
from .workspaceObject import WorkspaceObject
class Letter(WorkspaceObject):

View File

@ -1,4 +1,4 @@
from workspaceStructure import WorkspaceStructure
from .workspaceStructure import WorkspaceStructure
class Replacement(WorkspaceStructure):

View File

@ -1,8 +1,8 @@
import logging
from workspaceStructure import WorkspaceStructure
import formulas
from .workspaceStructure import WorkspaceStructure
from . import formulas
class Rule(WorkspaceStructure):

View File

@ -1,5 +1,5 @@
from slipnode import Slipnode
from sliplink import Sliplink
from .slipnode import Slipnode
from .sliplink import Sliplink
class Slipnet(object):

View File

@ -1,6 +1,6 @@
import unittest
from copycat import Copycat
from .copycat import Copycat
def pnormaldist(p):
@ -20,7 +20,7 @@ def pnormaldist(p):
0.99999999: 5.7307,
0.999999999: 6.1094,
}
return max(v for k, v in table.iteritems() if k <= p)
return max(v for k, v in table.items() if k <= p)
def lower_bound_on_probability(hits, attempts, confidence=0.95):
@ -44,11 +44,11 @@ class TestCopycat(unittest.TestCase):
self.longMessage = True # new in Python 2.7
def assertProbabilitiesLookRoughlyLike(self, actual, expected):
actual_count = 0.0 + sum(d['count'] for d in actual.values())
expected_count = 0.0 + sum(d['count'] for d in expected.values())
actual_count = 0.0 + sum(d['count'] for d in list(actual.values()))
expected_count = 0.0 + sum(d['count'] for d in list(expected.values()))
self.assertGreater(actual_count, 1)
self.assertGreater(expected_count, 1)
for k in set(actual.keys() + expected.keys()):
for k in set(list(actual.keys()) + list(expected.keys())):
if k not in expected:
self.fail('Key %s was produced but not expected! %r != %r' % (k, actual, expected))
expected_probability = expected[k]['count'] / expected_count
@ -56,10 +56,10 @@ class TestCopycat(unittest.TestCase):
actual_lo = lower_bound_on_probability(actual[k]['count'], actual_count)
actual_hi = upper_bound_on_probability(actual[k]['count'], actual_count)
if not (actual_lo <= expected_probability <= actual_hi):
print 'Failed (%s <= %s <= %s)' % (actual_lo, expected_probability, actual_hi)
print('Failed (%s <= %s <= %s)' % (actual_lo, expected_probability, actual_hi))
self.fail('Count ("obviousness" metric) seems way off! %r != %r' % (actual, expected))
if abs(actual[k]['avgtemp'] - expected[k]['avgtemp']) >= 10.0 + (10.0 / actual[k]['count']):
print 'Failed (%s - %s >= %s)' % (actual[k]['avgtemp'], expected[k]['avgtemp'], 10.0 + (10.0 / actual[k]['count']))
print('Failed (%s - %s >= %s)' % (actual[k]['avgtemp'], expected[k]['avgtemp'], 10.0 + (10.0 / actual[k]['count'])))
self.fail('Temperature ("elegance" metric) seems way off! %r != %r' % (actual, expected))
else:
actual_hi = upper_bound_on_probability(0, actual_count)
@ -68,7 +68,7 @@ class TestCopycat(unittest.TestCase):
def run_testcase(self, initial, modified, target, iterations, expected):
actual = Copycat().run(initial, modified, target, iterations)
self.assertEqual(sum(a['count'] for a in actual.values()), iterations)
self.assertEqual(sum(a['count'] for a in list(actual.values())), iterations)
self.assertProbabilitiesLookRoughlyLike(actual, expected)
def test_simple_cases(self):

View File

@ -1,8 +1,8 @@
import formulas
from bond import Bond
from correspondence import Correspondence
from letter import Letter
from workspaceString import WorkspaceString
from . import formulas
from .bond import Bond
from .correspondence import Correspondence
from .letter import Letter
from .workspaceString import WorkspaceString
def __adjustUnhappiness(values):

View File

@ -1,6 +1,6 @@
from description import Description
from formulas import weightedAverage
from workspaceStructure import WorkspaceStructure
from .description import Description
from .formulas import weightedAverage
from .workspaceStructure import WorkspaceStructure
class WorkspaceObject(WorkspaceStructure):
@ -109,7 +109,7 @@ class WorkspaceObject(WorkspaceStructure):
if d.descriptionType.fully_active()]
def getPossibleDescriptions(self, descriptionType):
from group import Group # gross, TODO FIXME
from .group import Group # gross, TODO FIXME
slipnet = self.ctx.slipnet
descriptions = []
for link in descriptionType.instanceLinks:

View File

@ -1,5 +1,5 @@
from group import Group
from letter import Letter
from .group import Group
from .letter import Letter
class WorkspaceString(object):

View File

@ -1,4 +1,4 @@
import formulas
from . import formulas
class WorkspaceStructure(object):

3
copycat/curses_main.py → curses_main.py Normal file → Executable file
View File

@ -1,9 +1,10 @@
#!/usr/bin/env python3
import argparse
import curses
import logging
from copycat import Copycat
from curses_reporter import CursesReporter
from copycat.curses_reporter import CursesReporter
if __name__ == '__main__':

16
copycat/main.py → main.py Normal file → Executable file
View File

@ -1,17 +1,16 @@
#!/usr/bin/env python3
import argparse
import logging
from copycat import Copycat, Reporter
class SimpleReporter(Reporter):
def report_answer(self, answer):
print 'Answered %s (time %d, final temperature %.1f)' % (
print('Answered %s (time %d, final temperature %.1f)' % (
answer['answer'], answer['time'], answer['temp'],
)
))
if __name__ == '__main__':
def main():
logging.basicConfig(level=logging.INFO, format='%(message)s', filename='./copycat.log', filemode='w')
parser = argparse.ArgumentParser()
@ -25,5 +24,8 @@ if __name__ == '__main__':
copycat = Copycat(reporter=SimpleReporter(), rng_seed=options.seed)
answers = copycat.run(options.initial, options.modified, options.target, options.iterations)
for answer, d in sorted(answers.iteritems(), key=lambda kv: kv[1]['avgtemp']):
print '%s: %d (avg time %.1f, avg temp %.1f)' % (answer, d['count'], d['avgtime'], d['avgtemp'])
for answer, d in sorted(iter(answers.items()), key=lambda kv: kv[1]['avgtemp']):
print('%s: %d (avg time %.1f, avg temp %.1f)' % (answer, d['count'], d['avgtime'], d['avgtemp']))
if __name__ == '__main__':
main()