Browse Source

Test passing w/ clean GraphState :water_buffalo:

Got rid of all the debug harness and refactored graphstate.py
master
Pete Shadbolt 8 years ago
parent
commit
beea2e4ddc
3 changed files with 30 additions and 37 deletions
  1. +5
    -2
      abp/clifford.py
  2. +24
    -35
      abp/graphstate.py
  3. +1
    -0
      static/scripts/anders_briegel.js

+ 5
- 2
abp/clifford.py View File

@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-


""" """
This program generates lookup tables and handles the Clifford group
This program generates and caches lookup tables, and handles the Clifford group.
It provides tables for Clifford group multiplication and conjugation,
as well as CZ and decompositions of the 2x2 Cliffords.
""" """


import os, json, tempfile, os, sys, json, string import os, json, tempfile, os, sys, json, string
@@ -183,6 +185,7 @@ def write_javascript_tables():


def temp(filename): def temp(filename):
""" Get a temporary path """ """ Get a temporary path """
# TODO: this STILL fucking fails sometimes. WHY
tempdir = tempfile.gettempdir() tempdir = tempfile.gettempdir()
return os.path.join(tempdir, filename) return os.path.join(tempdir, filename)


@@ -224,7 +227,7 @@ def load_from_disk():
by_name = json.load(f) by_name = json.load(f)


def is_diagonal(v): def is_diagonal(v):
""" TODO:remove. Checks if a VOP is diagonal or not """
""" TODO: remove this. Checks if a VOP is diagonal or not """
return v in {0, 3, 5, 6} return v in {0, 3, 5, 6}


if __name__ == "__main__": if __name__ == "__main__":


+ 24
- 35
abp/graphstate.py View File

@@ -7,6 +7,7 @@ import json
import qi, clifford, util import qi, clifford, util
import random import random



class GraphState(object): class GraphState(object):


def __init__(self, nodes=[]): def __init__(self, nodes=[]):
@@ -25,7 +26,7 @@ class GraphState(object):
for n in nodes: for n in nodes:
self.add_node(n) self.add_node(n)


def add_edge(self, v1, v2, data = {}):
def add_edge(self, v1, v2, data={}):
""" Add an edge between two vertices in the self """ """ Add an edge between two vertices in the self """
assert v1 != v2 assert v1 != v2
self.adj[v1][v2] = data self.adj[v1][v2] = data
@@ -56,8 +57,8 @@ class GraphState(object):
""" Describe a graph as an edgelist """ """ Describe a graph as an edgelist """
# TODO: inefficient # TODO: inefficient
edges = set(tuple(sorted((i, n))) edges = set(tuple(sorted((i, n)))
for i, v in self.adj.items()
for n in v)
for i, v in self.adj.items()
for n in v)
return tuple(edges) return tuple(edges)


def remove_vop(self, a, avoid): def remove_vop(self, a, avoid):
@@ -71,7 +72,7 @@ class GraphState(object):
else: else:
self.local_complementation(swap_qubit, "V ->") self.local_complementation(swap_qubit, "V ->")


def local_complementation(self, v, prefix = ""):
def local_complementation(self, v, prefix=""):
""" As defined in LISTING 1 of Anders & Briegel """ """ As defined in LISTING 1 of Anders & Briegel """
for i, j in it.combinations(self.adj[v], 2): for i, j in it.combinations(self.adj[v], 2):
self.toggle_edge(i, j) self.toggle_edge(i, j)
@@ -80,56 +81,45 @@ class GraphState(object):
sqz_h = clifford.conjugation_table[clifford.by_name["sqz"]] sqz_h = clifford.conjugation_table[clifford.by_name["sqz"]]
self.node[v]["vop"] = clifford.times_table[self.node[v]["vop"], msqx_h] self.node[v]["vop"] = clifford.times_table[self.node[v]["vop"], msqx_h]
for i in self.adj[v]: for i in self.adj[v]:
self.node[i]["vop"] = clifford.times_table[self.node[i]["vop"], sqz_h]
self.node[i]["vop"] = clifford.times_table[
self.node[i]["vop"], sqz_h]


def act_local_rotation(self, v, op): def act_local_rotation(self, v, op):
""" Act a local rotation """ """ Act a local rotation """
rotation = clifford.by_name[str(op)] rotation = clifford.by_name[str(op)]
self.node[v]["vop"] = clifford.times_table[rotation, self.node[v]["vop"]]
self.node[v]["vop"] = clifford.times_table[
rotation, self.node[v]["vop"]]


