diff --git a/clifford.py b/clifford.py index 2548963..4765438 100644 --- a/clifford.py +++ b/clifford.py @@ -13,17 +13,32 @@ Following the prescription of Anders (thesis pg. 26): from numpy import * -i = matrix(eye(2, dtype=complex)) +def find_up_to_phase(u): + """ Find the index of a given u within a list of unitaries, up to a global phase """ + global unitaries + for i, t in enumerate(unitaries): + for phase in range(8): + if allclose(t, exp(1j*phase*pi/4.)*u): + return i, phase + raise IndexError + +id = matrix(eye(2, dtype=complex)) px = matrix([[0, 1], [1, 0]], dtype=complex) py = matrix([[0, -1j], [1j, 0]], dtype=complex) pz = matrix([[1, 0], [0, -1]], dtype=complex) -h = matrix([[1, 1], [1, -1]], dtype=complex) / sqrt(2) -p = matrix([[1, 0], [0, 1j]], dtype=complex) +ha = matrix([[1, 1], [1, -1]], dtype=complex) / sqrt(2) +ph= matrix([[1, 0], [0, 1j]], dtype=complex) -permutations = (i, h, p, h*p, h*p*h, h*p*h*p) -signs = (i, px, py, pz) +permutations = (id, ha, ph, ha*ph, ha*ph*ha, ha*ph*ha*ph) +signs = (id, px, py, pz) unitaries = [p*s for p in permutations for s in signs] +conjugation_table = [] + +for i, u in enumerate(unitaries): + i, phase = find_up_to_phase(u.H) + conjugation_table.append(i) + # TODO: # - check that we re-generate the table diff --git a/tests/test_clifford.py b/tests/test_clifford.py index ad4e43d..5a7aefa 100644 --- a/tests/test_clifford.py +++ b/tests/test_clifford.py @@ -11,14 +11,6 @@ msqx = sqrtm(-1j * lc.px) paulis = (lc.px, lc.py, lc.pz) -def find_u(u, unitaries): - """ Find the index of a given u within a list of unitaries """ - for i, t in enumerate(unitaries): - if allclose(t, u): - return i - return -1 - - def identify_pauli(m): """ Given a signed Pauli matrix, name it. """ for sign in (+1, -1): @@ -27,6 +19,12 @@ def identify_pauli(m): return sign, pauli_label +def test_find_up_to_phase(): + """ Test that slightly suspicious function """ + assert lc.find_up_to_phase(lc.id) == (0, 0) + assert lc.find_up_to_phase(lc.px) == (1, 0) + assert lc.find_up_to_phase(exp(1j*pi/4.)*lc.ha) == (4, 7) + def get_action(u): """ What does this unitary operator do to the Paulis? """ return [identify_pauli(u * p * u.H) for p in paulis] @@ -44,31 +42,22 @@ def test_we_have_24_matrices(): def test_we_have_all_useful_gates(): """ Check that all the interesting gates are included up to a global phase """ - names = "i", "px", "py", "pz", "h", "p" - unitaries = lc.i, lc.px, lc.py, lc.pz, lc.h, lc.p - for name, unitary in zip(names, unitaries): - i = find_u(unitary, lc.unitaries) - assert i >= 0 - print "{}\t=\tlc.unitaries[{}]".format(name, i) - - names = "sqrt(ix)", "sqrt(-ix)", "sqrt(iy)", "sqrt(-iy)", "sqrt(iz)", "sqrt(-iz)", - unitaries = sqz, msqz, sqy, msqy, sqx, msqx - for name, unitary in zip(names, unitaries): - rotated = [exp(1j * phase * pi / 4.) * unitary for phase in range(8)] - results = [find_u(r, lc.unitaries) for r in rotated] - assert any(x > 0 for x in results) - phase, index = [(i, r) for i, r in enumerate(results) if r>=0][0] - print "exp(1j*{}*pi/4) . {}\t=\tlc.unitaries[{}]".format(phase, name, index) + common_us = lc.id, lc.px, lc.py, lc.pz, lc.ha, lc.ph, sqz, msqz, sqy, msqy, sqx, msqx + for u in common_us: + lc.find_up_to_phase(u) def test_group(): """ Test we are really in a group """ + matches = set() for a in lc.unitaries: for b in lc.unitaries: - unitary = a*b - rotated = [exp(1j * phase * pi / 4.) * unitary for phase in range(8)] - results = [find_u(r, lc.unitaries) for r in rotated] - assert len([x for x in results if x>=0])==1 + i, phase = lc.find_up_to_phase(a*b) + matches.add(i) + assert len(matches)==24 +def test_conjugation_table(): + """ Check that the table of Hermitian conjugates is okay """ + assert len(set(lc.conjugation_table))==24