@@ -26,26 +26,17 @@ def get_name(i): | |||
def find_clifford(needle, haystack): | |||
""" Find the index of a given u within a list of unitaries, up to a global phase """ | |||
needle = normalize_global_phase(needle) | |||
needle = qi.normalize_global_phase(needle) | |||
for i, t in enumerate(haystack): | |||
if np.allclose(t, needle): | |||
return i | |||
raise IndexError | |||
def normalize_global_phase(m): | |||
""" Normalize the global phase of a matrix """ | |||
v = (x for x in m.flatten() if np.abs(x) > 0.001).next() | |||
phase = np.arctan2(v.imag, v.real) % np.pi | |||
rot = np.exp(-1j * phase) | |||
return rot * m if rot * v > 0 else -rot * m | |||
def find_cz(bond, c1, c2, commuters, state_table, ab_cz_table): | |||
""" Find the output of a CZ operation """ | |||
# Figure out the target state | |||
target = qi.cz.dot(state_table[bond, c1, c2]) | |||
target = normalize_global_phase(target) | |||
target = qi.normalize_global_phase(target) | |||
# Choose the sets to search over | |||
s1 = commuters if c1 in commuters else xrange(24) | |||
@@ -64,7 +55,7 @@ def compose_u(decomposition): | |||
""" Get the unitary representation of a particular decomposition """ | |||
matrices = ({"x": qi.sqx, "z": qi.msqz}[c] for c in decomposition) | |||
output = reduce(np.dot, matrices, np.eye(2, dtype=complex)) | |||
return normalize_global_phase(output) | |||
return qi.normalize_global_phase(output) | |||
def get_unitaries(): | |||
@@ -96,7 +87,7 @@ def get_state_table(unitaries): | |||
for bond, i, j in tqdm(params, desc="Building state table"): | |||
state = qi.bond if bond else qi.nobond | |||
kp = np.kron(unitaries[i], unitaries[j]) | |||
state_table[bond, i, j, :] = normalize_global_phase( | |||
state_table[bond, i, j, :] = qi.normalize_global_phase( | |||
np.dot(kp, state).T) | |||
return state_table | |||
@@ -3,6 +3,7 @@ | |||
""" | |||
Exposes a few basic QI operators | |||
And a circuit-model simulator | |||
""" | |||
import numpy as np | |||
@@ -20,7 +21,7 @@ id = np.array(np.eye(2, dtype=complex)) | |||
px = np.array([[0, 1], [1, 0]], dtype=complex) | |||
py = np.array([[0, -1j], [1j, 0]], dtype=complex) | |||
pz = np.array([[1, 0], [0, -1]], dtype=complex) | |||
ha = np.array([[1, 1], [1, -1]], dtype=complex) * ir2 | |||
ha = hadamard = np.array([[1, 1], [1, -1]], dtype=complex) * ir2 | |||
ph = np.array([[1, 0], [0, 1j]], dtype=complex) | |||
t = np.array([[1, 0], [0, np.exp(1j*np.pi/4)]], dtype=complex) | |||
@@ -48,6 +49,15 @@ by_name = dict(zip(names, common_us)) | |||
paulis = px, py, pz | |||
def normalize_global_phase(m): | |||
""" Normalize the global phase of a matrix """ | |||
v = (x for x in m.flatten() if np.abs(x) > 0.001).next() | |||
phase = np.arctan2(v.imag, v.real) % np.pi | |||
rot = np.exp(-1j * phase) | |||
return rot * m if rot * v > 0 else -rot * m | |||
class CircuitModel(object): | |||
def __init__(self, nqubits): | |||
self.nqubits = nqubits | |||
@@ -84,6 +94,13 @@ class CircuitModel(object): | |||
output[i ^ where] += v*u[not q, q] | |||
self.state = output | |||
def __eq__(self, other): | |||
""" Check whether two quantum states are the same or not | |||
UP TO A GLOBAL PHASE """ | |||
a = normalize_global_phase(self.state) | |||
b = normalize_global_phase(other.state) | |||
return np.allclose(a, b) | |||
def __str__(self): | |||
s = "" | |||
@@ -14,7 +14,7 @@ def test_hadamard_only_multiqubit(): | |||
g.act_hadamard(i) | |||
c.act_hadamard(i) | |||
assert np.allclose(g.to_state_vector().state, c.state) | |||
assert g.to_state_vector() == c | |||
for i in range(100): | |||
a, b = np.random.randint(0, n-1, 2) | |||
@@ -22,9 +22,7 @@ def test_hadamard_only_multiqubit(): | |||
g.act_cz(a, b) | |||
c.act_cz(a, b) | |||
s1 = clifford.normalize_global_phase(g.to_state_vector().state) | |||
s2 = clifford.normalize_global_phase(c.state) | |||
assert np.allclose(s1, s2) | |||
assert g.to_state_vector() == c | |||
def test_all_multiqubit(): | |||
@@ -34,13 +32,13 @@ def test_all_multiqubit(): | |||
c = CircuitModel(n) | |||
for i in range(10): | |||
i = np.random.randint(0, n-1) | |||
j = np.random.randint(0, 24) | |||
print i, j | |||
g.act_local_rotation(i, j) | |||
c.act_local_rotation(i, clifford.unitaries[j]) | |||
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 np.allclose(g.to_state_vector().state, c.state) | |||
assert g.to_state_vector() == c | |||
#for i in range(100): | |||
#a, b = np.random.randint(0, n-1, 2) | |||
@@ -48,7 +46,5 @@ def test_all_multiqubit(): | |||
#g.act_cz(a, b) | |||
#c.act_cz(a, b) | |||
#s1 = clifford.normalize_global_phase(g.to_state_vector().state) | |||
#s2 = clifford.normalize_global_phase(c.state) | |||
#assert np.allclose(s1, s2) | |||
assert g.to_state_vector() == c | |||
@@ -30,7 +30,7 @@ def test_cz_table(): | |||
# Go and compute the output | |||
computed_output = np.dot(qi.cz, input_state) | |||
computed_output = clifford.normalize_global_phase(computed_output) | |||
computed_output = qi.normalize_global_phase(computed_output) | |||
# Now look up the answer in the table | |||
bondp, c1p, c2p = ab_cz_table[bond, c1, c2] | |||
@@ -15,7 +15,7 @@ def test_cz_table(): | |||
# Go and compute the output | |||
computed_output = np.dot(qi.cz, input_state) | |||
computed_output = clifford.normalize_global_phase(computed_output) | |||
computed_output = qi.normalize_global_phase(computed_output) | |||
# Now look up the answer in the table | |||
bondp, c1p, c2p = clifford.cz_table[bond, c1, c2] | |||
@@ -7,5 +7,5 @@ def test_normalize_global_phase(): | |||
u = qi.pz | |||
phase = np.random.uniform(0, 2*np.pi) | |||
m = np.exp(1j*phase) * u | |||
normalized = clifford.normalize_global_phase(m) | |||
normalized = qi.normalize_global_phase(m) | |||
assert np.allclose(normalized, u) |
@@ -1,11 +1,38 @@ | |||
import numpy as np | |||
from abp import qi | |||
def _test_init(): | |||
def test_init(): | |||
""" Can you initialize some qubits """ | |||
psi = qi.CircuitModel(5) | |||
assert psi.d == 32 | |||
def test_single_qubit_stuff(): | |||
""" Try some sensible single-qubit things """ | |||
psi = qi.CircuitModel(2) | |||
psi.act_local_rotation(0, qi.px) | |||
assert np.allclose(psi.state[1], 1) | |||
psi.act_local_rotation(0, qi.px) | |||
assert np.allclose(psi.state[0], 1) | |||
psi.act_local_rotation(0, qi.pz) | |||
def test_more_single_qubit_stuff(): | |||
""" Try some sensible single-qubit things """ | |||
psi = qi.CircuitModel(2) | |||
psi.act_local_rotation(0, qi.px) | |||
psi.act_local_rotation(1, qi.px) | |||
psi.act_cz(0, 1) | |||
def test_equality(): | |||
""" Test that equality succeeds / fails as desired """ | |||
a = qi.CircuitModel(2) | |||
b = qi.CircuitModel(2) | |||
assert a == b | |||
a.act_local_rotation(0, qi.px) | |||
assert a != b | |||
def test_hadamard(): | |||
""" What does CZ do ? """ | |||
psi = qi.CircuitModel(3) | |||