| @@ -1,15 +0,0 @@ | |||||
| # Anders & Briegel in Python | |||||
| Implementing Anders & Briegel "Fast simulation of stabilizer circuits using a graph state representation" in Python. | |||||
| Work in progress: use at your own risk. | |||||
| <!-- Server--> | |||||
| <!--The graph state can be visualized and edited in a browser using the built-in web server.--> | |||||
| <!--To get a blank canvas, run `python abp/server.py` and open `localhost:8000` in a web browser.--> | |||||
| <!--This can also be used to visualize the state of programs during execution. See `examples/visualize.py` for an example of how to do this.--> | |||||
| @@ -1,3 +1,4 @@ | |||||
| # Alias some stuff to make imports cleaner | # Alias some stuff to make imports cleaner | ||||
| from abp.graphstate import GraphState | from abp.graphstate import GraphState | ||||
| from abp.qi import CircuitModel | from abp.qi import CircuitModel | ||||
| from abp.graphstate import VisibleGraphState | |||||
| @@ -0,0 +1,48 @@ | |||||
| import requests | |||||
| import abp, json | |||||
| class ClientError(Exception): | |||||
| def __init__(self, message): | |||||
| self.message = message | |||||
| class Client(object): | |||||
| def __init__(self, host="localhost", port=5000, clear=False): | |||||
| self.session = requests.Session() | |||||
| self.root = "http://{}:{}".format(host, port) | |||||
| if clear: | |||||
| self.clear() | |||||
| def get(self, endpoint): | |||||
| url =self.root+endpoint | |||||
| response = self.session.get(url) | |||||
| if response.status_code == 404: | |||||
| message = "404. Check that the server is running!".format(self.root, endpoint) | |||||
| raise ClientError(message) | |||||
| return response.content | |||||
| def get_state(self): | |||||
| response = self.get("/state") | |||||
| output = abp.GraphState() | |||||
| output.from_json(json.loads(response)) | |||||
| return output | |||||
| def set_state(self, state): | |||||
| response = self.session.post(self.root+"/state", data=state.to_json()) | |||||
| if not response.status_code == 200: | |||||
| print response.status_code | |||||
| return response.content | |||||
| def add_node(self, node): | |||||
| return self.get("/add_node/{}".format(node)) | |||||
| def act_local_rotation(self, node, operation): | |||||
| return self.get("/act_local_rotation/{}/{}".format(node, operation)) | |||||
| def act_cz(self, a, b): | |||||
| return self.get("/act_cz/{}/{}".format(a, b)) | |||||
| def clear(self): | |||||
| return self.get("/clear") | |||||
| def kill(self): | |||||
| self.session.close() | |||||
| @@ -6,16 +6,14 @@ import itertools as it | |||||
| import clifford | import clifford | ||||
| import json | import json | ||||
| import qi | import qi | ||||
| import shelve | |||||
| try: | |||||
| import networkx as nx | |||||
| except ImportError: | |||||
| print "Could not import networkx: layout will not work" | |||||
| import networkx as nx | |||||
| from websocket import create_connection | |||||
| import atexit | |||||
| class BaseGraphState(object): | |||||
| class GraphState(object): | |||||
| def __init__(self, nodes = []): | |||||
| def __init__(self, nodes=[]): | |||||
| self.ngbh = {} | self.ngbh = {} | ||||
| self.vops = {} | self.vops = {} | ||||
| self.meta = {} | self.meta = {} | ||||
| @@ -24,7 +22,6 @@ class BaseGraphState(object): | |||||
| except TypeError: | except TypeError: | ||||
| self.add_nodes(xrange(nodes)) | self.add_nodes(xrange(nodes)) | ||||
| def add_node(self, v): | def add_node(self, v): | ||||
| """ Add a node """ | """ Add a node """ | ||||
| self.ngbh[v] = set() | self.ngbh[v] = set() | ||||
| @@ -161,7 +158,7 @@ class BaseGraphState(object): | |||||
| """ Reconstruct from JSON """ | """ Reconstruct from JSON """ | ||||
| self.__init__([]) | self.__init__([]) | ||||
| self.vops = {int(key): value for key, value in data["nodes"].items()} | self.vops = {int(key): value for key, value in data["nodes"].items()} | ||||
| self.meta = {int(key): value for key, value in data["meta"].items()} | |||||
| self.meta = {int(key): value for key, value in data["meta"].items()} | |||||
| self.ngbh = {int(key): set() for key in self.vops} | self.ngbh = {int(key): set() for key in self.vops} | ||||
| self.add_edges(data["edges"]) | self.add_edges(data["edges"]) | ||||
| @@ -190,7 +187,7 @@ class BaseGraphState(object): | |||||
| def layout(self): | def layout(self): | ||||
| """ Automatically lay out the graph """ | """ Automatically lay out the graph """ | ||||
| if self.order()==0: | |||||
| if self.order() == 0: | |||||
| return | return | ||||
| g = self.to_networkx() | g = self.to_networkx() | ||||
| pos = nx.spring_layout(g, dim=3, scale=10) | pos = nx.spring_layout(g, dim=3, scale=10) | ||||
| @@ -199,8 +196,8 @@ class BaseGraphState(object): | |||||
| ax, ay, az = average(0), average(1), average(2) | ax, ay, az = average(0), average(1), average(2) | ||||
| for key, (x, y, z) in pos.items(): | for key, (x, y, z) in pos.items(): | ||||
| self.meta[key]["pos"] = { | self.meta[key]["pos"] = { | ||||
| "x": x - ax, | |||||
| "y": y - ay, | |||||
| "x": x - ax, | |||||
| "y": y - ay, | |||||
| "z": z - az} | "z": z - az} | ||||
| def to_stabilizer(self): | def to_stabilizer(self): | ||||
| @@ -232,10 +229,31 @@ class BaseGraphState(object): | |||||
| """ Check equality between graphs """ | """ Check equality between graphs """ | ||||
| return self.ngbh == other.ngbh and self.vops == other.vops | return self.ngbh == other.ngbh and self.vops == other.vops | ||||
| class DiffedGraphState(BaseGraphState): | |||||
| pass | |||||
| class GraphState(BaseGraphState): | |||||
| pass | |||||
| class VisibleGraphState(GraphState): | |||||
| def __init__(self, *args, **kwargs): | |||||
| GraphState.__init__(self, *args, **kwargs) | |||||
| self.ws = create_connection("ws://localhost:5001") | |||||
| atexit.register(self.ws.close) | |||||
| self.send("clear") | |||||
| def send(self, method, *args, **kwargs): | |||||
| kwargs.update({"method": method}) | |||||
| self.ws.send(json.dumps(kwargs)) | |||||
| def add_node(self, node): | |||||
| GraphState.add_node(self, node) | |||||
| self.send("add_node", node=node) | |||||
| def add_edge(self, start, end): | |||||
| GraphState.add_edge(self, start, end) | |||||
| self.send("add_edge", start=start, end=end) | |||||
| def del_edge(self, start, end): | |||||
| GraphState.del_edge(self, start, end) | |||||
| self.send("del_edge", start=start, end=end) | |||||
| def act_local_rotation(self, node, operation): | |||||
| GraphState.del_edge(self, start, end) | |||||
| self.send("update_vop", node=node, vop=self.vops[node]) | |||||
| @@ -1,21 +0,0 @@ | |||||
| import requests | |||||
| import abp, json | |||||
| import time | |||||
| client = abp.Client(clear=True) | |||||
| client.add_node(0) | |||||
| client.add_node(1) | |||||
| client.add_node(99) | |||||
| client.act_local_rotation(0, 10) | |||||
| client.act_local_rotation(1, 10) | |||||
| client.act_local_rotation(99, 10) | |||||
| client.act_cz(0, 1) | |||||
| client.act_cz(0, 99) | |||||
| client.act_cz(1, 99) | |||||
| for i in range(10): | |||||
| client.add_node(i+10) | |||||
| client.act_local_rotation(i+10, 10) | |||||
| client.act_cz(0, i+10) | |||||
| print client.get_state() | |||||
| @@ -0,0 +1,4 @@ | |||||
| from abp import VisibleGraphState | |||||
| s = VisibleGraphState() | |||||
| s.add_node(0) | |||||
| @@ -0,0 +1,38 @@ | |||||
| import abp | |||||
| import atexit | |||||
| import json | |||||
| from websocket import create_connection | |||||
| class ServedState(abp.GraphState): | |||||
| def __init__(self): | |||||
| abp.GraphState.__init__(self) | |||||
| self.ws = create_connection("ws://localhost:5001") | |||||
| atexit.register(self.ws.close) | |||||
| self.send("clear") | |||||
| def send(self, method, *args, **kwargs): | |||||
| kwargs.update({"method":method}) | |||||
| self.ws.send(json.dumps(kwargs)) | |||||
| def add_node(self, node): | |||||
| abp.GraphState.add_node(self, node) | |||||
| self.send("add_node", node = node) | |||||
| def add_edge(self, start, end): | |||||
| abp.GraphState.add_edge(self, start, end) | |||||
| self.send("add_edge", start = start, end = end) | |||||
| def del_edge(self, start, end): | |||||
| abp.GraphState.del_edge(self, start, end) | |||||
| self.send("del_edge", start = start, end = end) | |||||
| def del_edge(self, start, end): | |||||
| abp.GraphState.del_edge(self, start, end) | |||||
| self.send("del_edge", start = start, end = end) | |||||
| if __name__ == '__main__': | |||||
| s = ServedState() | |||||
| s.add_node(0) | |||||
| s.add_node(1) | |||||
| s.add_edge(0,1) | |||||
| @@ -0,0 +1,12 @@ | |||||
| <!DOCTYPE html> | |||||
| <html lang="en"> | |||||
| <head> | |||||
| <meta charset="utf-8"> | |||||
| <title>abp</title> | |||||
| </head> | |||||
| <body> | |||||
| <script type="text/javascript" src="poll.js"></script> | |||||
| </body> | |||||
| </html> | |||||
| @@ -0,0 +1,21 @@ | |||||
| function poll() { | |||||
| var ws = new WebSocket("ws://localhost:5001"); | |||||
| ws.onopen = function() | |||||
| { | |||||
| console.log("Connected to server."); | |||||
| }; | |||||
| ws.onmessage = function (evt) | |||||
| { | |||||
| var received_msg = evt.data; | |||||
| console.log("Message received: " + evt.data); | |||||
| }; | |||||
| ws.onclose = function() | |||||
| { | |||||
| console.log("Connection was closed."); | |||||
| }; | |||||
| } | |||||
| window.onload = poll; | |||||
| @@ -1,31 +1,24 @@ | |||||
| from flask import Flask, request, render_template, jsonify | |||||
| from flask_sockets import Sockets | |||||
| from werkzeug.contrib.cache import SimpleCache | |||||
| import werkzeug.serving | |||||
| import json | |||||
| import abp | |||||
| from websocket_server import WebsocketServer | |||||
| import threading | |||||
| cache = SimpleCache(default_timeout = 10000) | |||||
| cache.set("state", abp.GraphState()) | |||||
| app = Flask(__name__) | |||||
| sockets = Sockets(app) | |||||
| clients = [] | |||||
| state = "awd" | |||||
| @app.route("/") | |||||
| def index(): | |||||
| return render_template("index.html") | |||||
| def new_message(client, server, message): | |||||
| server.send_message_to_all(message) | |||||
| @sockets.route('/diff') | |||||
| def diff_socket(ws): | |||||
| while not ws.closed: | |||||
| message = ws.receive() | |||||
| print message | |||||
| ws.send("Hi from the server, you said '{}'".format(message)) | |||||
| def new_client(client, server): | |||||
| print "Client {} connected.".format(client["id"]) | |||||
| clients.append(client) | |||||
| @werkzeug.serving.run_with_reloader | |||||
| def runServer(): | |||||
| from gevent import pywsgi | |||||
| from geventwebsocket.handler import WebSocketHandler | |||||
| app.debug = True | |||||
| ws = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler) | |||||
| ws.serve_forever() | |||||
| def client_left(client, server): | |||||
| print "Client {} disconnected.".format(client["id"]) | |||||
| clients.remove(client) | |||||
| if __name__ == '__main__': | |||||
| server = WebsocketServer(5001) | |||||
| server.set_fn_new_client(new_client) | |||||
| server.set_fn_message_received(new_message) | |||||
| server.set_fn_client_left(client_left) | |||||
| server.run_forever() | |||||
| @@ -26,14 +26,6 @@ function render() { | |||||
| }); | }); | ||||
| } | } | ||||
| // This just organises kickoff | |||||
| function startMainLoop() { | |||||
| scene = makeScene(); | |||||
| controls.addEventListener("change", render); | |||||
| poll(); | |||||
| render(); | |||||
| } | |||||
| // Someone resized the window | // Someone resized the window | ||||
| function onWindowResize(evt){ | function onWindowResize(evt){ | ||||
| camera.aspect = window.innerWidth / window.innerHeight; | camera.aspect = window.innerWidth / window.innerHeight; | ||||
| @@ -69,8 +61,9 @@ function init() { | |||||
| controls.rotateSpeed = 0.2; | controls.rotateSpeed = 0.2; | ||||
| camera.position.set(0, 0, 40); | camera.position.set(0, 0, 40); | ||||
| // Start polling | |||||
| // Run | // Run | ||||
| startMainLoop(); | |||||
| scene = makeScene(); | |||||
| controls.addEventListener("change", render); | |||||
| poll(); | |||||
| render(); | |||||
| } | } | ||||
| @@ -1,25 +1,20 @@ | |||||
| function poll() { | function poll() { | ||||
| var ws = new WebSocket("ws://localhost:5000/diff"); | |||||
| ws.onopen = function() | |||||
| { | |||||
| // Web Socket is connected, send data using send() | |||||
| ws.send("Hello from the browser! I connected okay"); | |||||
| console.log("Sent a message to the server"); | |||||
| }; | |||||
| ws.onmessage = function (evt) | |||||
| { | |||||
| var received_msg = evt.data; | |||||
| console.log("I got a message from the server:"); | |||||
| console.log(evt.data); | |||||
| var xhr = new XMLHttpRequest(); | |||||
| xhr.timeout = 60000; | |||||
| xhr.onload = function() { | |||||
| var state = JSON.parse(xhr.responseText); | |||||
| updateScene(state); | |||||
| poll(); | |||||
| }; | }; | ||||
| ws.onclose = function() | |||||
| { | |||||
| ws.send("Bye by from the browser"); | |||||
| console.log("Connection is closed..."); | |||||
| xhr.onerror = function(e){ | |||||
| poll(); | |||||
| }; | }; | ||||
| xhr.open("GET", "/state", true); | |||||
| xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); | |||||
| xhr.send(); | |||||
| } | } | ||||
| function updateScene(state) { | function updateScene(state) { | ||||
| @@ -3,7 +3,7 @@ import abp, json | |||||
| import time | import time | ||||
| def _test_client(): | |||||
| def test_client(): | |||||
| client = abp.Client(clear=True) | client = abp.Client(clear=True) | ||||
| client.clear() | client.clear() | ||||