|
|
@@ -7,6 +7,9 @@ import json |
|
|
|
import qi, clifford, util |
|
|
|
import random |
|
|
|
|
|
|
|
def debug(x): |
|
|
|
pass |
|
|
|
|
|
|
|
class GraphState(object): |
|
|
|
|
|
|
|
def __init__(self, nodes=[]): |
|
|
@@ -62,15 +65,28 @@ class GraphState(object): |
|
|
|
|
|
|
|
def remove_vop(self, a, avoid): |
|
|
|
""" Reduces VOP[a] to the identity """ |
|
|
|
#TODO: inefficient |
|
|
|
|
|
|
|
others = set(self.adj[a]) - {avoid} |
|
|
|
swap_qubit = others.pop() if others else avoid |
|
|
|
|
|
|
|
debug("remove_byprod_op called: (v, avoid, vb):") |
|
|
|
self.print_adj_list_line(a) |
|
|
|
self.print_adj_list_line(avoid) |
|
|
|
self.print_adj_list_line(swap_qubit) |
|
|
|
debug("using {}".format(clifford.decompositions[self.node[a]["vop"]])) |
|
|
|
|
|
|
|
for v in reversed(clifford.decompositions[self.node[a]["vop"]]): |
|
|
|
self.local_complementation(a if v == "x" else swap_qubit) |
|
|
|
assert self.node[a]["vop"]==0 |
|
|
|
|
|
|
|
debug("remove_byprod_op: after (v, avoid, vb):") |
|
|
|
self.print_adj_list_line(a) |
|
|
|
self.print_adj_list_line(avoid) |
|
|
|
self.print_adj_list_line(swap_qubit) |
|
|
|
|
|
|
|
def local_complementation(self, v): |
|
|
|
""" As defined in LISTING 1 of Anders & Briegel """ |
|
|
|
debug("V ->Inverting about {}".format(self.get_adj_list_line(v))) |
|
|
|
for i, j in it.combinations(self.adj[v], 2): |
|
|
|
self.toggle_edge(i, j) |
|
|
|
|
|
|
@@ -91,16 +107,23 @@ class GraphState(object): |
|
|
|
|
|
|
|
def act_cz(self, a, b): |
|
|
|
""" Act a controlled-phase gate on two qubits """ |
|
|
|
debug("before cphase between {} and {}".format(a, b)) |
|
|
|
self.print_adj_list_line(a) |
|
|
|
self.print_adj_list_line(b) |
|
|
|
|
|
|
|
ci = self.get_connection_info(a, b) |
|
|
|
if ci["non1"]: |
|
|
|
debug("cphase: left vertex has NONs -> putting it to Id") |
|
|
|
self.remove_vop(a, b) |
|
|
|
|
|
|
|
ci = self.get_connection_info(a, b) |
|
|
|
if ci["non2"]: |
|
|
|
debug("cphase: right vertex has NONs -> putting it to Id") |
|
|
|
self.remove_vop(b, a) |
|
|
|
|
|
|
|
ci = self.get_connection_info(a, b) |
|
|
|
if ci["non1"] and not clifford.is_diagonal(self.node[a]["vop"]): |
|
|
|
debug("cphase: left one needs treatment again -> putting it to Id") |
|
|
|
self.remove_vop(b, a) |
|
|
|
|
|
|
|
self.cz_with_table(a, b) |
|
|
@@ -108,23 +131,41 @@ class GraphState(object): |
|
|
|
def get_connection_info(self, a, b): |
|
|
|
if self.has_edge(a, b): |
|
|
|
return {"was_edge": True, |
|
|
|
"non1": len(self.node.get(a, [])) > 0, |
|
|
|
"non2": len(self.node.get(b, [])) > 0} |
|
|
|
"non1": len(self.adj.get(a)) > 1, |
|
|
|
"non2": len(self.adj.get(b)) > 1} |
|
|
|
else: |
|
|
|
return {"was_edge": False, |
|
|
|
"non1": len(self.node.get(a, [])) > 1, |
|
|
|
"non2": len(self.node.get(b, [])) > 1} |
|
|
|
"non1": len(self.adj.get(a)) > 0, |
|
|
|
"non2": len(self.adj.get(b)) > 0} |
|
|
|
|
|
|
|
def cz_with_table(self, a, b): |
|
|
|
""" Run the table """ |
|
|
|
debug("cphase_with_table called on:") |
|
|
|
self.print_adj_list_line(a) |
|
|
|
self.print_adj_list_line(b) |
|
|
|
|
|
|
|
ci = self.get_connection_info(a, b) |
|
|
|
assert ci["non1"]==False or clifford.is_diagonal(self.node[a]["vop"]) |
|
|
|
assert ci["non2"]==False or clifford.is_diagonal(self.node[b]["vop"]) |
|
|
|
try: |
|
|
|
assert ci["non1"]==False or clifford.is_diagonal(self.node[a]["vop"]) |
|
|
|
assert ci["non2"]==False or clifford.is_diagonal(self.node[b]["vop"]) |
|
|
|
except AssertionError: |
|
|
|
print ci |
|
|
|
print self.node[a]["vop"] |
|
|
|
print self.node[b]["vop"] |
|
|
|
|
|
|
|
edge = self.has_edge(a, b) |
|
|
|
new_edge, self.node[a]["vop"], self.node[ |
|
|
|
b]["vop"] = clifford.cz_table[edge, self.node[a]["vop"], self.node[b]["vop"]] |
|
|
|
if new_edge != edge: |
|
|
|
self.toggle_edge(a, b) |
|
|
|
if new_edge: |
|
|
|
debug("adding edge") |
|
|
|
else: |
|
|
|
debug("deling edge") |
|
|
|
|
|
|
|
debug("cphase_with_table: after") |
|
|
|
self.print_adj_list_line(a) |
|
|
|
self.print_adj_list_line(b) |
|
|
|
|
|
|
|
ci = self.get_connection_info(a, b) |
|
|
|
assert ci["non1"]==False or clifford.is_diagonal(self.node[a]["vop"]) |
|
|
@@ -214,6 +255,18 @@ class GraphState(object): |
|
|
|
rows.append(s) |
|
|
|
return " \n".join(rows) + " \n" |
|
|
|
|
|
|
|
def get_adj_list_line(self, key): |
|
|
|
""" TODO: delete """ |
|
|
|
node = self.node[key] |
|
|
|
adj = " ".join(map(str, sorted(self.adj[key]))) |
|
|
|
vop = clifford.get_name(node["vop"]) |
|
|
|
s = "Vertex {}: VOp {}, neighbors {}".format(key, vop, adj) |
|
|
|
return s |
|
|
|
|
|
|
|
def print_adj_list_line(self, key): |
|
|
|
debug(self.get_adj_list_line(key)) |
|
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other): |
|
|
|
""" Check equality between graphs """ |
|
|
|
return self.adj == other.adj and self.node == other.node |
|
|
|