From 9fae542174621990554f8b97b34f49a3d8a0aff3 Mon Sep 17 00:00:00 2001 From: Pete Shadbolt Date: Fri, 18 Nov 2016 22:04:03 -0800 Subject: [PATCH] Working on removing fancy.py --- abp/__init__.py | 1 + abp/fancy.py | 64 --------------------------- abp/graphstate.py | 33 ++------------ abp/nxgraphstate.py | 24 ++++++++++ doc/abp.rst | 4 +- examples/visualization/stress_test.py | 2 +- tests/{test_fancy.py => test_nx.py} | 12 ++--- 7 files changed, 38 insertions(+), 102 deletions(-) delete mode 100644 abp/fancy.py create mode 100644 abp/nxgraphstate.py rename tests/{test_fancy.py => test_nx.py} (78%) diff --git a/abp/__init__.py b/abp/__init__.py index 924fa75..48827db 100644 --- a/abp/__init__.py +++ b/abp/__init__.py @@ -1,5 +1,6 @@ # Alias some stuff to make imports cleaner from abp.graphstate import GraphState +from abp.nxgraphstate import NXGraphState from abp.qi import CircuitModel DETERMINISTIC = False diff --git a/abp/fancy.py b/abp/fancy.py deleted file mode 100644 index 94185ff..0000000 --- a/abp/fancy.py +++ /dev/null @@ -1,64 +0,0 @@ -import time, atexit, json -import sys -import networkx as nx -import numpy as np -import websocket -from socket import error as socket_error -import graphstate -import clifford -import util - -class GraphState(graphstate.GraphState, nx.Graph): - def __init__(self, *args, **kwargs): - graphstate.GraphState.__init__(self, *args, **kwargs) - self.connect_to_server() - - def connect_to_server(self, uri = "ws://localhost:5000"): - """ Attempt to connect to the websocket server """ - try: - self.ws = websocket.create_connection(uri, timeout=0.1) - atexit.register(self.shutdown) - except: #TODO: bad practice - self.ws = None - - def shutdown(self): - """ Close the connection to the websocket """ - if not self.ws: - return - self.ws.close() - - def update(self, delay = 0.5): - """ Call this function when you are ready to send data to the browser """ - if not self.ws: - return - - # Automatically perform layout if position is not provided - if not all(("position" in node) for node in self.node.values()): - self.layout() - - # Send data to browser and rate-limit - try: - self.ws.send(json.dumps(self.to_json(stringify=True))) - self.ws.recv() - time.sleep(delay) - except websocket._exceptions.WebSocketTimeoutException: - print "Timed out ... you might be pushing a bit hard" - time.sleep(delay) - #self.ws.close() - #self.connect_to_server() - - def layout(self): - """ Automatically lay out the graph """ - pos = nx.spring_layout(self, dim=3, scale=np.sqrt(self.order())) - middle = np.average(pos.values(), axis=0) - pos = {key: value - middle for key, value in pos.items()} - for key, (x, y, z) in pos.items(): - self.node[key]["position"] = util.xyz(x, y, z) - - def add_vops(self): - """ Automatically add vops if they're not present """ - for key in self.node: - if not "vop" in self.node[key]: - self.node[key]["vop"] = clifford.identity - - diff --git a/abp/graphstate.py b/abp/graphstate.py index b1f41e3..b3255e2 100755 --- a/abp/graphstate.py +++ b/abp/graphstate.py @@ -276,41 +276,15 @@ class GraphState(object): return int(result) def measure_x(self, node, force=None, detail=False, friend=None): - """ Measure in the X basis - - :param node: The name of the qubit to measure. - :param force: Measurements in quantum mechanics are probabilistic. If you want to force a particular outcome, use the ``force``. - :type force: boolean - :param detail: Provide detailed information - :type detail: boolean - :param friend: Specify a node to toggle about - :type friend: Any neighbour of ``node``. - - """ + """ Measure in the X basis """ return self.measure(node, "px", force, detail, friend) def measure_y(self, node, force=None, detail=False): - """ Measure in the Y basis - - :param node: The name of the qubit to measure. - :param force: Measurements in quantum mechanics are probabilistic. If you want to force a particular outcome, use the ``force``. - :type force: boolean - :param detail: Provide detailed information - :type detail: boolean - - """ + """ Measure in the Y basis """ return self.measure(node, "py", force, detail) def measure_z(self, node, force=None, detail=False): - """ Measure in the Z basis - - :param node: The name of the qubit to measure. - :param force: Measurements in quantum mechanics are probabilistic. If you want to force a particular outcome, use the ``force``. - :type force: boolean - :param detail: Provide detailed information - :type detail: boolean - - """ + """ Measure in the Z basis """ return self.measure(node, "pz", force, detail) def measure_sequence(self, measurements, forces=None, detail=False): @@ -512,3 +486,4 @@ class GraphState(object): g.node = self.node.copy() g.adj = self.adj.copy() return g + diff --git a/abp/nxgraphstate.py b/abp/nxgraphstate.py new file mode 100644 index 0000000..253fd30 --- /dev/null +++ b/abp/nxgraphstate.py @@ -0,0 +1,24 @@ +import networkx as nx +import graphstate +import clifford + +class NXGraphState(graphstate.GraphState, nx.Graph): + """ This is GraphState with NetworkX-like abilities """ + def __init__(self, *args, **kwargs): + graphstate.GraphState.__init__(self, *args, **kwargs) + + def layout(self): + """ Automatically lay out the graph """ + pos = nx.spring_layout(self, dim=3, scale=np.sqrt(self.order())) + middle = np.average(pos.values(), axis=0) + pos = {key: value - middle for key, value in pos.items()} + for key, (x, y, z) in pos.items(): + self.node[key]["position"] = util.xyz(x, y, z) + + def add_vops(self): + """ Automatically add vops if they're not present """ + for key in self.node: + if not "vop" in self.node[key]: + self.node[key]["vop"] = clifford.identity + + diff --git a/doc/abp.rst b/doc/abp.rst index 974b09e..40a4088 100644 --- a/doc/abp.rst +++ b/doc/abp.rst @@ -35,10 +35,10 @@ abp.clifford module :undoc-members: :show-inheritance: -abp.fancy module +abp.nxgraphstate module ---------------- -.. automodule:: abp.fancy +.. automodule:: abp.nxgraphstate :members: :undoc-members: :show-inheritance: diff --git a/examples/visualization/stress_test.py b/examples/visualization/stress_test.py index c89cc72..53d42b3 100644 --- a/examples/visualization/stress_test.py +++ b/examples/visualization/stress_test.py @@ -31,8 +31,8 @@ def lattice(unit_cell, size): nodes, edges = lattice(threedee_unit_cell, (4, 4, 4)) +psi = GraphState() while True: - psi = GraphState() for node in nodes: psi.add_qubit(str(node), position=xyz(node[0], node[1], node[2]), vop="identity") psi.update(0.1) diff --git a/tests/test_fancy.py b/tests/test_nx.py similarity index 78% rename from tests/test_fancy.py rename to tests/test_nx.py index f1fba44..e43ccc6 100644 --- a/tests/test_fancy.py +++ b/tests/test_nx.py @@ -1,6 +1,6 @@ import json import networkx as nx -from abp import GraphState, fancy +from abp import GraphState, NXGraphState from abp import clifford from abp.util import xyz from mock import simple_graph @@ -16,7 +16,7 @@ def test_json_basic(): def test_tuple_keys(): """ Test that we can use tuple-ish keys """ - g = fancy.GraphState() + g = NXGraphState() g.add_qubit("string") g.add_qubit((1, 2, 3)) g.add_edge((1, 2, 3), "string") @@ -24,8 +24,8 @@ def test_tuple_keys(): def networkx_test(): - """ Test that fancy graph states really behave like networkx graphs """ - g = fancy.GraphState() + """ Test that NXGraphStates really behave like networkx graphs """ + g = NXGraphState() g.add_qubit(0, position=xyz(10, 0, 0)) g.add_qubit(1, position=xyz(1, 0, 0)) g.act_hadamard(0) @@ -37,9 +37,9 @@ def networkx_test(): def test_from_nx(): """ Test that making graphs from networkx objects goes smoothly """ g = nx.random_geometric_graph(100, 2) - psi = fancy.GraphState(g) + psi = NXGraphState(g) assert psi.node[0]["vop"] == 0 assert len(psi.edges()) > 0 psi.measure(0, "px", detail=True) - psi = fancy.GraphState(nx.Graph(((0, 1),))) + psi = NXGraphState(nx.Graph(((0, 1),)))