Merge branch 'feature-gui' into develop
This commit is contained in:
@ -24,25 +24,22 @@ class Reporter(object):
|
|||||||
|
|
||||||
|
|
||||||
class Copycat(object):
|
class Copycat(object):
|
||||||
def __init__(self, rng_seed=None, reporter=None, showgui=True):
|
def __init__(self, rng_seed=None, reporter=None, gui=False):
|
||||||
self.coderack = Coderack(self)
|
self.coderack = Coderack(self)
|
||||||
self.random = Randomness(rng_seed)
|
self.random = Randomness(rng_seed)
|
||||||
self.slipnet = Slipnet()
|
self.slipnet = Slipnet()
|
||||||
self.temperature = Temperature() # TODO: use entropy
|
self.temperature = Temperature() # TODO: use entropy
|
||||||
self.workspace = Workspace(self)
|
self.workspace = Workspace(self)
|
||||||
self.reporter = reporter or Reporter()
|
self.reporter = reporter or Reporter()
|
||||||
self.showgui = showgui
|
if gui:
|
||||||
self.gui = GUI('Copycat')
|
self.gui = GUI('Copycat')
|
||||||
self.lastUpdate = float('-inf')
|
self.lastUpdate = float('-inf')
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
if (not self.showgui) or (self.showgui and (not self.gui.app.primary.control.paused or self.gui.app.primary.control.has_step())):
|
self.coderack.chooseAndRunCodelet()
|
||||||
self.coderack.chooseAndRunCodelet()
|
self.reporter.report_coderack(self.coderack)
|
||||||
self.reporter.report_coderack(self.coderack)
|
self.reporter.report_temperature(self.temperature)
|
||||||
self.reporter.report_temperature(self.temperature)
|
self.reporter.report_workspace(self.workspace)
|
||||||
self.reporter.report_workspace(self.workspace)
|
|
||||||
if (self.showgui):
|
|
||||||
self.gui.update(self)
|
|
||||||
|
|
||||||
def update_workspace(self, currentTime):
|
def update_workspace(self, currentTime):
|
||||||
self.workspace.updateEverything()
|
self.workspace.updateEverything()
|
||||||
@ -55,15 +52,12 @@ class Copycat(object):
|
|||||||
def check_reset(self):
|
def check_reset(self):
|
||||||
if self.gui.app.primary.control.go:
|
if self.gui.app.primary.control.go:
|
||||||
initial, modified, target = self.gui.app.primary.control.get_vars()
|
initial, modified, target = self.gui.app.primary.control.get_vars()
|
||||||
self.reset_with_strings(initial, modified, target)
|
self.gui.app.reset_with_strings(initial, modified, target)
|
||||||
|
self.workspace.resetWithStrings(initial, modified, target)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def reset_with_strings(self, initial, modified, target):
|
|
||||||
self.workspace.resetWithStrings(initial, modified, target)
|
|
||||||
self.gui.app.reset_with_strings(initial, modified, target)
|
|
||||||
|
|
||||||
def mainLoop(self):
|
def mainLoop(self):
|
||||||
currentTime = self.coderack.codeletsRun
|
currentTime = self.coderack.codeletsRun
|
||||||
self.temperature.tryUnclamp(currentTime) # TODO: use entropy
|
self.temperature.tryUnclamp(currentTime) # TODO: use entropy
|
||||||
@ -72,8 +66,6 @@ class Copycat(object):
|
|||||||
self.update_workspace(currentTime)
|
self.update_workspace(currentTime)
|
||||||
self.step()
|
self.step()
|
||||||
|
|
||||||
if self.showgui:
|
|
||||||
self.gui.refresh()
|
|
||||||
|
|
||||||
def runTrial(self):
|
def runTrial(self):
|
||||||
"""Run a trial of the copycat algorithm"""
|
"""Run a trial of the copycat algorithm"""
|
||||||
@ -99,18 +91,18 @@ class Copycat(object):
|
|||||||
while True:
|
while True:
|
||||||
if self.check_reset():
|
if self.check_reset():
|
||||||
answers = {}
|
answers = {}
|
||||||
answer = self.runTrial()
|
self.gui.refresh()
|
||||||
if self.showgui:
|
if not self.gui.paused():
|
||||||
self.gui.app.log('Answered: {}'.format(answer['answer']))
|
answer = self.runTrial()
|
||||||
d = answers.setdefault(answer['answer'], {
|
self.gui.update(self)
|
||||||
'count': 0,
|
d = answers.setdefault(answer['answer'], {
|
||||||
'sumtemp': 0,
|
'count': 0,
|
||||||
'sumtime': 0
|
'sumtemp': 0,
|
||||||
})
|
'sumtime': 0
|
||||||
d['count'] += 1
|
})
|
||||||
d['sumtemp'] += answer['temp']
|
d['count'] += 1
|
||||||
d['sumtime'] += answer['time']
|
d['sumtemp'] += answer['temp']
|
||||||
if self.showgui:
|
d['sumtime'] += answer['time']
|
||||||
self.gui.add_answers(answers)
|
self.gui.add_answers(answers)
|
||||||
|
|
||||||
for answer, d in answers.items():
|
for answer, d in answers.items():
|
||||||
@ -118,16 +110,12 @@ class Copycat(object):
|
|||||||
d['avgtime'] = d.pop('sumtime') / d['count']
|
d['avgtime'] = d.pop('sumtime') / d['count']
|
||||||
|
|
||||||
def run(self, initial, modified, target, iterations):
|
def run(self, initial, modified, target, iterations):
|
||||||
self.reset_with_strings(initial, modified, target)
|
|
||||||
self.temperature.useAdj('best')
|
self.temperature.useAdj('best')
|
||||||
|
self.gui.app.reset_with_strings(initial, modified, target)
|
||||||
|
self.workspace.resetWithStrings(initial, modified, target)
|
||||||
answers = {}
|
answers = {}
|
||||||
for i in range(iterations):
|
for i in range(iterations):
|
||||||
if self.check_reset():
|
|
||||||
answers = {}
|
|
||||||
answer = self.runTrial()
|
answer = self.runTrial()
|
||||||
if self.showgui:
|
|
||||||
self.gui.app.log('Answered: {}'.format(answer['answer']))
|
|
||||||
d = answers.setdefault(answer['answer'], {
|
d = answers.setdefault(answer['answer'], {
|
||||||
'count': 0,
|
'count': 0,
|
||||||
'sumtemp': 0, # TODO: use entropy
|
'sumtemp': 0, # TODO: use entropy
|
||||||
@ -136,8 +124,6 @@ class Copycat(object):
|
|||||||
d['count'] += 1
|
d['count'] += 1
|
||||||
d['sumtemp'] += answer['temp'] # TODO: use entropy
|
d['sumtemp'] += answer['temp'] # TODO: use entropy
|
||||||
d['sumtime'] += answer['time']
|
d['sumtime'] += answer['time']
|
||||||
if self.showgui:
|
|
||||||
self.gui.add_answers(answers)
|
|
||||||
|
|
||||||
for answer, d in answers.items():
|
for answer, d in answers.items():
|
||||||
d['avgtemp'] = d.pop('sumtemp') / d['count']
|
d['avgtemp'] = d.pop('sumtemp') / d['count']
|
||||||
@ -145,7 +131,6 @@ class Copycat(object):
|
|||||||
return answers
|
return answers
|
||||||
|
|
||||||
def run_forever(self, initial, modified, target):
|
def run_forever(self, initial, modified, target):
|
||||||
self.reset_with_strings(initial, modified, target)
|
self.workspace.resetWithStrings(initial, modified, target)
|
||||||
while True:
|
while True:
|
||||||
self.check_reset()
|
|
||||||
self.runTrial()
|
self.runTrial()
|
||||||
|
|||||||
39
copycat/gui/gui.py
Executable file → Normal file
39
copycat/gui/gui.py
Executable file → Normal file
@ -30,25 +30,18 @@ class MainApplication(GridFrame):
|
|||||||
self.add(self.primary, 0, 0, xspan=2)
|
self.add(self.primary, 0, 0, xspan=2)
|
||||||
self.create_widgets()
|
self.create_widgets()
|
||||||
GridFrame.configure(self)
|
GridFrame.configure(self)
|
||||||
|
|
||||||
#self.messages = []
|
|
||||||
|
|
||||||
#def log(self, message):
|
|
||||||
# self.messages.append(message)
|
|
||||||
|
|
||||||
def create_widgets(self):
|
def create_widgets(self):
|
||||||
self.slipList = List(self, 10)
|
columns = 20
|
||||||
|
self.slipList = List(self, columns)
|
||||||
self.add(self.slipList, 0, 1)
|
self.add(self.slipList, 0, 1)
|
||||||
|
|
||||||
self.codeletList = List(self, 10)
|
self.codeletList = List(self, columns)
|
||||||
self.add(self.codeletList, 1, 1)
|
self.add(self.codeletList, 1, 1)
|
||||||
|
|
||||||
self.objectList = List(self, 10)
|
self.objectList = List(self, columns)
|
||||||
self.add(self.objectList, 2, 1)
|
self.add(self.objectList, 2, 1)
|
||||||
|
|
||||||
#self.logBox = List(self, 10)
|
|
||||||
#self.add(self.logBox, 1, 0)
|
|
||||||
|
|
||||||
self.graph2 = Plot(self, 'Answer Distribution')
|
self.graph2 = Plot(self, 'Answer Distribution')
|
||||||
self.add(self.graph2, 2, 0)
|
self.add(self.graph2, 2, 0)
|
||||||
|
|
||||||
@ -62,14 +55,24 @@ class MainApplication(GridFrame):
|
|||||||
self.slipList.update(slipnodes, key=lambda s:s.activation,
|
self.slipList.update(slipnodes, key=lambda s:s.activation,
|
||||||
formatter=lambda s : '{}: {}'.format(s.name, round(s.activation, 2)))
|
formatter=lambda s : '{}: {}'.format(s.name, round(s.activation, 2)))
|
||||||
self.codeletList.update(codelets, key=lambda c:c.urgency, formatter= lambda s : '{}: {}'.format(s.name, round(s.urgency, 2)))
|
self.codeletList.update(codelets, key=lambda c:c.urgency, formatter= lambda s : '{}: {}'.format(s.name, round(s.urgency, 2)))
|
||||||
self.objectList.update(objects, formatter=lambda s : '{}'.format(str(s.descriptions)))
|
get_descriptors = lambda s : ', '.join('({}={})'.format(d.descriptionType.name, d.descriptor.name) for d in s.descriptions)
|
||||||
#self.logBox.update(list(reversed(self.messages))[:10])
|
self.objectList.update(objects, formatter=lambda s : '{}: {}'.format(s, get_descriptors(s)))
|
||||||
|
'''
|
||||||
|
if len(objects) > 0:
|
||||||
|
print('Descriptions:')
|
||||||
|
for obj in objects:
|
||||||
|
print(obj)
|
||||||
|
for description in obj.descriptions:
|
||||||
|
print(' {}:'.format(description))
|
||||||
|
print(' {}'.format(description.descriptionType.name))
|
||||||
|
print(' {}'.format(description.descriptor.name))
|
||||||
|
'''
|
||||||
|
|
||||||
def reset_with_strings(self, initial, modified, target):
|
def reset_with_strings(self, initial, modified, target):
|
||||||
self.primary.reset_with_strings(initial, modified, target)
|
self.primary.reset_with_strings(initial, modified, target)
|
||||||
|
|
||||||
class GUI(object):
|
class GUI(object):
|
||||||
def __init__(self, title, updateInterval=.1):
|
def __init__(self, title):
|
||||||
self.root = tk.Tk()
|
self.root = tk.Tk()
|
||||||
self.root.title(title)
|
self.root.title(title)
|
||||||
tk.Grid.rowconfigure(self.root, 0, weight=1)
|
tk.Grid.rowconfigure(self.root, 0, weight=1)
|
||||||
@ -79,9 +82,6 @@ class GUI(object):
|
|||||||
|
|
||||||
configure_style(ttk.Style())
|
configure_style(ttk.Style())
|
||||||
|
|
||||||
self.lastUpdated = time.time()
|
|
||||||
self.updateInterval = updateInterval
|
|
||||||
|
|
||||||
def add_answers(self, answers):
|
def add_answers(self, answers):
|
||||||
def modifier(status):
|
def modifier(status):
|
||||||
with plt.style.context(('dark_background')):
|
with plt.style.context(('dark_background')):
|
||||||
@ -92,7 +92,8 @@ class GUI(object):
|
|||||||
self.root.update_idletasks()
|
self.root.update_idletasks()
|
||||||
self.root.update()
|
self.root.update()
|
||||||
|
|
||||||
|
def paused(self):
|
||||||
|
return self.app.primary.control.paused
|
||||||
|
|
||||||
def update(self, copycat):
|
def update(self, copycat):
|
||||||
current = time.time()
|
|
||||||
self.app.update(copycat)
|
self.app.update(copycat)
|
||||||
self.lastUpdated = current
|
|
||||||
|
|||||||
@ -7,66 +7,23 @@ from tkinter import filedialog
|
|||||||
from .control import Control
|
from .control import Control
|
||||||
from .gridframe import GridFrame
|
from .gridframe import GridFrame
|
||||||
|
|
||||||
font1Size = 32
|
from .workspacecanvas import WorkspaceCanvas
|
||||||
font2Size = 16
|
|
||||||
font1 = ('Helvetica', str(font1Size))
|
|
||||||
font2 = ('Helvetica', str(font2Size))
|
|
||||||
|
|
||||||
style = dict(background='black',
|
|
||||||
foreground='white',
|
|
||||||
font=font2)
|
|
||||||
|
|
||||||
def create_main_canvas(root, initial, final, new, guess):
|
|
||||||
padding = 100
|
|
||||||
|
|
||||||
canvas = tk.Canvas(root, background='black')
|
|
||||||
|
|
||||||
def add_sequences(sequences, x, y):
|
|
||||||
for sequence in sequences:
|
|
||||||
x += padding
|
|
||||||
if sequence is None:
|
|
||||||
sequence = ''
|
|
||||||
for char in sequence:
|
|
||||||
canvas.create_text(x, y, text=char, anchor=tk.NW, font=font1, fill='white')
|
|
||||||
x += font1Size
|
|
||||||
return x, y
|
|
||||||
|
|
||||||
x = 0
|
|
||||||
y = padding
|
|
||||||
|
|
||||||
add_sequences([initial, final], x, y)
|
|
||||||
|
|
||||||
x = 0
|
|
||||||
y += padding
|
|
||||||
|
|
||||||
add_sequences([new, guess], x, y)
|
|
||||||
|
|
||||||
#canvas['height'] = str(int(canvas['height']) + padding)
|
|
||||||
#canvas['width'] = str(int(canvas['width']) + padding)
|
|
||||||
|
|
||||||
return canvas
|
|
||||||
|
|
||||||
class Primary(GridFrame):
|
class Primary(GridFrame):
|
||||||
|
|
||||||
def __init__(self, parent, *args, **kwargs):
|
def __init__(self, parent, *args, **kwargs):
|
||||||
GridFrame.__init__(self, parent, *args, **kwargs)
|
GridFrame.__init__(self, parent, *args, **kwargs)
|
||||||
|
|
||||||
self.initial = ''
|
self.canvas = WorkspaceCanvas(self)
|
||||||
self.modified = ''
|
|
||||||
self.target = ''
|
|
||||||
|
|
||||||
self.canvas = create_main_canvas(self, self.initial, self.modified, self.target, '')
|
|
||||||
self.add(self.canvas, 0, 0, xspan=2)
|
self.add(self.canvas, 0, 0, xspan=2)
|
||||||
|
|
||||||
self.control = Control(self)
|
self.control = Control(self)
|
||||||
self.add(self.control, 0, 2)
|
self.add(self.control, 0, 2)
|
||||||
|
|
||||||
GridFrame.configure(self)
|
GridFrame.configure(self)
|
||||||
|
|
||||||
def update(self, copycat):
|
def update(self, copycat):
|
||||||
answer = '' if copycat.workspace.rule is None else copycat.workspace.rule.buildTranslatedRule()
|
self.canvas.update(copycat)
|
||||||
#self.canvas = create_main_canvas(self, self.initial, self.modified, self.target, answer)
|
|
||||||
#self.add(self.canvas, 0, 0, xspan=2)
|
|
||||||
|
|
||||||
def reset_with_strings(self, initial, modified, target):
|
def reset_with_strings(self, initial, modified, target):
|
||||||
self.initial = initial
|
self.canvas.reset_with_strings(initial, modified, target)
|
||||||
self.modified = modified
|
|
||||||
self.target = target
|
|
||||||
|
|||||||
159787
copycat/gui/sys
Normal file
159787
copycat/gui/sys
Normal file
File diff suppressed because it is too large
Load Diff
3093
copycat/gui/time
Normal file
3093
copycat/gui/time
Normal file
File diff suppressed because it is too large
Load Diff
69
copycat/gui/workspacecanvas.py
Normal file
69
copycat/gui/workspacecanvas.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
import tkinter.ttk as ttk
|
||||||
|
|
||||||
|
from .gridframe import GridFrame
|
||||||
|
|
||||||
|
font1Size = 32
|
||||||
|
font1 = ('Helvetica', font1Size)
|
||||||
|
|
||||||
|
class WorkspaceCanvas(GridFrame):
|
||||||
|
|
||||||
|
def __init__(self, parent, *args, **kwargs):
|
||||||
|
GridFrame.__init__(self, parent, *args, **kwargs)
|
||||||
|
|
||||||
|
self.chars = []
|
||||||
|
|
||||||
|
self.initial = ''
|
||||||
|
self.modified = ''
|
||||||
|
self.target = ''
|
||||||
|
self.answer = ''
|
||||||
|
|
||||||
|
self.changed = False
|
||||||
|
|
||||||
|
self.canvas = tk.Canvas(self, background='black')
|
||||||
|
self.add(self.canvas, 0, 0)
|
||||||
|
|
||||||
|
GridFrame.configure(self)
|
||||||
|
|
||||||
|
def update(self, copycat):
|
||||||
|
answer = '' if copycat.workspace.rule is None else copycat.workspace.rule.buildTranslatedRule()
|
||||||
|
if answer != self.answer:
|
||||||
|
self.changed = True
|
||||||
|
|
||||||
|
if self.changed:
|
||||||
|
self.canvas.delete('all')
|
||||||
|
del self.chars[:]
|
||||||
|
self.add_text()
|
||||||
|
|
||||||
|
def add_text(self):
|
||||||
|
padding = 100
|
||||||
|
|
||||||
|
def add_sequences(sequences, x, y):
|
||||||
|
for sequence in sequences:
|
||||||
|
x += padding
|
||||||
|
if sequence is None:
|
||||||
|
sequence = ''
|
||||||
|
for char in sequence:
|
||||||
|
self.chars.append((char, (x, y)))
|
||||||
|
self.canvas.create_text(x, y, text=char, anchor=tk.NW, font=font1, fill='white')
|
||||||
|
x += font1Size
|
||||||
|
return x, y
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
y = padding
|
||||||
|
|
||||||
|
add_sequences([self.initial, self.modified], x, y)
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
y += padding
|
||||||
|
|
||||||
|
add_sequences([self.target, self.answer], x, y)
|
||||||
|
|
||||||
|
def reset_with_strings(self, initial, modified, target):
|
||||||
|
if initial != self.initial or \
|
||||||
|
modified != self.modified or \
|
||||||
|
target != self.target:
|
||||||
|
self.changed = True
|
||||||
|
self.initial = initial
|
||||||
|
self.modified = modified
|
||||||
|
self.target = target
|
||||||
2
gui.py
2
gui.py
@ -17,7 +17,7 @@ def main():
|
|||||||
parser.add_argument('--seed', type=int, default=None, help='Provide a deterministic seed for the RNG.')
|
parser.add_argument('--seed', type=int, default=None, help='Provide a deterministic seed for the RNG.')
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
|
|
||||||
copycat = Copycat(reporter=SimpleReporter(), rng_seed=options.seed)
|
copycat = Copycat(reporter=SimpleReporter(), rng_seed=options.seed, gui=True)
|
||||||
copycat.runGUI()
|
copycat.runGUI()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user