From beea2e4ddce9af80eaaf55a0c5b3b5fc506fe4d0 Mon Sep 17 00:00:00 2001 From: Pete Shadbolt Date: Fri, 27 May 2016 15:25:51 +0100 Subject: [PATCH] Test passing w/ clean GraphState :water_buffalo: Got rid of all the debug harness and refactored graphstate.py --- abp/clifford.py | 7 ++-- abp/graphstate.py | 59 +++++++++++++------------------- static/scripts/anders_briegel.js | 1 + 3 files changed, 30 insertions(+), 37 deletions(-) diff --git a/abp/clifford.py b/abp/clifford.py index 9fb5948..27c2a70 100644 --- a/abp/clifford.py +++ b/abp/clifford.py @@ -1,7 +1,9 @@ # -*- 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 @@ -183,6 +185,7 @@ def write_javascript_tables(): def temp(filename): """ Get a temporary path """ + # TODO: this STILL fucking fails sometimes. WHY tempdir = tempfile.gettempdir() return os.path.join(tempdir, filename) @@ -224,7 +227,7 @@ def load_from_disk(): by_name = json.load(f) 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} if __name__ == "__main__": diff --git a/abp/graphstate.py b/abp/graphstate.py index 25dc4e7..1c0d4c8 100644 --- a/abp/graphstate.py +++ b/abp/graphstate.py @@ -7,6 +7,7 @@ import json import qi, clifford, util import random + class GraphState(object): def __init__(self, nodes=[]): @@ -25,7 +26,7 @@ class GraphState(object): for n in nodes: 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 """ assert v1 != v2 self.adj[v1][v2] = data @@ -56,8 +57,8 @@ class GraphState(object): """ Describe a graph as an edgelist """ # TODO: inefficient 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) def remove_vop(self, a, avoid): @@ -71,7 +72,7 @@ class GraphState(object): else: 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 """ for i, j in it.combinations(self.adj[v], 2): self.toggle_edge(i, j) @@ -80,56 +81,45 @@ class GraphState(object): sqz_h = clifford.conjugation_table[clifford.by_name["sqz"]] self.node[v]["vop"] = clifford.times_table[self.node[v]["vop"], msqx_h] 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): """ Act a local rotation """ 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): """ Shorthand """ 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): """ 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) - ci = self.get_connection_info(a, b) - if ci["non2"]: + if self.lonely(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.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) - 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: self.toggle_edge(a, b) - def measure_z(self, node, force=None): """ 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 for neighbour in self.adj[node]: @@ -163,7 +153,7 @@ class GraphState(object): def __str__(self): """ Represent as a string for quick debugging """ 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) return "graph:\n node: {}\n adj: {}\n".format(node, nbstr) @@ -174,7 +164,7 @@ class GraphState(object): def from_json(self, data): """ Reconstruct from JSON """ self.__init__([]) - #TODO + # TODO def to_state_vector(self): """ Get the full state vector """ @@ -191,7 +181,7 @@ class GraphState(object): def to_stabilizer(self): """ 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): if a == b: output[a][b] = "X" @@ -214,4 +204,3 @@ class GraphState(object): def __eq__(self, other): """ Check equality between graphs """ return self.adj == other.adj and self.node == other.node - diff --git a/static/scripts/anders_briegel.js b/static/scripts/anders_briegel.js index 6331741..c1fe54b 100644 --- a/static/scripts/anders_briegel.js +++ b/static/scripts/anders_briegel.js @@ -93,6 +93,7 @@ abj.act_hadamard = function(node) { }; abj.is_sole_member = function(group, node) { + // TODO: this is slow as heck var keys = Object.keys(group); return keys.length == 1 && keys[0] == node; };