Browse Source

Tidying tests

master
Pete Shadbolt 7 years ago
parent
commit
3b6963c95e
13 changed files with 169 additions and 165 deletions
  1. +1
    -1
      README.md
  2. +1
    -1
      setup.py
  3. +0
    -13
      tests/demograph.py
  4. +0
    -53
      tests/dummy.py
  5. +17
    -5
      tests/mock.py
  6. +0
    -14
      tests/old/test_circuit_model_fails.py
  7. +0
    -7
      tests/old/test_clifford_names.py
  8. +0
    -24
      tests/old/test_conjugation.py
  9. +0
    -27
      tests/old/test_cphase_table.py
  10. +0
    -15
      tests/old/test_get_state_vector.py
  11. +42
    -2
      tests/test_clifford.py
  12. +76
    -0
      tests/test_graphstate.py
  13. +32
    -3
      tests/test_qi.py

+ 1
- 1
README.md View File

@@ -1,6 +1,6 @@
# abp # abp


Python port of Anders and Briegel' s [method](https://arxiv.org/abs/quant-ph/0504117) for fast simulation of Clifford circuits. You can read the full documentation [here](https://peteshadbolt.co.uk/abp/).
Python port of Anders and Briegel' s [method](https://arxiv.org/abs/quant-ph/0504117) for fast simulation of Clifford circuits. You can read the full documentation [here](https://peteshadbolt.co.uk/abp/).


![demo](examples/demo.gif) ![demo](examples/demo.gif)




+ 1
- 1
setup.py View File

@@ -6,7 +6,7 @@ STATIC = glob("static/*.*")+glob("static/img/*.*")+glob("static/scripts/*.*")


