| @@ -5,7 +5,7 @@ This module implements Anders and Briegel's method for fast simulation of Cliffo | |||||
| import itertools as it | import itertools as it | ||||
| import json, random | import json, random | ||||
| import qi, clifford, util | import qi, clifford, util | ||||
| from stabilizer import Stabilizer | |||||
| class GraphState(object): | class GraphState(object): | ||||
| @@ -361,6 +361,9 @@ class GraphState(object): | |||||
| >>> with open("graph.json") as f: | >>> with open("graph.json") as f: | ||||
| json.dump(graph.to_json(True), f) | json.dump(graph.to_json(True), f) | ||||
| .. todo:: | |||||
| Implement ``from_json()``! | |||||
| """ | """ | ||||
| if stringify: | if stringify: | ||||
| node = {str(key): value for key, value in self.node.items()} | node = {str(key): value for key, value in self.node.items()} | ||||
| @@ -370,11 +373,6 @@ class GraphState(object): | |||||
| else: | else: | ||||
| return {"node": self.node, "adj": self.adj} | return {"node": self.node, "adj": self.adj} | ||||
| def from_json(self, data): | |||||
| """ Reconstruct from JSON """ | |||||
| self.__init__([]) | |||||
| # TODO | |||||
| def to_state_vector(self): | def to_state_vector(self): | ||||
| """ Get the full state vector corresponding to this stabilizer state. Useful for debugging, interface with other simulators. | """ 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! | 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"]]) | state.act_local_rotation(mapping[i], clifford.unitaries[n["vop"]]) | ||||
| return state | return state | ||||
| def to_stabilizer(self): | |||||
| """ Get the stabilizer representation of the state. """ | |||||
| return Stabilizer(self) | |||||
| def __eq__(self, other): | def __eq__(self, other): | ||||
| """ Check equality between GraphStates """ | """ Check equality between GraphStates """ | ||||
| return self.adj == other.adj and self.node == other.node | return self.adj == other.adj and self.node == other.node | ||||
| @@ -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): | class Stabilizer(object): | ||||
| def __init__(self, g): | def __init__(self, g): | ||||
| """ Construct a Stabilizer from a Graphstate """ | """ 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: | 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 | |||||
| @@ -50,6 +50,9 @@ class ABPWrapper(GraphState): | |||||
| def __init__(self, nodes=[]): | def __init__(self, nodes=[]): | ||||
| super(ABPWrapper, self).__init__(nodes, deterministic=True) | super(ABPWrapper, self).__init__(nodes, deterministic=True) | ||||
| def print_stabilizer(self): | |||||
| print self.to_stabilizer() | |||||
| def __eq__(self, other): | def __eq__(self, other): | ||||
| return self.to_json() == other.to_json() | return self.to_json() == other.to_json() | ||||
| @@ -74,13 +74,6 @@ def test_cz(): | |||||
| assert g.has_edge(0, 1) | 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(): | def test_local_complementation(): | ||||
| """ Test that local complementation works okay """ | """ Test that local complementation works okay """ | ||||
| pairs = (0, 1), (0, 3), (1, 3), (1, 2), | pairs = (0, 1), (0, 3), (1, 3), (1, 2), | ||||
| @@ -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 | |||||