@@ -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 | |||||