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