diff --git a/abp/graphstate.py b/abp/graphstate.py index b2e7bb9..9c5f705 100644 --- a/abp/graphstate.py +++ b/abp/graphstate.py @@ -5,7 +5,7 @@ This module implements Anders and Briegel's method for fast simulation of Cliffo import itertools as it import json, random import qi, clifford, util - +from stabilizer import Stabilizer class GraphState(object): @@ -361,6 +361,9 @@ class GraphState(object): >>> with open("graph.json") as f: json.dump(graph.to_json(True), f) + .. todo:: + Implement ``from_json()``! + """ if stringify: node = {str(key): value for key, value in self.node.items()} @@ -370,11 +373,6 @@ class GraphState(object): else: return {"node": self.node, "adj": self.adj} - def from_json(self, data): - """ Reconstruct from JSON """ - self.__init__([]) - # TODO - def to_state_vector(self): """ Get the full state vector corresponding to this stabilizer state. Useful for debugging, interface with other simulators. This method becomes very slow for more than about ten qubits! @@ -401,6 +399,10 @@ class GraphState(object): state.act_local_rotation(mapping[i], clifford.unitaries[n["vop"]]) return state + def to_stabilizer(self): + """ Get the stabilizer representation of the state. """ + return Stabilizer(self) + def __eq__(self, other): """ Check equality between GraphStates """ return self.adj == other.adj and self.node == other.node diff --git a/abp/stabilizer.py b/abp/stabilizer.py index 6c4f02d..426cf45 100644 --- a/abp/stabilizer.py +++ b/abp/stabilizer.py @@ -1,18 +1,47 @@ +""" +Implements a simple Stabilizer object. +""" + +import itertools as it +from abp import clifford + +I = clifford.by_name["identity"] +X = clifford.by_name["px"] +Z = clifford.by_name["pz"] + class Stabilizer(object): def __init__(self, g): """ Construct a Stabilizer from a Graphstate """ - pass - - def to_stabilizer(self): - """ Get the stabilizer tableau. Work in progress! - """ - for a, b in it.product(self.node, self.node): - output[a]["sign"] = 1 + self.tableau = {i:{j: I for j in g.node} for i in g.node} + self.phases = {i: 1 for i in g.node} + for a, b in it.product(g.node, g.node): if a == b: - output[a][b] = "X" - elif a in self.adj[b]: - output[a][b] = "Z" - else: - output[a][b] = "I" - return output + self.tableau[a][b] = X + elif a in g.adj[b]: + self.tableau[a][b] = Z + self.conjugate(a, b, g.node[b]["vop"]) + + def conjugate(self, a, b, vop): + """ Do a little conjugation """ + op, phase = clifford.conjugate(self.tableau[a][b], vop) + self.tableau[a][b] = op + self.phases[a] *= phase + + def to_dictionary(self): + """ For comparison with old A&B code """ + m = {1: 0, 1j:1, -1: 2, -1j: 3} + return {"paulis": self.tableau, + "phases": {key: m[value] for key, value in self.phases.items()}} + + def __str__(self): + """ Represent as a string """ + s = "" + for i in sorted(self.phases): + sign = self.phases[i] + sign = {1: " ", -1: " -", 1j: " i", -1j: "-i"}[sign] + row = (self.tableau[i][j] for j in sorted(self.phases)) + row = ("IXYZ"[i] for i in row) + row = " ".join(row) + s += "{} {}\n".format(sign, row) + return s diff --git a/tests/mock.py b/tests/mock.py index ee034f0..a801c23 100644 --- a/tests/mock.py +++ b/tests/mock.py @@ -50,6 +50,9 @@ class ABPWrapper(GraphState): def __init__(self, nodes=[]): super(ABPWrapper, self).__init__(nodes, deterministic=True) + def print_stabilizer(self): + print self.to_stabilizer() + def __eq__(self, other): return self.to_json() == other.to_json() diff --git a/tests/test_graphstate.py b/tests/test_graphstate.py index b63f053..c582e1c 100644 --- a/tests/test_graphstate.py +++ b/tests/test_graphstate.py @@ -74,13 +74,6 @@ def test_cz(): assert g.has_edge(0, 1) -def test_stabilizer(): - """ Test that we can generate stabilizers okay """ - g = mock.simple_graph() - stab = g.to_stabilizer() - # TODO - - def test_local_complementation(): """ Test that local complementation works okay """ pairs = (0, 1), (0, 3), (1, 3), (1, 2), diff --git a/tests/mercedes.py b/tests/test_mercedes.py similarity index 100% rename from tests/mercedes.py rename to tests/test_mercedes.py diff --git a/tests/test_stabilizer.py b/tests/test_stabilizer.py new file mode 100644 index 0000000..4d97b0d --- /dev/null +++ b/tests/test_stabilizer.py @@ -0,0 +1,21 @@ +from abp import GraphState +from tqdm import tqdm +import mock + +REPEATS = 1000 + +def test_stabilizers_against_anders_and_briegel(n=10): + """ Test that stabilizers are line-for-line equivalent """ + + for i in tqdm(range(REPEATS), "Stabilizer representation VS A&B"): + c = mock.random_stabilizer_circuit(n) + g = mock.AndersWrapper(range(n)) + g.act_circuit(c) + da = g.get_full_stabilizer().to_dictionary() + + g = mock.ABPWrapper(range(n)) + g.act_circuit(c) + db = g.to_stabilizer().to_dictionary() + + assert da == db +