Browse Source

Add and test `GraphState.to_stabilizer()` :rage4:

master
Pete Shadbolt 7 years ago
parent
commit
3dbd70e046
6 changed files with 74 additions and 26 deletions
  1. +8
    -6
      abp/graphstate.py
  2. +42
    -13
      abp/stabilizer.py
  3. +3
    -0
      tests/mock.py
  4. +0
    -7
      tests/test_graphstate.py
  5. +0
    -0
      tests/test_mercedes.py
  6. +21
    -0
      tests/test_stabilizer.py

+ 8
- 6
abp/graphstate.py View File

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


+ 42
- 13
abp/stabilizer.py View File

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



+ 3
- 0
tests/mock.py View File

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




+ 0
- 7
tests/test_graphstate.py View File

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


tests/mercedes.py → tests/test_mercedes.py View File


+ 21
- 0
tests/test_stabilizer.py View File

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


Loading…
Cancel
Save