| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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: | |||
| @@ -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) | |||
| @@ -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),))) | |||