@@ -15,9 +15,9 @@ decompositions = ("xxxx", "xx", "zzxx", "zz", "zxx", "z", "zzz", "xxz", | |||||
"xzx", "xzxxx", "xzzzx", "xxxzx", "xzz", "zzx", "xxx", "x", | "xzx", "xzxxx", "xzzzx", "xxxzx", "xzz", "zzx", "xxx", "x", | ||||
"zzzx", "xxzx", "zx", "zxxx", "xxxz", "xzzz", "xz", "xzxx") | "zzzx", "xxzx", "zx", "zxxx", "xxxz", "xzzz", "xz", "xzxx") | ||||
def conjugate(vop, transform): | |||||
def conjugate(operator, unitary): | |||||
""" Returns transform * vop * transform^dagger and a phase in {+1, -1} """ | """ Returns transform * vop * transform^dagger and a phase in {+1, -1} """ | ||||
return measurement_table[vop, transform] | |||||
return measurement_table[operator, unitary] | |||||
def use_old_cz(): | def use_old_cz(): | ||||
""" Use the CZ table from A&B's code """ | """ Use the CZ table from A&B's code """ | ||||
@@ -101,22 +101,32 @@ def get_state_table(unitaries): | |||||
np.dot(kp, state).T) | np.dot(kp, state).T) | ||||
return state_table | return state_table | ||||
def get_measurement_entry(operator, unitary): | |||||
""" | |||||
Any Clifford group unitary will map an operator A in {I, X, Y, Z} | |||||
to an operator B in +-{I, X, Y, Z}. This finds that mapping. | |||||
""" | |||||
matrices = ({"x": qi.msqx, "z": qi.sqz}[c] for c in decompositions[unitary]) | |||||
unitary = reduce(np.dot, matrices, np.eye(2, dtype=complex)) | |||||
operator = qi.operators[operator] | |||||
new_operator = reduce(np.dot, (unitary, operator, qi.hermitian_conjugate(unitary))) | |||||
for i, o in enumerate(qi.operators): | |||||
if np.allclose(o, new_operator): | |||||
return i, 1 | |||||
elif np.allclose(o, -new_operator): | |||||
return i, -1 | |||||
raise IndexError | |||||
def get_measurement_table(): | def get_measurement_table(): | ||||
""" | """ | ||||
Compute a table of transform * operation * transform^dagger | Compute a table of transform * operation * transform^dagger | ||||
This is pretty unintelligible right now, we should probably compute the phase from unitaries instead | This is pretty unintelligible right now, we should probably compute the phase from unitaries instead | ||||
""" | """ | ||||
measurement_table = np.zeros((4, 24, 2), dtype=complex) | measurement_table = np.zeros((4, 24, 2), dtype=complex) | ||||
for vop, transform in it.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 | |||||
measurement_table[vop, transform] = [op, phase] | |||||
for operator, unitary in it.product(range(4), range(24)): | |||||
measurement_table[operator, unitary] = [operator, unitary] | |||||
return measurement_table | return measurement_table | ||||
@@ -36,6 +36,8 @@ cz = np.array(np.eye(4), dtype=complex) | |||||
cz[3,3]=-1 | cz[3,3]=-1 | ||||
# States | # States | ||||
zero = np.array([[1],[0]], dtype=complex) | |||||
one = np.array([[0],[1]], dtype=complex) | |||||
plus = np.array([[1],[1]], dtype=complex) / np.sqrt(2) | plus = np.array([[1],[1]], dtype=complex) / np.sqrt(2) | ||||
bond = cz.dot(np.kron(plus, plus)) | bond = cz.dot(np.kron(plus, plus)) | ||||
nobond = np.kron(plus, plus) | nobond = np.kron(plus, plus) | ||||
@@ -46,6 +48,7 @@ names = "identity", "px", "py", "pz", "hadamard", "phase", "sqz", "msqz", "sqy", | |||||
by_name = dict(zip(names, common_us)) | by_name = dict(zip(names, common_us)) | ||||
paulis = px, py, pz | paulis = px, py, pz | ||||
operators = id, px, py, pz | |||||
def normalize_global_phase(m): | def normalize_global_phase(m): | ||||
@@ -0,0 +1,46 @@ | |||||
from abp import clifford, qi | |||||
import numpy as np | |||||
import itertools as it | |||||
def conj_hack(operator, unitary): | |||||
""" TODO: make this meaningful / legible """ | |||||
assert operator in set(xrange(4)) | |||||
op = clifford.times_table[unitary, operator] | |||||
op = clifford.times_table[op, clifford.conjugation_table[unitary]] | |||||
is_id_or_operator = (unitary % 4 == 0) or (unitary % 4 == operator) | |||||
is_non_pauli = (unitary >= 4) and (unitary <= 15) | |||||
phase = ((-1, 1), (1, -1))[is_id_or_operator][is_non_pauli] | |||||
if operator == 0: | |||||
phase = 1 | |||||
return op, phase | |||||
def conj(operator, unitary): | |||||
""" Better """ | |||||
matrices = ({"x": qi.msqx, "z": qi.sqz}[c] for c in clifford.decompositions[unitary]) | |||||
unitary = reduce(np.dot, matrices, np.eye(2, dtype=complex)) | |||||
operator = qi.operators[operator] | |||||
new_operator = reduce(np.dot, (unitary, operator, qi.hermitian_conjugate(unitary))) | |||||
for i, o in enumerate(qi.operators): | |||||
if np.allclose(o, new_operator): | |||||
return i, 1 | |||||
elif np.allclose(o, -new_operator): | |||||
return i, -1 | |||||
raise IndexError | |||||
for operator, unitary in it.product(range(4), range(24)): | |||||
assert conj(operator, unitary) == conj_hack(operator, unitary) | |||||
#new = np.dot(u, np.dot(o, qi.hermitian_conjugate(u))) | |||||
#which = clifford.find_clifford(new, clifford.unitaries[:4]) | |||||
#assert which in xrange(4) | |||||
#whichm = [qi.id, qi.px, qi.py, qi.pz][which] | |||||
#if np.allclose(new, whichm): | |||||
#return which, 1 | |||||
#elif np.allclose(new, -whichm): | |||||
#return which, -1 | |||||
#else: | |||||
#raise IndexError | |||||
@@ -4,7 +4,6 @@ import itertools | |||||
#//! replaces op by trans * op * trans^dagger and returns a phase, | #//! replaces op by trans * op * trans^dagger and returns a phase, | ||||
#/*! either +1 or -1 (as RightPhase(0) or RightPhase(2)) */ | #/*! either +1 or -1 (as RightPhase(0) or RightPhase(2)) */ | ||||
#RightPhase conjugate (const LocCliffOp trans); | |||||
def test_conjugation(): | def test_conjugation(): | ||||
""" Test that clifford.conugate() agrees with graphsim.LocCliffOp.conjugate """ | """ Test that clifford.conugate() agrees with graphsim.LocCliffOp.conjugate """ | ||||