{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from collections import defaultdict\n", "\n", "class Executor():\n", " def __init__(self):\n", " self.components = {}\n", " self.to_run = set()\n", " self.sources = []\n", " self.destinations = []\n", " \n", " def execute(self):\n", " while self.to_run:\n", " self.to_run.pop().evaluate(self)\n", " \n", " def add_component(self, name, component):\n", " self.components[name] = component\n", " self.to_run.add(component)\n", " \n", " class Connection():\n", " def __init__(self, source, dest):\n", " self.source = source\n", " self.dest = dest\n", "\n", " def evaluate(self, executor):\n", " executor.set_input(self.dest, executor.get_outval(self.source))\n", " \n", " def add_connection(self, source, destination):\n", " sourceComponent, sourceWire = source.split('.')\n", " destComponent, destWire = destination.split('.')\n", " connection = self.Connection(source, destination)\n", " self.to_run.add(connection)\n", " \n", " self.components[sourceComponent].add_listener(sourceWire, connection)\n", " \n", " def set_input(self, wireDescriptor, val):\n", " component, wire = wireDescriptor.split('.')\n", " self.components[component].set_input(wire, val, self)\n", " \n", " def get_inval(self, descriptor):\n", " component, wire = descriptor.split('.')\n", " return self.components[component].get_input(wire)\n", " \n", " def get_outval(self, descriptor):\n", " component, wire = descriptor.split('.')\n", " return self.components[component].get_output(wire)\n", " \n", " def set_displayset(self, sources, destinations):\n", " self.sources = sources\n", " self.destinations = destinations\n", " \n", " def get_displaystate(self):\n", " sources = {descriptor: self.get_inval(descriptor) for descriptor in self.sources}\n", " destinations = {descriptor: self.get_outval(descriptor) for descriptor in self.destinations}\n", " \n", " return {\n", " 'inputs': sources,\n", " 'outputs': destinations\n", " }\n", " \n", " def queue(self, runnable):\n", " self.to_run.add(runnable)\n", "\n", "class BaseCircuit():\n", " def __init__(self):\n", " self.outputs = {}\n", " self.listeners = defaultdict(lambda: [])\n", " self.inputs = {}\n", " \n", " def outputs(self):\n", " return self.outputs.keys()\n", " \n", " def get_output(self, outkey):\n", " return self.outputs[outkey]\n", " \n", " def set_input(self, inkey, value, executor):\n", " if self.inputs[inkey] != value:\n", " executor.queue(self)\n", " self.inputs[inkey] = value\n", " \n", " def get_input(self, inkey):\n", " return self.inputs[inkey]\n", " \n", " def get_inputs(self):\n", " return self.inputs.keys()\n", " \n", " def add_listener(self, outkey, listener):\n", " self.listeners[outkey].append(listener)\n", " \n", " def _set_output(self, outputs, executor):\n", " for outkey, outval in outputs.items():\n", " if outval != self.outputs[outkey]:\n", " self.outputs[outkey] = outval\n", " for listener in self.listeners[outkey]:\n", " executor.queue(listener)\n", " \n", " def evaluate(self):\n", " raise Exception(\"Evaluate called on abstract BaseCircuit class\")\n", "\n", "class OrGate(BaseCircuit):\n", " def __init__(self):\n", " super().__init__()\n", " self.outputs = {\n", " 'out': False,\n", " }\n", " self.inputs = {\n", " 'a': False,\n", " 'b': False,\n", " }\n", " \n", " def evaluate(self, executor):\n", " print(\"Evaluate got called\")\n", " self._set_output(\n", " {\n", " 'out': self.get_input('a') or self.get_input('b'),\n", " },\n", " executor,\n", " )\n", "\n", "class NorGate(BaseCircuit):\n", " def __init__(self):\n", " super().__init__()\n", " self.outputs = {\n", " 'out': True,\n", " }\n", " self.inputs = {\n", " 'a': False,\n", " 'b': False,\n", " }\n", " \n", " def evaluate(self, executor):\n", " self._set_output(\n", " {\n", " 'out': (not self.get_input('a')) and (not self.get_input('b')),\n", " },\n", " executor,\n", " )" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluate got called\n", "{'inputs': {'orGate.a': False, 'orGate.b': False},\n", " 'outputs': {'orGate.out': False}}\n", "Evaluate got called\n", "Evaluate got called\n", "{'inputs': {'orGate.a': True, 'orGate.b': True},\n", " 'outputs': {'orGate.out': True}}\n", "Evaluate got called\n", "{'inputs': {'orGate.a': False, 'orGate.b': True},\n", " 'outputs': {'orGate.out': True}}\n" ] } ], "source": [ "from pprint import pprint\n", "\n", "executor = Executor()\n", "executor.add_component(\"orGate\", OrGate())\n", "executor.add_connection(\"orGate.out\", \"orGate.b\")\n", "executor.set_displayset(\n", " sources=['orGate.a', 'orGate.b'],\n", " destinations=['orGate.out'],\n", ")\n", "\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input('orGate.a', True)\n", "\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input('orGate.a', False)\n", "\n", "executor.execute()\n", "pprint(executor.get_displaystate())" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'inputs': {'bottomNor.a': False,\n", " 'bottomNor.b': False,\n", " 'topNor.a': False,\n", " 'topNor.b': True},\n", " 'outputs': {'bottomNor.out': True, 'topNor.out': False}}\n", "{'inputs': {'bottomNor.a': False,\n", " 'bottomNor.b': False,\n", " 'topNor.a': True,\n", " 'topNor.b': True},\n", " 'outputs': {'bottomNor.out': True, 'topNor.out': False}}\n", "{'inputs': {'bottomNor.a': False,\n", " 'bottomNor.b': False,\n", " 'topNor.a': False,\n", " 'topNor.b': True},\n", " 'outputs': {'bottomNor.out': True, 'topNor.out': False}}\n", "{'inputs': {'bottomNor.a': True,\n", " 'bottomNor.b': True,\n", " 'topNor.a': False,\n", " 'topNor.b': False},\n", " 'outputs': {'bottomNor.out': False, 'topNor.out': True}}\n", "{'inputs': {'bottomNor.a': True,\n", " 'bottomNor.b': False,\n", " 'topNor.a': False,\n", " 'topNor.b': False},\n", " 'outputs': {'bottomNor.out': False, 'topNor.out': True}}\n" ] } ], "source": [ "executor = Executor()\n", "executor.add_component(\"topNor\", NorGate())\n", "executor.add_component(\"bottomNor\", NorGate())\n", "executor.add_connection(\"topNor.out\", \"bottomNor.a\")\n", "executor.add_connection(\"bottomNor.out\", \"topNor.b\")\n", "executor.set_displayset(\n", " sources=[\"topNor.a\", \"topNor.b\", \"bottomNor.a\", \"bottomNor.b\"],\n", " destinations=[\"topNor.out\", \"bottomNor.out\"],\n", ")\n", "\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"topNor.a\", True)\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"topNor.a\", False)\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"bottomNor.b\", True)\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"bottomNor.b\", False)\n", "executor.execute()\n", "pprint(executor.get_displaystate())" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def parse_circuit(circuit):\n", " executor = Executor()\n", " for name, component in circuit['components'].items():\n", " executor.add_component(name, component)\n", " for source, dest in circuit['connections']:\n", " executor.add_connection(source, dest)\n", " executor.set_displayset(\n", " sources=circuit['in_displayset'],\n", " destinations=circuit['out_displayset'],\n", " )\n", " return executor" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'inputs': {'bottomNor.b': False, 'topNor.a': False},\n", " 'outputs': {'bottomNor.out': True, 'topNor.out': False}}\n", "{'inputs': {'bottomNor.b': False, 'topNor.a': True},\n", " 'outputs': {'bottomNor.out': True, 'topNor.out': False}}\n", "{'inputs': {'bottomNor.b': False, 'topNor.a': False},\n", " 'outputs': {'bottomNor.out': True, 'topNor.out': False}}\n", "{'inputs': {'bottomNor.b': True, 'topNor.a': False},\n", " 'outputs': {'bottomNor.out': False, 'topNor.out': True}}\n", "{'inputs': {'bottomNor.b': False, 'topNor.a': False},\n", " 'outputs': {'bottomNor.out': False, 'topNor.out': True}}\n" ] } ], "source": [ "executor = parse_circuit({\n", " 'components': {\n", " 'topNor': NorGate(),\n", " 'bottomNor': NorGate(),\n", " },\n", " 'connections': [\n", " ('topNor.out', 'bottomNor.a'),\n", " ('bottomNor.out', 'topNor.b'),\n", " ],\n", " 'in_displayset': [\n", " 'topNor.a',\n", " 'bottomNor.b',\n", " ],\n", " 'out_displayset': [\n", " 'topNor.out',\n", " 'bottomNor.out',\n", " ],\n", " })\n", "\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"topNor.a\", True)\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"topNor.a\", False)\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"bottomNor.b\", True)\n", "executor.execute()\n", "pprint(executor.get_displaystate())\n", "\n", "executor.set_input(\"bottomNor.b\", False)\n", "executor.execute()\n", "pprint(executor.get_displaystate())" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [conda env:anaconda3]", "language": "python", "name": "conda-env-anaconda3-py" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 1 }