diff --git a/abp/clifford.py b/abp/clifford.py index fd40aef..48e423a 100644 --- a/abp/clifford.py +++ b/abp/clifford.py @@ -9,14 +9,24 @@ from functools import reduce import itertools as it import numpy as np from tqdm import tqdm -# import argparse - import qi decompositions = ("xxxx", "xx", "zzxx", "zz", "zxx", "z", "zzz", "xxz", "xzx", "xzxxx", "xzzzx", "xxxzx", "xzz", "zzx", "xxx", "x", "zzzx", "xxzx", "zx", "zxxx", "xxxz", "xzzz", "xz", "xzxx") +def conjugate(vop, transform): + """ Returns transform * vop * transform^dagger and a phase in {+1, -1} """ + assert vop in set(xrange(4)) + op = times_table[transform, vop] + op = times_table[op, conjugation_table[transform]] + is_id_or_vop = (transform % 4 == 0) or (transform % 4 == vop) + is_non_pauli = (transform >= 4) and (transform <= 15) + phase = ((-1, 1), (1, -1))[is_id_or_vop][is_non_pauli] + if vop == 0: + phase = 1 + return op, phase + def get_name(i): """ Get the human-readable name of this clifford """ @@ -94,6 +104,24 @@ def get_state_table(unitaries): np.dot(kp, state).T) return state_table +def get_measurement_table(): + """ + Compute a table of transform * operation * transform^dagger + This is pretty unintelligible right now, we should probably compute the phase from unitaries instead + """ + for operation_index, transform_index in itertools.product(range(4), range(24)): + assert vop in set(xrange(4)) + op = times_table[transform, vop] + op = times_table[op, conjugation_table[transform]] + is_id_or_vop = (transform % 4 == 0) or (transform % 4 == vop) + is_non_pauli = (transform >= 4) and (transform <= 15) + phase = ((-1, 1), (1, -1))[is_id_or_vop][is_non_pauli] + if vop == 0: + phase = 1 + return op, phase + + + def get_commuters(unitaries): """ Get the indeces of gates which commute with CZ """ diff --git a/scripts/investigate_rightphase.py b/scripts/investigate_rightphase.py index 0da9752..daca21d 100644 --- a/scripts/investigate_rightphase.py +++ b/scripts/investigate_rightphase.py @@ -1,13 +1,13 @@ from anders_briegel import graphsim +from abp import clifford, qi +import itertools +import numpy as np -for i in range(4): - for j in range(24): - a = graphsim.LocCliffOp(i) - b = graphsim.LocCliffOp(j) - print - print i, j - print i, j, a.op, b.op - output = a.conjugate(b) - print i, j, a.op, b.op, output.ph +for i, j in itertools.product(range(4), range(24)): + operation, phase = clifford.conjugate(i, j) + vop_u = clifford.unitaries[i] + transform_u = clifford.unitaries[j] + u = np.dot(transform_u, np.dot(vop_u, qi.hermitian_conjugate(transform_u))) + #print u.round(2) diff --git a/tests/test_conjugation.py b/tests/test_conjugation.py index bf9250d..42d7ffe 100644 --- a/tests/test_conjugation.py +++ b/tests/test_conjugation.py @@ -1,4 +1,5 @@ from anders_briegel import graphsim +from abp import clifford import itertools #//! replaces op by trans * op * trans^dagger and returns a phase, @@ -7,9 +8,15 @@ import itertools def test_conjugation(): """ Test that clifford.conugate() agrees with graphsim.LocCliffOp.conjugate """ - for i, j in it.product(range(4), range(24)): - a = graphsim.LocCliffOp(i) - b = graphsim.LocCliffOp(j) - output = a.conjugate(b) - print i, j, a.op, b.op, output.ph + 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 + 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