setup( setup(
name = "abp", name = "abp",
version = "0.4.1",
version = "0.4.2",
packages = find_packages(), packages = find_packages(),
test_suite = "tests", test_suite = "tests",
author = "Pete Shadbolt", author = "Pete Shadbolt",


+ 0
- 13
tests/demograph.py View File

@@ -1,13 +0,0 @@
from abp import GraphState

def demograph():
""" A graph for testing with """
g = GraphState([0,1,2,3,100,200])
g.add_edge(0, 1)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(0, 3)
g.add_edge(100, 200)
return g



+ 0
- 53
tests/dummy.py View File

@@ -1,53 +0,0 @@
from abp import GraphState, clifford
from anders_briegel import graphsim
import numpy as np

def clean_random_state(N=10):
""" A state to test on """
a = GraphState(range(N))
b = graphsim.GraphRegister(N)
clifford.use_old_cz()

for i in range(N):
a.act_hadamard(i)
b.hadamard(i)

for i in range(10):
j, k= np.random.choice(range(N), 2, replace=False)
a.act_cz(j, k)
b.cphase(j, k)

return a, b

def messy_random_state(N=10):
a, b = clean_random_state(N)
for i in range(N):
a.act_hadamard(i)
b.hadamard(i)

for i in range(N):
j, k= np.random.choice(range(N), 2, replace=False)
a.act_cz(j, k)
b.cphase(j, k)

for i in range(N):
j = np.random.choice(range(N))
k = np.random.choice(range(24))
a.act_local_rotation(j, k)
b.local_op(j, graphsim.LocCliffOp(k))

return a, b

def bell():
a = GraphState(range(2))
b = graphsim.GraphRegister(2)
a.act_hadamard(0); a.act_hadamard(1);
b.hadamard(0); b.hadamard(1);
a.act_cz(0,1)
b.cphase(0,1)
return a, b

def onequbit():
a = GraphState(range(1))
b = graphsim.GraphRegister(1)
return a, b

+ 17
- 5
tests/mock.py View File

@@ -29,8 +29,8 @@ class AndersWrapper(graphsim.GraphRegister):


def measure(self, qubit, basis, force): def measure(self, qubit, basis, force):
basis = clifford.by_name[basis] basis = clifford.by_name[basis]
basis = {1: graphsim.lco_X,
2: graphsim.lco_Y,
basis = {1: graphsim.lco_X,
2: graphsim.lco_Y,
3: graphsim.lco_Z}[clifford.by_name[basis]] 3: graphsim.lco_Z}[clifford.by_name[basis]]
super(AndersWrapper, self).measure(qubit, basis, None, force) super(AndersWrapper, self).measure(qubit, basis, None, force)


@@ -50,7 +50,7 @@ class ABPWrapper(GraphState):
""" A wrapper for abp, just to ensure determinism """ """ A wrapper for abp, just to ensure determinism """


def __init__(self, nodes=[]): def __init__(self, nodes=[]):
super(ABPWrapper, self).__init__(nodes, deterministic = True)
super(ABPWrapper, self).__init__(nodes, deterministic=True)




def random_pair(n): def random_pair(n):
@@ -60,13 +60,14 @@ def random_pair(n):


def random_graph_state(n=10): def random_graph_state(n=10):
""" A random Graph state. """ """ A random Graph state. """
czs = [(random_pair(n), "cz") for i in range(n*2)]
czs = [(random_pair(n), "cz") for i in range(n * 2)]
for Base in AndersWrapper, ABPWrapper: for Base in AndersWrapper, ABPWrapper:
g = Base(range(n)) g = Base(range(n))
g.act_circuit((i, "hadamard") for i in range(n)) g.act_circuit((i, "hadamard") for i in range(n))
g.act_circuit(czs) g.act_circuit(czs)
yield g yield g



def random_stabilizer_state(n=10): def random_stabilizer_state(n=10):
""" Generate a random stabilizer state, without any VOPs """ """ Generate a random stabilizer state, without any VOPs """
rotations = [(i, random.choice(range(24))) for i in range(n)] rotations = [(i, random.choice(range(24))) for i in range(n)]
@@ -74,17 +75,20 @@ def random_stabilizer_state(n=10):
g.act_circuit(rotations) g.act_circuit(rotations)
yield g yield g



def bell_pair(): def bell_pair():
for Base in AndersWrapper, ABPWrapper: for Base in AndersWrapper, ABPWrapper:
g = Base((0, 1)) g = Base((0, 1))
g.act_circuit(((0, "hadamard"), (1, "hadamard"), ((0, 1), "cz"))) g.act_circuit(((0, "hadamard"), (1, "hadamard"), ((0, 1), "cz")))
yield g yield g



def onequbit(): def onequbit():
for Base in AndersWrapper, ABPWrapper: for Base in AndersWrapper, ABPWrapper:
g = Base((0,)) g = Base((0,))
yield g yield g



def named_node_graph(): def named_node_graph():
""" A graph with named nodes""" """ A graph with named nodes"""
edges = (0, 1), (1, 2), (2, 0), (0, 3), (100, 200), (200, "named") edges = (0, 1), (1, 2), (2, 0), (0, 3), (100, 200), (200, "named")
@@ -93,6 +97,15 @@ def named_node_graph():
g.act_circuit((edge, "cz") for edge in edges) g.act_circuit((edge, "cz") for edge in edges)
return g return g


def simple_graph():
""" A simple graph to test with"""
edges = (0, 1), (1, 2), (2, 0), (0, 3), (100, 200)
g = ABPWrapper([0, 1, 2, 3, 100, 200])
g.act_circuit((i, "hadamard") for i in g.node)
g.act_circuit((edge, "cz") for edge in edges)
return g


if __name__ == '__main__': if __name__ == '__main__':
a, b = random_graph_state() a, b = random_graph_state()
assert a == b assert a == b
@@ -101,4 +114,3 @@ if __name__ == '__main__':
assert a == b assert a == b


print named_node_graph() print named_node_graph()


+ 0
- 14
tests/old/test_circuit_model_fails.py View File

@@ -1,14 +0,0 @@
from abp import qi

def test_dumbness():
a = qi.CircuitModel(1)
b = qi.CircuitModel(1)
assert a == b

a.act_local_rotation(0, qi.px)

assert not (a == b)

a.act_local_rotation(0, qi.px)

assert (a == b)

+ 0
- 7
tests/old/test_clifford_names.py View File

@@ -1,7 +0,0 @@
from abp import clifford

def test_names():
""" Test the naming scheme """
for i in range(24):
clifford.get_name(i)
assert clifford.get_name(16)=="IE"

+ 0
- 24
tests/old/test_conjugation.py View File

@@ -1,24 +0,0 @@
from anders_briegel import graphsim
from abp import clifford
import itertools

#//! replaces op by trans * op * trans^dagger and returns a phase,
#/*! either +1 or -1 (as RightPhase(0) or RightPhase(2)) */

def test_conjugation():
""" Test that clifford.conugate() agrees with graphsim.LocCliffOp.conjugate """
for operation_index, transform_index in itertools.product(range(4), range(24)):
transform = graphsim.LocCliffOp(transform_index)
operation = graphsim.LocCliffOp(operation_index)

phase = operation.conjugate(transform).ph
if phase == 1:
print phase
phase = [1, 0, -1][phase]
new_operation = operation.op

NEW_OPERATION, PHASE = clifford.conjugate(operation_index, transform_index)
print new_operation, NEW_OPERATION, " ",
assert new_operation == NEW_OPERATION
assert PHASE == phase


+ 0
- 27
tests/old/test_cphase_table.py View File

@@ -1,27 +0,0 @@
import numpy as np
from abp import clifford, qi, build_tables
import itertools as it

def test_cz_table():
""" Does the CZ code work good? """
state_table = build_tables.get_state_table(clifford.unitaries)

rows = it.product([0, 1], it.combinations_with_replacement(range(24), 2))

for bond, (c1, c2) in rows:

# Pick the input state
input_state = state_table[bond, c1, c2]

# Go and compute the output
computed_output = np.dot(qi.cz, input_state)
computed_output = qi.normalize_global_phase(computed_output)

# Now look up the answer in the table
bondp, c1p, c2p = clifford.cz_table[bond, c1, c2]
table_output = state_table[bondp, c1p, c2p]

assert np.allclose(computed_output, table_output)




+ 0
- 15
tests/old/test_get_state_vector.py View File

@@ -1,15 +0,0 @@
from abp import GraphState
from abp import qi
import numpy as np

def test_single_qubit():
""" Test some single-qubit stuff """
g = GraphState()
g.add_node(0)
g.add_node(1)
g.act_local_rotation(0, "hadamard")
g.act_local_rotation(1, "hadamard")
g.act_cz(0, 1)
assert np.allclose(g.to_state_vector().state, qi.bond)



tests/old/test_clifford.py → tests/test_clifford.py View File

@@ -1,17 +1,18 @@
from numpy import *
import numpy as np
from tqdm import tqdm from tqdm import tqdm
import itertools as it import itertools as it
from abp import clifford from abp import clifford
from abp import build_tables from abp import build_tables
from abp import qi from abp import qi
from nose.tools import raises from nose.tools import raises
from anders_briegel import graphsim




def identify_pauli(m): def identify_pauli(m):
""" Given a signed Pauli matrix, name it. """ """ Given a signed Pauli matrix, name it. """
for sign in (+1, -1): for sign in (+1, -1):
for pauli_label, pauli in zip("xyz", qi.paulis): for pauli_label, pauli in zip("xyz", qi.paulis):
if allclose(sign * pauli, m):
if np.allclose(sign * pauli, m):
return sign, pauli_label return sign, pauli_label




@@ -70,6 +71,45 @@ def test_cz_table_makes_sense():
assert all( assert all(
clifford.cz_table[0, hadamard, hadamard] == [0, hadamard, hadamard]) clifford.cz_table[0, hadamard, hadamard] == [0, hadamard, hadamard])



def test_commuters(): def test_commuters():
""" Test that commutation is good """ """ Test that commutation is good """
assert len(build_tables.get_commuters(clifford.unitaries)) == 4 assert len(build_tables.get_commuters(clifford.unitaries)) == 4


def test_conjugation():
""" Test that clifford.conugate() agrees with graphsim.LocCliffOp.conjugate """
for operation_index, transform_index in it.product(range(4), range(24)):
transform = graphsim.LocCliffOp(transform_index)
operation = graphsim.LocCliffOp(operation_index)

phase = operation.conjugate(transform).ph
phase = [1, 0, -1][phase]
new_operation = operation.op

NEW_OPERATION, PHASE = clifford.conjugate(
operation_index, transform_index)
assert new_operation == NEW_OPERATION
assert PHASE == phase


def test_cz_table():
""" Does the CZ code work good? """
state_table = build_tables.get_state_table(clifford.unitaries)

rows = it.product([0, 1], it.combinations_with_replacement(range(24), 2))

for bond, (c1, c2) in rows:

# Pick the input state
input_state = state_table[bond, c1, c2]

# Go and compute the output
computed_output = np.dot(qi.cz, input_state)
computed_output = qi.normalize_global_phase(computed_output)

# Now look up the answer in the table
bondp, c1p, c2p = clifford.cz_table[bond, c1, c2]
table_output = state_table[bondp, c1p, c2p]

assert np.allclose(computed_output, table_output)

+ 76
- 0
tests/test_graphstate.py View File

@@ -0,0 +1,76 @@
from abp import GraphState
from abp import clifford
from mock import simple_graph
import time


def test_graph_basic():
""" Test that we can construct graphs, delete edges, whatever """
g = simple_graph()
assert set(g.adj[0].keys()) == set([1, 2, 3])
g._del_edge(0, 1)
assert set(g.adj[0].keys()) == set([2, 3])
assert g.has_edge(1, 2)
assert not g.has_edge(0, 1)


def test_local_complementation():
""" Test that local complementation works as expected """
g = simple_graph()
g.local_complementation(0)
assert g.has_edge(0, 1)
assert g.has_edge(0, 2)
assert not g.has_edge(1, 2)
assert g.has_edge(3, 2)
assert g.has_edge(3, 1)

# TODO: test VOP conditions


def test_remove_vop():
""" Test that removing VOPs really works """
g = simple_graph()
g.remove_vop(0, 1)
assert g.node[0]["vop"] == clifford.by_name["identity"]
g.remove_vop(1, 1)
assert g.node[1]["vop"] == clifford.by_name["identity"]
g.remove_vop(2, 1)
assert g.node[2]["vop"] == clifford.by_name["identity"]
g.remove_vop(0, 1)
assert g.node[0]["vop"] == clifford.by_name["identity"]


def test_edgelist():
""" Test making edgelists """
g = simple_graph()
el = g.edgelist()
assert (0, 3) in el
assert (0, 2) in el
assert (100, 200) in el


def test_stress(n = int(1e5)):
""" Testing that making a graph of ten thousand qubits takes less than half a second"""
g = GraphState(range(n+1))
t = time.clock()
for i in xrange(n):
g._add_edge(i, i + 1)
assert time.clock() - t < .5


def test_cz():
""" Test CZ gate """
g = GraphState([0, 1])
g.act_local_rotation(0, clifford.by_name["hadamard"])
g.act_local_rotation(1, clifford.by_name["hadamard"])
g.act_local_rotation(1, clifford.by_name["py"])
assert not g.has_edge(0, 1)
g.act_cz(0, 1)
assert g.has_edge(0, 1)

def test_stabilizer():
""" Test that we can generate stabilizers okay """
g = simple_graph()
stab = g.to_stabilizer()
#TODO


tests/old/test_qi_circuit_model.py → tests/test_qi.py View File

@@ -1,11 +1,14 @@
import numpy as np import numpy as np
from abp import qi from abp import qi
from abp import GraphState



def test_init(): def test_init():
""" Can you initialize some qubits """ """ Can you initialize some qubits """
psi = qi.CircuitModel(5) psi = qi.CircuitModel(5)
assert psi.d == 32 assert psi.d == 32



def test_single_qubit_stuff(): def test_single_qubit_stuff():
""" Try some sensible single-qubit things """ """ Try some sensible single-qubit things """
psi = qi.CircuitModel(2) psi = qi.CircuitModel(2)
@@ -18,6 +21,7 @@ def test_single_qubit_stuff():
psi.act_local_rotation(0, qi.px) psi.act_local_rotation(0, qi.px)
assert np.allclose(psi.state[0], -1) assert np.allclose(psi.state[0], -1)



def test_further_single_qubit_stuff(): def test_further_single_qubit_stuff():
""" Try some sensible single-qubit things """ """ Try some sensible single-qubit things """
psi = qi.CircuitModel(2) psi = qi.CircuitModel(2)
@@ -37,6 +41,7 @@ def test_more_single_qubit_stuff():
psi.act_local_rotation(1, qi.px) psi.act_local_rotation(1, qi.px)
psi.act_cz(0, 1) psi.act_cz(0, 1)



def test_equality(): def test_equality():
""" Test that equality succeeds / fails as desired """ """ Test that equality succeeds / fails as desired """
a = qi.CircuitModel(2) a = qi.CircuitModel(2)
@@ -46,17 +51,17 @@ def test_equality():
assert a != b assert a != b





def test_hadamard(): def test_hadamard():
""" What does CZ do ? """ """ What does CZ do ? """
psi = qi.CircuitModel(3) psi = qi.CircuitModel(3)
psi.act_hadamard(0) psi.act_hadamard(0)
psi.act_hadamard(1) psi.act_hadamard(1)
assert np.allclose(psi.state, np.array([[1,1,1,1,0,0,0,0]]).T/2.)
assert np.allclose(psi.state, np.array([[1, 1, 1, 1, 0, 0, 0, 0]]).T / 2.)
psi.act_hadamard(1) psi.act_hadamard(1)
psi.act_hadamard(0) psi.act_hadamard(0)
psi.act_hadamard(2) psi.act_hadamard(2)
assert np.allclose(psi.state, qi.ir2*np.array([[1,0,0,0,1,0,0,0]]).T)
assert np.allclose(
psi.state, qi.ir2 * np.array([[1, 0, 0, 0, 1, 0, 0, 0]]).T)




def test_cz(): def test_cz():
@@ -82,3 +87,27 @@ def test_local_rotation():
assert np.allclose(psi.state[0], 1) assert np.allclose(psi.state[0], 1)




def test_dumbness():
""" Check that I haven't done something really dumb """
a = qi.CircuitModel(1)
b = qi.CircuitModel(1)
assert a == b

a.act_local_rotation(0, qi.px)

assert not (a == b)

a.act_local_rotation(0, qi.px)

assert (a == b)


def test_to_state_vector_single_qubit():
""" Test some single-qubit stuff """
g = GraphState()
g.add_node(0)
g.add_node(1)
g.act_local_rotation(0, "hadamard")
g.act_local_rotation(1, "hadamard")
g.act_cz(0, 1)
assert np.allclose(g.to_state_vector().state, qi.bond)

Loading…
Cancel
Save