def act_hadamard(self, qubit): def act_hadamard(self, qubit):
""" Shorthand """ """ Shorthand """
self.act_local_rotation(qubit, 10) self.act_local_rotation(qubit, 10)


def lonely(self, a, b):
""" Is this qubit lonely ? """
return len(self.adj[a]) > (b in self.adj[a])

def act_cz(self, a, b): def act_cz(self, a, b):
""" Act a controlled-phase gate on two qubits """ """ Act a controlled-phase gate on two qubits """
ci = self.get_connection_info(a, b)
if ci["non1"]:
if self.lonely(a, b):
self.remove_vop(a, b) self.remove_vop(a, b)


ci = self.get_connection_info(a, b)
if ci["non2"]:
if self.lonely(b, a):
self.remove_vop(b, a) self.remove_vop(b, a)


ci = self.get_connection_info(a, b)
if ci["non1"] and not clifford.is_diagonal(self.node[a]["vop"]):
if self.lonely(a, b) and not clifford.is_diagonal(self.node[a]["vop"]):
self.remove_vop(a, b) self.remove_vop(a, b)


self.cz_with_table(a, b)

def get_connection_info(self, a, b):
if self.has_edge(a, b):
return {"was_edge": True,
"non1": len(self.adj.get(a)) > 1,
"non2": len(self.adj.get(b)) > 1}
else:
return {"was_edge": False,
"non1": len(self.adj.get(a)) > 0,
"non2": len(self.adj.get(b)) > 0}

def cz_with_table(self, a, b):
""" Run the table """
ci = self.get_connection_info(a, b)
edge = self.has_edge(a, b) 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"]]
va = self.node[a]["vop"]
vb = self.node[b]["vop"]
new_edge, self.node[a]["vop"], self.node[b]["vop"] = \
clifford.cz_table[edge, va, vb]
if new_edge != edge: if new_edge != edge:
self.toggle_edge(a, b) self.toggle_edge(a, b)



def measure_z(self, node, force=None): def measure_z(self, node, force=None):
""" Measure the graph in the Z-basis """ """ Measure the graph in the Z-basis """
res = force if force!=None else random.choice([0, 1])
res = force if force != None else random.choice([0, 1])


# Disconnect # Disconnect
for neighbour in self.adj[node]: for neighbour in self.adj[node]:
@@ -163,7 +153,7 @@ class GraphState(object):
def __str__(self): def __str__(self):
""" Represent as a string for quick debugging """ """ Represent as a string for quick debugging """
node = {key: clifford.get_name(value["vop"]) node = {key: clifford.get_name(value["vop"])
for key, value in self.node.items()}
for key, value in self.node.items()}
nbstr = str(self.adj) nbstr = str(self.adj)
return "graph:\n node: {}\n adj: {}\n".format(node, nbstr) return "graph:\n node: {}\n adj: {}\n".format(node, nbstr)


@@ -174,7 +164,7 @@ class GraphState(object):
def from_json(self, data): def from_json(self, data):
""" Reconstruct from JSON """ """ Reconstruct from JSON """
self.__init__([]) self.__init__([])
#TODO
# TODO


def to_state_vector(self): def to_state_vector(self):
""" Get the full state vector """ """ Get the full state vector """
@@ -191,7 +181,7 @@ class GraphState(object):


def to_stabilizer(self): def to_stabilizer(self):
""" Get the stabilizer of this graph """ """ Get the stabilizer of this graph """
output = {a:{} for a in self.node}
output = {a: {} for a in self.node}
for a, b in it.product(self.node, self.node): for a, b in it.product(self.node, self.node):
if a == b: if a == b:
output[a][b] = "X" output[a][b] = "X"
@@ -214,4 +204,3 @@ class GraphState(object):
def __eq__(self, other): def __eq__(self, other):
""" Check equality between graphs """ """ Check equality between graphs """
return self.adj == other.adj and self.node == other.node return self.adj == other.adj and self.node == other.node


+ 1
- 0
static/scripts/anders_briegel.js View File

@@ -93,6 +93,7 @@ abj.act_hadamard = function(node) {
}; };


abj.is_sole_member = function(group, node) { abj.is_sole_member = function(group, node) {
// TODO: this is slow as heck
var keys = Object.keys(group); var keys = Object.keys(group);
return keys.length == 1 && keys[0] == node; return keys.length == 1 && keys[0] == node;
}; };


Loading…
Cancel
Save