From d5e7e5d9b32e080fcc8bca5ceefa176cd5fa7f67 Mon Sep 17 00:00:00 2001 From: Pete Shadbolt Date: Mon, 25 Jul 2016 02:41:16 +0100 Subject: [PATCH] Better integration of ``mock`` --- abp/qi.py | 10 +++- tests/mock.py | 69 +++++++++++++--------- tests/test_graphstate.py | 124 +++++++++++---------------------------- 3 files changed, 83 insertions(+), 120 deletions(-) diff --git a/abp/qi.py b/abp/qi.py index 7712af5..49a5228 100644 --- a/abp/qi.py +++ b/abp/qi.py @@ -104,10 +104,18 @@ class CircuitModel(object): output = np.zeros((self.d, 1), dtype=complex) for i, v in enumerate(self.state): q = int(i & where > 0) - output[i] += v * u[q, q] # TODO this is probably wrong + output[i] += v * u[q, q] output[i ^ where] += v * u[int(not q), q] self.state = output + def act_circuit(self, circuit): + """ Act a sequence of gates """ + for node, operation in circuit: + if operation == "cz": + self.act_cz(*node) + else: + self.act_local_rotation(node, operation) + def __eq__(self, other): """ Check whether two quantum states are the same or not UP TO A GLOBAL PHASE """ diff --git a/tests/mock.py b/tests/mock.py index 8830b28..bae268e 100644 --- a/tests/mock.py +++ b/tests/mock.py @@ -3,7 +3,7 @@ Mock graphs used for testing """ import numpy as np -from abp import GraphState, clifford +from abp import GraphState, clifford, qi from anders_briegel import graphsim from numpy import random @@ -52,41 +52,45 @@ class ABPWrapper(GraphState): def __init__(self, nodes=[]): super(ABPWrapper, self).__init__(nodes, deterministic=True) + def __eq__(self, other): + return self.to_json() == other.to_json() + +class CircuitModelWrapper(qi.CircuitModel): + + def __init__(self, nodes=[]): + assert list(nodes) == range(len(nodes)) + super(CircuitModelWrapper, self).__init__(len(nodes)) + + def act_circuit(self, circuit): + """ Act a sequence of gates """ + for node, operation in circuit: + if operation == "cz": + self.act_cz(*node) + else: + u = clifford.unitaries[clifford.by_name[str(operation)]] + self.act_local_rotation(node, u) + def random_pair(n): """ Helper function to get random pairs""" return tuple(random.choice(range(n), 2, replace=False)) -def random_graph_state(n=10): +def random_graph_circuit(n=10): """ A random Graph state. """ - czs = [(random_pair(n), "cz") for i in range(n * 2)] - for Base in AndersWrapper, ABPWrapper: - g = Base(range(n)) - g.act_circuit((i, "hadamard") for i in range(n)) - g.act_circuit(czs) - yield g + return [(i, "hadamard") for i in range(n)] + \ + [(random_pair(n), "cz") for i in range(n * 2)] -def random_stabilizer_state(n=10): +def random_stabilizer_circuit(n=10): """ Generate a random stabilizer state, without any VOPs """ - rotations = [(i, random.choice(range(24))) for i in range(n)] - for g in random_graph_state(): - g.act_circuit(rotations) - yield g + return random_graph_circuit(n) + \ + [(i, random.choice(range(24))) for i in range(n)] def bell_pair(): - for Base in AndersWrapper, ABPWrapper: - g = Base((0, 1)) - g.act_circuit(((0, "hadamard"), (1, "hadamard"), ((0, 1), "cz"))) - yield g - - -def onequbit(): - for Base in AndersWrapper, ABPWrapper: - g = Base((0,)) - yield g + """ Generate a bell pair circuit """ + return [(0, "hadamard"), (1, "hadamard"), ((0, 1), "cz")] def named_node_graph(): @@ -106,12 +110,21 @@ def simple_graph(): g.act_circuit((edge, "cz") for edge in edges) return g +def circuit_to_state(Base, n, circuit): + """ Convert a circuit to a state, given a base class """ + g = Base(range(n)) + g.act_circuit(circuit) + return g -if __name__ == '__main__': - a, b = random_graph_state() +def test_circuit(circuit): + """ Check that two classes exhibit the same behaviour for a given circuit """ + a = circuit_to_state(ABPWrapper, 10, circuit) + b = circuit_to_state(AndersWrapper, 10, circuit) assert a == b - a, b = random_stabilizer_state() - assert a == b - print named_node_graph() +if __name__ == '__main__': + for i in range(1000): + test_circuit(random_graph_circuit(10)) + test_circuit(random_stabilizer_circuit(10)) + diff --git a/tests/test_graphstate.py b/tests/test_graphstate.py index c6abdf2..dd23a3a 100644 --- a/tests/test_graphstate.py +++ b/tests/test_graphstate.py @@ -1,6 +1,5 @@ from abp import GraphState, CircuitModel, clifford -from abp import clifford -from mock import simple_graph +import mock import random import numpy as np from tqdm import tqdm @@ -11,7 +10,7 @@ DEPTH = 100 def test_graph_basic(): """ Test that we can construct graphs, delete edges, whatever """ - g = simple_graph() + g = mock.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]) @@ -21,7 +20,7 @@ def test_graph_basic(): def test_local_complementation(): """ Test that local complementation works as expected """ - g = simple_graph() + g = mock.simple_graph() g.local_complementation(0) assert g.has_edge(0, 1) assert g.has_edge(0, 2) @@ -34,7 +33,7 @@ def test_local_complementation(): def test_remove_vop(): """ Test that removing VOPs really works """ - g = simple_graph() + g = mock.simple_graph() g.remove_vop(0, 1) assert g.node[0]["vop"] == clifford.by_name["identity"] g.remove_vop(1, 1) @@ -47,17 +46,17 @@ def test_remove_vop(): def test_edgelist(): """ Test making edgelists """ - g = simple_graph() + g = mock.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)): +def test_stress(n=int(1e5)): """ Testing that making a graph of ten thousand qubits takes less than half a second""" import time - g = GraphState(range(n+1)) + g = GraphState(range(n + 1)) t = time.clock() for i in xrange(n): g._add_edge(i, i + 1) @@ -74,107 +73,50 @@ def test_cz(): g.act_cz(0, 1) assert g.has_edge(0, 1) + def test_stabilizer(): """ Test that we can generate stabilizers okay """ - g = simple_graph() + g = mock.simple_graph() stab = g.to_stabilizer() - #TODO + # TODO + def test_local_complementation(): """ Test that local complementation works okay """ - psi = GraphState() - psi.add_node(0) - psi.add_node(1) - psi.add_node(2) - psi.add_node(3) - - for n in psi.node: - psi.act_hadamard(n) - - psi.act_cz(0, 1) - psi.act_cz(0, 3) - psi.act_cz(1, 3) - psi.act_cz(1, 2) - + pairs = (0, 1), (0, 3), (1, 3), (1, 2), + psi = GraphState(range(4)) + psi.act_circuit([(i, "hadamard") for i in psi.node]) + psi.act_circuit([(pair, "cz") for pair in pairs]) old_edges = psi.edgelist() old_state = psi.to_state_vector() psi.local_complementation(1) assert old_edges != psi.edgelist() assert old_state == psi.to_state_vector() + def test_single_qubit(): """ A multi qubit test with Hadamards only""" - for repeat in tqdm(range(REPEATS), desc="Testing against circuit model"): - g = GraphState([0]) - c = CircuitModel(1) - - for i in range(100): - op = np.random.choice(range(24)) - g.act_local_rotation(0, op) - c.act_local_rotation(0, clifford.unitaries[op]) - - assert g.to_state_vector() == c + for repeat in tqdm(range(REPEATS), desc="Randomly testing single qubit operations against circuit model"): + circuit = [(0, random.choice(range(24))) for i in range(DEPTH)] + a = mock.circuit_to_state(mock.ABPWrapper, 1, circuit) + b = mock.circuit_to_state(mock.CircuitModelWrapper, 1, circuit) + assert a.to_state_vector() == b -def test_hadamard_only_multiqubit(n=6): +def test_graphstate_multiqubit(n=6): """ A multi qubit test with Hadamards only""" - for repeat in tqdm(range(REPEATS), desc="Testing against circuit model"): - g = GraphState(range(n)) - c = CircuitModel(n) - - for i in range(n): - g.act_hadamard(i) - c.act_hadamard(i) - - assert g.to_state_vector() == c + for repeat in tqdm(range(REPEATS), desc="Randomly testing multiqubit operations against circuit model"): + circuit = mock.random_graph_circuit(n) + a = mock.circuit_to_state(mock.ABPWrapper, n, circuit) + b = mock.circuit_to_state(mock.CircuitModelWrapper, n, circuit) + assert a.to_state_vector() == b - for i in range(100): - a, b = np.random.choice(range(n), 2, False) - g.act_cz(a, b) - c.act_cz(a, b) - assert g.to_state_vector() == c - - -def test_all_multiqubit(n=4): +def test_stabilizerstate_multiqubit(n=6): """ A multi qubit test with arbitrary local rotations """ - g = GraphState(range(n)) - c = CircuitModel(n) - for i in range(10): - qubit = np.random.randint(0, n - 1) - rotation = np.random.randint(0, 24 - 1) - g.act_local_rotation(qubit, rotation) - c.act_local_rotation(qubit, clifford.unitaries[rotation]) - - assert g.to_state_vector() == c - - for repeat in tqdm(range(REPEATS), desc="Testing against circuit model"): - a, b = np.random.choice(range(n), 2, False) - g.act_cz(a, b) - c.act_cz(a, b) - assert np.allclose(np.sum(np.abs(c.state) ** 2), 1) - assert np.allclose( - np.sum(np.abs(g.to_state_vector().state) ** 2), 1) - - assert g.to_state_vector() == c - - assert g.to_state_vector() == c - -def test_all(n=8): - """ A multi qubit test with arbitrary local rotations """ - g = GraphState(range(n)) - c = CircuitModel(n) - for repeat in tqdm(xrange(REPEATS), "Testing against circuit model"): - for step in xrange(DEPTH): - if random.random()>0.5: - qubit = np.random.randint(0, n - 1) - rotation = np.random.randint(0, 24 - 1) - g.act_local_rotation(qubit, rotation) - c.act_local_rotation(qubit, clifford.unitaries[rotation]) - else: - a, b = np.random.choice(range(n), 2, False) - g.act_cz(a, b) - c.act_cz(a, b) - assert g.to_state_vector() == c - + for repeat in tqdm(range(REPEATS), desc="Randomly testing multiqubit operations against circuit model"): + circuit = mock.random_stabilizer_circuit(n) + a = mock.circuit_to_state(mock.ABPWrapper, n, circuit) + b = mock.circuit_to_state(mock.CircuitModelWrapper, n, circuit) + assert a.to_state_vector() == b