Browse Source

Meaningful conjugation code

master
Pete Shadbolt 8 years ago
parent
commit
0ec10d155c
4 changed files with 71 additions and 13 deletions
  1. +22
    -12
      abp/clifford.py
  2. +3
    -0
      abp/qi.py
  3. +46
    -0
      scripts/wtf.py
  4. +0
    -1
      tests/test_conjugation.py

+ 22
- 12
abp/clifford.py View File

@@ -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






+ 3
- 0
abp/qi.py View File

@@ -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):


+ 46
- 0
scripts/wtf.py View File

@@ -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


+ 0
- 1
tests/test_conjugation.py View File

@@ -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 """


Loading…
Cancel
Save