@@ -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 | |||
from abp.graphstate import GraphState | |||
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 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]) |
@@ -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 | |||
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(); | |||
} |
@@ -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) { | |||
@@ -3,7 +3,7 @@ import abp, json | |||
import time | |||
def _test_client(): | |||
def test_client(): | |||
client = abp.Client(clear=True) | |||
client.clear() | |||