@@ -1,5 +1,6 @@ | |||||
# 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.nxgraphstate import NXGraphState | |||||
from abp.qi import CircuitModel | from abp.qi import CircuitModel | ||||
DETERMINISTIC = False | 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) | return int(result) | ||||
def measure_x(self, node, force=None, detail=False, friend=None): | 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) | return self.measure(node, "px", force, detail, friend) | ||||
def measure_y(self, node, force=None, detail=False): | 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) | return self.measure(node, "py", force, detail) | ||||
def measure_z(self, node, force=None, detail=False): | 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) | return self.measure(node, "pz", force, detail) | ||||
def measure_sequence(self, measurements, forces=None, detail=False): | def measure_sequence(self, measurements, forces=None, detail=False): | ||||
@@ -512,3 +486,4 @@ class GraphState(object): | |||||
g.node = self.node.copy() | g.node = self.node.copy() | ||||
g.adj = self.adj.copy() | g.adj = self.adj.copy() | ||||
return g | 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: | :undoc-members: | ||||
:show-inheritance: | :show-inheritance: | ||||
abp.fancy module | |||||
abp.nxgraphstate module | |||||
---------------- | ---------------- | ||||
.. automodule:: abp.fancy | |||||
.. automodule:: abp.nxgraphstate | |||||
:members: | :members: | ||||
:undoc-members: | :undoc-members: | ||||
:show-inheritance: | :show-inheritance: | ||||
@@ -31,8 +31,8 @@ def lattice(unit_cell, size): | |||||
nodes, edges = lattice(threedee_unit_cell, (4, 4, 4)) | nodes, edges = lattice(threedee_unit_cell, (4, 4, 4)) | ||||
psi = GraphState() | |||||
while True: | while True: | ||||
psi = GraphState() | |||||
for node in nodes: | for node in nodes: | ||||
psi.add_qubit(str(node), position=xyz(node[0], node[1], node[2]), vop="identity") | psi.add_qubit(str(node), position=xyz(node[0], node[1], node[2]), vop="identity") | ||||
psi.update(0.1) | psi.update(0.1) | ||||
@@ -1,6 +1,6 @@ | |||||
import json | import json | ||||
import networkx as nx | import networkx as nx | ||||
from abp import GraphState, fancy | |||||
from abp import GraphState, NXGraphState | |||||
from abp import clifford | from abp import clifford | ||||
from abp.util import xyz | from abp.util import xyz | ||||
from mock import simple_graph | from mock import simple_graph | ||||
@@ -16,7 +16,7 @@ def test_json_basic(): | |||||
def test_tuple_keys(): | def test_tuple_keys(): | ||||
""" Test that we can use tuple-ish keys """ | """ Test that we can use tuple-ish keys """ | ||||
g = fancy.GraphState() | |||||
g = NXGraphState() | |||||
g.add_qubit("string") | g.add_qubit("string") | ||||
g.add_qubit((1, 2, 3)) | g.add_qubit((1, 2, 3)) | ||||
g.add_edge((1, 2, 3), "string") | g.add_edge((1, 2, 3), "string") | ||||
@@ -24,8 +24,8 @@ def test_tuple_keys(): | |||||
def networkx_test(): | 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(0, position=xyz(10, 0, 0)) | ||||
g.add_qubit(1, position=xyz(1, 0, 0)) | g.add_qubit(1, position=xyz(1, 0, 0)) | ||||
g.act_hadamard(0) | g.act_hadamard(0) | ||||
@@ -37,9 +37,9 @@ def networkx_test(): | |||||
def test_from_nx(): | def test_from_nx(): | ||||
""" Test that making graphs from networkx objects goes smoothly """ | """ Test that making graphs from networkx objects goes smoothly """ | ||||
g = nx.random_geometric_graph(100, 2) | g = nx.random_geometric_graph(100, 2) | ||||
psi = fancy.GraphState(g) | |||||
psi = NXGraphState(g) | |||||
assert psi.node[0]["vop"] == 0 | assert psi.node[0]["vop"] == 0 | ||||
assert len(psi.edges()) > 0 | assert len(psi.edges()) > 0 | ||||
psi.measure(0, "px", detail=True) | psi.measure(0, "px", detail=True) | ||||
psi = fancy.GraphState(nx.Graph(((0, 1),))) | |||||
psi = NXGraphState(nx.Graph(((0, 1),))) |