Next up: measurement Also added a test on local complementationmaster
| @@ -2,7 +2,7 @@ | |||||
| Allows us to visualize the state in a browser | Allows us to visualize the state in a browser | ||||
| """ | """ | ||||
| import atexit, json | |||||
| import atexit, json, time | |||||
| from graphstate import GraphState | from graphstate import GraphState | ||||
| from websocket import create_connection | from websocket import create_connection | ||||
| @@ -21,14 +21,9 @@ class VisibleGraphState(GraphState): | |||||
| self.update() | self.update() | ||||
| self.ws.close() | self.ws.close() | ||||
| def to_json(self): | |||||
| """ We override to_json() so that we send the whole `ngbh` structure in JS-friendly form """ | |||||
| ngbh = {a: {b: True for b in self.ngbh[a]} | |||||
| for a in self.ngbh} | |||||
| return {"vops": self.vops, "ngbh": ngbh, "meta": self.meta} | |||||
| def update(self): | |||||
| def update(self, delay = 0.5): | |||||
| """ Call this function when you are ready to send data to the browser """ | """ Call this function when you are ready to send data to the browser """ | ||||
| data = json.dumps(self.to_json()) | data = json.dumps(self.to_json()) | ||||
| self.ws.send(data) | self.ws.send(data) | ||||
| time.sleep(delay) | |||||
| @@ -1,19 +1,25 @@ | |||||
| from abp.viz import VisibleGraphState | from abp.viz import VisibleGraphState | ||||
| from abp.util import xyz | |||||
| import numpy as np | import numpy as np | ||||
| import time | import time | ||||
| import itertools | import itertools | ||||
| square_unit_cell = (((0, 0), (0, 1)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((0, 1), (1, 1))) | |||||
| funny_unit_cell = (((0, 0), (0, 1)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((0, 1), (1, 1)), ((0, 0), (.5, .5))) | |||||
| square_unit_cell = ( | |||||
| ((0, 0), (0, 1)), ((0, 0), (1, 0)), ((1, 0), (1, 1)), ((0, 1), (1, 1))) | |||||
| funny_unit_cell = (((0, 0), (0, 1)), ((0, 0), (1, 0)), | |||||
| ((1, 0), (1, 1)), ((0, 1), (1, 1)), ((0, 0), (.5, .5))) | |||||
| def add_offset(vector, offset): | def add_offset(vector, offset): | ||||
| """ Offset a vector in n-dimensional space """ | """ Offset a vector in n-dimensional space """ | ||||
| return tuple(v+o for v, o in zip(vector, offset)) | |||||
| return tuple(v + o for v, o in zip(vector, offset)) | |||||
| def offset_unit_cell(unit_cell, offset): | def offset_unit_cell(unit_cell, offset): | ||||
| """ Offset a unit cell """ | """ Offset a unit cell """ | ||||
| return {(add_offset(a, offset), add_offset(b, offset)) for a, b in unit_cell} | return {(add_offset(a, offset), add_offset(b, offset)) for a, b in unit_cell} | ||||
| def lattice(unit_cell, size): | def lattice(unit_cell, size): | ||||
| """ Generate a lattice from a unit cell """ | """ Generate a lattice from a unit cell """ | ||||
| edges = set() | edges = set() | ||||
| @@ -23,15 +29,14 @@ def lattice(unit_cell, size): | |||||
| nodes = set(itertools.chain(*edges)) | nodes = set(itertools.chain(*edges)) | ||||
| return nodes, edges | return nodes, edges | ||||
| #s = VisibleGraphState() | |||||
| nodes, edges = lattice(funny_unit_cell, (10, 10)) | |||||
| # s = VisibleGraphState() | |||||
| nodes, edges = lattice(square_unit_cell, (4, 4)) | |||||
| psi = VisibleGraphState() | psi = VisibleGraphState() | ||||
| for node in nodes: | for node in nodes: | ||||
| pos = {"x": node[0], "y": node[1], "z": 0} | |||||
| psi.add_node(str(node), meta={"position":pos}) | |||||
| psi.add_node(str(node), position=xyz(node[0], node[1])) | |||||
| psi.act_hadamard(str(node)) | |||||
| for edge in edges: | for edge in edges: | ||||
| psi.add_edge(str(edge[0]), str(edge[1])) | |||||
| psi.act_cz(str(edge[0]), str(edge[1])) | |||||
| @@ -0,0 +1,20 @@ | |||||
| from abp.viz import VisibleGraphState | |||||
| from abp.util import xyz | |||||
| from abp.clifford import * | |||||
| psi = VisibleGraphState() | |||||
| psi.add_node(0, position = xyz(0, 0)) | |||||
| psi.add_node(1, position = xyz(1, 1)) | |||||
| psi.add_node(2, position = xyz(3, 2)) | |||||
| psi.add_node(3, position = xyz(0, 3)) | |||||
| for n in psi.node: | |||||
| psi.act_hadamard(n) | |||||
| psi.act_cz(0, 1) | |||||
| psi.act_cz(0, 3) | |||||
| psi.act_cz(1, 3) | |||||
| psi.act_cz(1, 2) | |||||
| while True: | |||||
| psi.update() | |||||
| psi.local_complementation(1) | |||||
| @@ -34,6 +34,7 @@ | |||||
| <li><a href="#">Measure in Z</a></li> | <li><a href="#">Measure in Z</a></li> | ||||
| <li><a href="#">Act Hadamard</a></li> | <li><a href="#">Act Hadamard</a></li> | ||||
| <li><a href="#">Act Phase</a></li> | <li><a href="#">Act Phase</a></li> | ||||
| <li><a href="#" onclick="editor.localComplementation()">Invert neighbourhood</a></li> | |||||
| <!--<li>--> | <!--<li>--> | ||||
| <!--<a href="#">IA</a>--> | <!--<a href="#">IA</a>--> | ||||
| <!--<a href="#">IB</a>--> | <!--<a href="#">IB</a>--> | ||||
| @@ -70,11 +70,11 @@ abj.local_complementation = function(node) { | |||||
| var keys = Object.keys(abj.adj[node]); | var keys = Object.keys(abj.adj[node]); | ||||
| for (var i = 0; i < keys.length; ++i) { | for (var i = 0; i < keys.length; ++i) { | ||||
| for (var j = i + 1; j < keys.length; ++j) { | for (var j = i + 1; j < keys.length; ++j) { | ||||
| toggle_edge(keys[i], keys[j]); | |||||
| abj.toggle_edge(keys[i], keys[j]); | |||||
| } | } | ||||
| abj.node[i].vop = tables.times_table[abj.node[keys[i]].vop][sqz_h]; | |||||
| abj.node[i].vop = tables.times_table[abj.node[keys[i]].vop][6]; | |||||
| } | } | ||||
| abj.node[node].vop = tables.times_table[abj.node[node].vop][msqx_h]; | |||||
| abj.node[node].vop = tables.times_table[abj.node[node].vop][14]; | |||||
| }; | }; | ||||
| abj.act_local_rotation = function(node, operation) { | abj.act_local_rotation = function(node, operation) { | ||||
| @@ -48,7 +48,7 @@ editor.addQubitAtPoint = function(point) { | |||||
| } | } | ||||
| // TODO: This SUCKS | // TODO: This SUCKS | ||||
| var new_node = Math.random()*100000|0; | |||||
| var new_node = point.x + "." + point.y + "." + point.z; | |||||
| abj.add_node(new_node, { position: point, vop:0 }); | abj.add_node(new_node, { position: point, vop:0 }); | ||||
| editor.focus(new_node); | editor.focus(new_node); | ||||
| graph.update(); | graph.update(); | ||||
| @@ -145,3 +145,10 @@ editor.deleteNode = function() { | |||||
| editor.selection = undefined; | editor.selection = undefined; | ||||
| node_data.className = "hidden"; | node_data.className = "hidden"; | ||||
| }; | }; | ||||
| editor.localComplementation = function() { | |||||
| if (editor.selection === undefined){ return; } | |||||
| abj.local_complementation(editor.selection); | |||||
| graph.update(); | |||||
| gui.serverMessage("Inverted neighbourhood of " + editor.selection + "."); | |||||
| }; | |||||
| @@ -0,0 +1,24 @@ | |||||
| from abp import GraphState | |||||
| from abp import qi | |||||
| def test_local_comp(): | |||||
| """ Test that local complementation works okay """ | |||||
| psi = GraphState() | |||||
| psi.add_node(0) | |||||
| psi.add_node(1) | |||||
| psi.add_node(2) | |||||
| psi.add_node(3) | |||||
| for n in psi.node: | |||||
| psi.act_hadamard(n) | |||||
| psi.act_cz(0, 1) | |||||
| psi.act_cz(0, 3) | |||||
| psi.act_cz(1, 3) | |||||
| psi.act_cz(1, 2) | |||||
| before = psi.copy() | |||||
| psi.local_complementation(1) | |||||
| assert before.edgelist() != psi.edgelist() | |||||
| assert before.to_state_vector() == psi.to_state_vector() | |||||