From 3a39a49ef00905aa9e36c3a6b1f8cc2c374fd803 Mon Sep 17 00:00:00 2001 From: Pete Shadbolt Date: Mon, 16 May 2016 23:36:04 +0100 Subject: [PATCH] Looks a little more promising --- README.mkd | 15 ------------- abp/__init__.py | 1 + abp/client.py | 48 +++++++++++++++++++++++++++++++++++++++++ abp/graphstate.py | 50 +++++++++++++++++++++++++++++-------------- examples/client.py | 21 ------------------ server/client.py | 4 ++++ server/client2.py | 38 ++++++++++++++++++++++++++++++++ server/index.html | 12 +++++++++++ server/poll.js | 21 ++++++++++++++++++ server/server.py | 45 ++++++++++++++++---------------------- server/static/main.js | 15 ++++--------- server/static/poll.js | 33 ++++++++++++---------------- tests/test_client.py | 2 +- 13 files changed, 196 insertions(+), 109 deletions(-) delete mode 100644 README.mkd create mode 100644 abp/client.py delete mode 100644 examples/client.py create mode 100644 server/client.py create mode 100644 server/client2.py create mode 100644 server/index.html create mode 100644 server/poll.js diff --git a/README.mkd b/README.mkd deleted file mode 100644 index abc2d8c..0000000 --- a/README.mkd +++ /dev/null @@ -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. - - - - - - - - - - diff --git a/abp/__init__.py b/abp/__init__.py index a2258ac..a3b1ee4 100644 --- a/abp/__init__.py +++ b/abp/__init__.py @@ -1,3 +1,4 @@ # Alias some stuff to make imports cleaner from abp.graphstate import GraphState from abp.qi import CircuitModel +from abp.graphstate import VisibleGraphState diff --git a/abp/client.py b/abp/client.py new file mode 100644 index 0000000..7d127cb --- /dev/null +++ b/abp/client.py @@ -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() diff --git a/abp/graphstate.py b/abp/graphstate.py index 0970a25..79f1041 100644 --- a/abp/graphstate.py +++ b/abp/graphstate.py @@ -6,16 +6,14 @@ import itertools as it import clifford import json 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.vops = {} self.meta = {} @@ -24,7 +22,6 @@ class BaseGraphState(object): except TypeError: self.add_nodes(xrange(nodes)) - def add_node(self, v): """ Add a node """ self.ngbh[v] = set() @@ -161,7 +158,7 @@ class BaseGraphState(object): """ Reconstruct from JSON """ self.__init__([]) 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.add_edges(data["edges"]) @@ -190,7 +187,7 @@ class BaseGraphState(object): def layout(self): """ Automatically lay out the graph """ - if self.order()==0: + if self.order() == 0: return g = self.to_networkx() 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) for key, (x, y, z) in pos.items(): self.meta[key]["pos"] = { - "x": x - ax, - "y": y - ay, + "x": x - ax, + "y": y - ay, "z": z - az} def to_stabilizer(self): @@ -232,10 +229,31 @@ class BaseGraphState(object): """ Check equality between graphs """ 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]) diff --git a/examples/client.py b/examples/client.py deleted file mode 100644 index e73d664..0000000 --- a/examples/client.py +++ /dev/null @@ -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() diff --git a/server/client.py b/server/client.py new file mode 100644 index 0000000..4824dee --- /dev/null +++ b/server/client.py @@ -0,0 +1,4 @@ +from abp import VisibleGraphState + +s = VisibleGraphState() +s.add_node(0) diff --git a/server/client2.py b/server/client2.py new file mode 100644 index 0000000..033e298 --- /dev/null +++ b/server/client2.py @@ -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) diff --git a/server/index.html b/server/index.html new file mode 100644 index 0000000..135dccc --- /dev/null +++ b/server/index.html @@ -0,0 +1,12 @@ + + + + + + abp + + + + + + diff --git a/server/poll.js b/server/poll.js new file mode 100644 index 0000000..83f4779 --- /dev/null +++ b/server/poll.js @@ -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; + diff --git a/server/server.py b/server/server.py index 1596d7e..3f32e80 100644 --- a/server/server.py +++ b/server/server.py @@ -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() diff --git a/server/static/main.js b/server/static/main.js index e25fc11..03ed3ee 100644 --- a/server/static/main.js +++ b/server/static/main.js @@ -26,14 +26,6 @@ function render() { }); } -// This just organises kickoff -function startMainLoop() { - scene = makeScene(); - controls.addEventListener("change", render); - poll(); - render(); -} - // Someone resized the window function onWindowResize(evt){ camera.aspect = window.innerWidth / window.innerHeight; @@ -69,8 +61,9 @@ function init() { controls.rotateSpeed = 0.2; camera.position.set(0, 0, 40); - // Start polling - // Run - startMainLoop(); + scene = makeScene(); + controls.addEventListener("change", render); + poll(); + render(); } diff --git a/server/static/poll.js b/server/static/poll.js index 064770b..9597387 100644 --- a/server/static/poll.js +++ b/server/static/poll.js @@ -1,25 +1,20 @@ - 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) { diff --git a/tests/test_client.py b/tests/test_client.py index 12d360b..77c8d16 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -3,7 +3,7 @@ import abp, json import time -def _test_client(): +def test_client(): client = abp.Client(clear=True) client.clear()