@@ -1,4 +1,4 @@ | |||||
tables.pkl | |||||
*.pkl | |||||
papers/ | papers/ | ||||
# Project-specific | # Project-specific | ||||
@@ -32,7 +32,7 @@ def name_of(vop): | |||||
return "%s" % get_name[vop] if vop in get_name else "VOP%d" % vop | return "%s" % get_name[vop] if vop in get_name else "VOP%d" % vop | ||||
@cache_to_disk("tables.pkl") | |||||
@cache_to_disk("clifford_tables.pkl") | |||||
def construct_tables(): | def construct_tables(): | ||||
""" Constructs / caches multiplication and conjugation tables """ | """ Constructs / caches multiplication and conjugation tables """ | ||||
by_name = {name: find_up_to_phase(u)[0] for name, u in qi.by_name.items()} | by_name = {name: find_up_to_phase(u)[0] for name, u in qi.by_name.items()} | ||||
@@ -51,8 +51,3 @@ elements = {"x": qi.sqx, "z": qi.msqz} | |||||
unitaries = [compose_u(d) for d in decompositions] | unitaries = [compose_u(d) for d in decompositions] | ||||
by_name, get_name, conjugation_table, times_table = construct_tables() | by_name, get_name, conjugation_table, times_table = construct_tables() | ||||
if __name__ == '__main__': | |||||
print by_name | |||||
print get_name | |||||
@@ -1,48 +0,0 @@ | |||||
from graph import * | |||||
import viz | |||||
import itertools as it | |||||
import clifford | |||||
def cphase(g, vops, a, b): | |||||
""" Act a controlled-phase gate on two qubits """ | |||||
if g[a]-{b}: remove_vop(g, vops, a, b) | |||||
if g[b]-{a}: remove_vop(g, vops, b, a) | |||||
if g[a]-{b}: remove_vop(g, vops, a, b) | |||||
edge = has_edge(g, a, b) | |||||
new_edge, vops[a], vops[b] = cphase_table[edge, vops[a], vops[b]] | |||||
if new_edge != edge: | |||||
toggle_edge(g, a, b) | |||||
def remove_vop(g, vops, a, avoid): | |||||
""" Reduces VOP[a] to the identity, avoiding (if possible) the use of vertex b as a swapping partner """ | |||||
others = g[a] - {avoid} | |||||
swap_qubit = others.pop() if others else avoid | |||||
for v in reversed(clifford.decompositions[vops[a]]): | |||||
local_complementation(g, vops, a if v == "x" else swap_qubit) | |||||
def local_complementation(g, vops, v): | |||||
""" As defined in LISTING 1 of Anders & Briegel """ | |||||
for i, j in it.combinations(g[v], 2): | |||||
toggle_edge(g, i, j) | |||||
# Update VOPs | |||||
vops[v] = clifford.times_table[vops[v]][clifford.by_name["sqx"]] | |||||
for i in g[v]: | |||||
vops[i] = clifford.times_table[vops[i]][clifford.by_name["msqz"]] | |||||
if __name__ == '__main__': | |||||
g, vops = graph() | |||||
add_edge(g, 0, 1) | |||||
add_edge(g, 1, 2) | |||||
add_edge(g, 0, 2) | |||||
add_edge(g, 0, 3) | |||||
add_edge(g, 6, 7) | |||||
pos = viz.draw(g, vops, "out.pdf") | |||||
remove_vop(g, vops, 0, 1) | |||||
remove_vop(g, vops, 1, 2) | |||||
cphase(g, vops, 0, 1) | |||||
viz.draw(g, vops, "out2.pdf", pos) |
@@ -0,0 +1,14 @@ | |||||
""" This part computes the CZ table """ | |||||
from util import cache_to_disk | |||||
import qi | |||||
import numpy as np | |||||
from tqdm import tqdm | |||||
import clifford | |||||
#@cache_to_disk("cz_table.pkl") | |||||
def construct_table(): | |||||
print "awd" | |||||
return "awd" | |||||
cz_table = construct_table() |
@@ -3,6 +3,7 @@ Provides an extremely basic graph structure, based on neighbour lists | |||||
""" | """ | ||||
from collections import defaultdict | from collections import defaultdict | ||||
import itertools as it | |||||
import clifford | import clifford | ||||
def graph(): | def graph(): | ||||
@@ -39,3 +40,32 @@ def edgelist(g): | |||||
for n in v) | for n in v) | ||||
return [tuple(e) for e in edges] | return [tuple(e) for e in edges] | ||||
def cphase(g, vops, a, b): | |||||
""" Act a controlled-phase gate on two qubits """ | |||||
if g[a]-{b}: remove_vop(g, vops, a, b) | |||||
if g[b]-{a}: remove_vop(g, vops, b, a) | |||||
if g[a]-{b}: remove_vop(g, vops, a, b) | |||||
edge = has_edge(g, a, b) | |||||
new_edge, vops[a], vops[b] = cphase_table[edge, vops[a], vops[b]] | |||||
if new_edge != edge: | |||||
toggle_edge(g, a, b) | |||||
def remove_vop(g, vops, a, avoid): | |||||
""" Reduces VOP[a] to the identity, avoiding (if possible) the use of vertex b as a swapping partner """ | |||||
others = g[a] - {avoid} | |||||
swap_qubit = others.pop() if others else avoid | |||||
for v in reversed(clifford.decompositions[vops[a]]): | |||||
local_complementation(g, vops, a if v == "x" else swap_qubit) | |||||
def local_complementation(g, vops, v): | |||||
""" As defined in LISTING 1 of Anders & Briegel """ | |||||
for i, j in it.combinations(g[v], 2): | |||||
toggle_edge(g, i, j) | |||||
# Update VOPs | |||||
vops[v] = clifford.times_table[vops[v]][clifford.by_name["sqx"]] | |||||
for i in g[v]: | |||||
vops[i] = clifford.times_table[vops[i]][clifford.by_name["msqz"]] | |||||
@@ -1,55 +0,0 @@ | |||||
cphase (vertex a, vertex b): | |||||
if ngbh a\{b} =/= {}: | |||||
remove VOP (a, b) | |||||
end if | |||||
if ngbh b\{a} =/= {}: | |||||
remove VOP (b, a) | |||||
end if | |||||
[It may happen that the condition in line 2 has not been fulfilled then, but is now due to the effect of line 5. So we check again:] | |||||
if ngbh a\{b} =/= {}: | |||||
remove VOP (a, b) | |||||
end if | |||||
[Now we can be sure that the the condition (ngbh c\{a, b} = {} or VOP[c] ∈ Z) is fulfilled for c = a, b and we may use the lookup table (cf. Eq. (9)).] | |||||
if {a, b} ∈ E : | |||||
edge ← true | |||||
else: | |||||
edge ← false | |||||
end if | |||||
(edge, VOP[a], VOP[b]) ← cphase_table[edge, VOP[a], VOP[b]] | |||||
remove_VOP (vertex a, vertex b): | |||||
[This reduces VOP[a] to I, avoiding (if possible) to use b as swapping partner.] | |||||
[First, we choose a swapping partner c.] | |||||
if ngbh a\{b} = {}: | |||||
c ← any element of ngbh a\{b} | |||||
else: | |||||
c←b | |||||
end if | |||||
d ← decomposition lookup table [a] | |||||
[c contains now a decomposition such as Eq. (7)] | |||||
for v from last factor of d to first factor of d | |||||
if v = −iX: | |||||
local complementation (a) | |||||
else: ( this means that v = iZ) | |||||
local complementation (b) | |||||
end if | |||||
[Now, VOP[a] = I.] | |||||
local complementation (vertex a) | |||||
[performs the operation specified in Definition 4] | |||||
nv ← ngbh v | |||||
for i ∈ nv : | |||||
for j ∈ nv : | |||||
if i < j: | |||||
if (i, j) ∈ E: | |||||
remove edge (i, j) | |||||
else: | |||||
add edge (i, j) | |||||
end if | |||||
end if | |||||
end for | |||||
VOP[i] ← VOP[i]sqrt(−iZ) | |||||
VOP[v] ← VOP[v]sqrt(iX) | |||||
end for |
@@ -1,6 +1,4 @@ | |||||
import cz | |||||
from graph import * | from graph import * | ||||
import viz | |||||
def test_local_complementation(): | def test_local_complementation(): | ||||
""" Test that local complementation works as expected """ | """ Test that local complementation works as expected """ | ||||
@@ -9,7 +7,7 @@ def test_local_complementation(): | |||||
add_edge(g, 0, 2) | add_edge(g, 0, 2) | ||||
add_edge(g, 1, 2) | add_edge(g, 1, 2) | ||||
add_edge(g, 0, 3) | add_edge(g, 0, 3) | ||||
cz.local_complementation(g, vops, 0) | |||||
local_complementation(g, vops, 0) | |||||
assert has_edge(g, 0, 1) | assert has_edge(g, 0, 1) | ||||
assert has_edge(g, 0, 2) | assert has_edge(g, 0, 2) | ||||
assert not has_edge(g, 1, 2) | assert not has_edge(g, 1, 2) | ||||
@@ -1,9 +1,17 @@ | |||||
""" | """ | ||||
Provides a decorator to cache function output to disk | |||||
Useful but messy crap | |||||
""" | """ | ||||
import cPickle | import cPickle | ||||
import networkx as nx | |||||
from matplotlib import pyplot as plt | |||||
from graph import * | |||||
import clifford | |||||
import numpy as np | |||||
VOP_COLORS = ["red", "green", "blue", "orange", "yellow", "purple", "black", "white"] | |||||
def cache_to_disk(file_name): | def cache_to_disk(file_name): | ||||
""" A decorator to cache the output of a function to disk """ | |||||
def wrap(func): | def wrap(func): | ||||
def modified(*args, **kwargs): | def modified(*args, **kwargs): | ||||
try: | try: | ||||
@@ -15,3 +23,23 @@ def cache_to_disk(file_name): | |||||
return output | return output | ||||
return modified | return modified | ||||
return wrap | return wrap | ||||
def draw(graph, vops, filename="out.pdf", pos=None, ns=500): | |||||
""" Draw a graph with networkx layout """ | |||||
plt.clf() | |||||
g = nx.from_edgelist(edgelist(graph)) | |||||
pos = nx.spring_layout(g) if pos==None else pos | |||||
colors = [VOP_COLORS[vop % len(VOP_COLORS)] for vop in vops] | |||||
nx.draw_networkx_nodes(g, pos, node_color="white", node_size=ns) | |||||
nx.draw_networkx_nodes(g, pos, node_color=colors, node_size=ns, alpha=.4) | |||||
nx.draw_networkx_edges(g, pos, edge_color="gray") | |||||
nx.draw_networkx_labels(g, pos, font_family="FreeSans") | |||||
labels = {i: clifford.name_of(vops[i]) for i in g.nodes()} | |||||
pos = {k: v + np.array([0, -.1]) for k, v in pos.items()} | |||||
nx.draw_networkx_labels(g, pos, labels, font_family="FreeSans") | |||||
plt.axis('off') | |||||
plt.savefig(filename) | |||||
return pos | |||||
@@ -1,30 +0,0 @@ | |||||
""" | |||||
Utility function for plotting graphs nicely | |||||
""" | |||||
import networkx as nx | |||||
from matplotlib import pyplot as plt | |||||
from graph import * | |||||
import clifford | |||||
import numpy as np | |||||
VOP_COLORS = ["red", "green", "blue", "orange", "yellow", "purple", "black", "white"] | |||||
def draw(graph, vops, filename="out.pdf", pos=None, ns=500): | |||||
""" Draw a graph with networkx layout """ | |||||
plt.clf() | |||||
g = nx.from_edgelist(edgelist(graph)) | |||||
pos = nx.spring_layout(g) if pos==None else pos | |||||
colors = [VOP_COLORS[vop % len(VOP_COLORS)] for vop in vops] | |||||
nx.draw_networkx_nodes(g, pos, node_color="white", node_size=ns) | |||||
nx.draw_networkx_nodes(g, pos, node_color=colors, node_size=ns, alpha=.4) | |||||
nx.draw_networkx_edges(g, pos, edge_color="gray") | |||||
nx.draw_networkx_labels(g, pos, font_family="FreeSans") | |||||
labels = {i: clifford.name_of(vops[i]) for i in g.nodes()} | |||||
pos = {k: v + np.array([0, -.1]) for k, v in pos.items()} | |||||
nx.draw_networkx_labels(g, pos, labels, font_family="FreeSans") | |||||
plt.axis('off') | |||||
plt.savefig(filename) | |||||
return pos | |||||