From 37913a4b2cb5bbfaa02ad29750c33bb9d59a68b2 Mon Sep 17 00:00:00 2001 From: Pete Shadbolt Date: Wed, 18 May 2016 18:01:33 +0100 Subject: [PATCH] Lattice example --- examples/lattice_demo.py | 37 ++++++++++++++++++++++ examples/visualization_demo.py | 2 +- static/scripts/anders_briegel.js | 54 ++++++++++++++------------------ static/scripts/graph.js | 33 +++++++++---------- static/scripts/gui.js | 30 +++++++++++++++--- static/scripts/main.js | 3 +- static/scripts/materials.js | 38 ++++++++++------------ static/scripts/orbitcontrols.js | 1 + static/scripts/websocket.js | 2 +- 9 files changed, 124 insertions(+), 76 deletions(-) create mode 100644 examples/lattice_demo.py diff --git a/examples/lattice_demo.py b/examples/lattice_demo.py new file mode 100644 index 0000000..4a15906 --- /dev/null +++ b/examples/lattice_demo.py @@ -0,0 +1,37 @@ +from abp.viz import VisibleGraphState +import numpy as np +import time +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))) + +def add_offset(vector, offset): + """ Offset a vector in n-dimensional space """ + return tuple(v+o for v, o in zip(vector, offset)) + +def offset_unit_cell(unit_cell, offset): + """ Offset a unit cell """ + return {(add_offset(a, offset), add_offset(b, offset)) for a, b in unit_cell} + +def lattice(unit_cell, size): + """ Generate a lattice from a unit cell """ + edges = set() + for offset in itertools.product(*map(range, size)): + edges |= offset_unit_cell(unit_cell, offset) + + nodes = set(itertools.chain(*edges)) + return nodes, edges + +#s = VisibleGraphState() +nodes, edges = lattice(funny_unit_cell, (10, 10)) + +psi = VisibleGraphState() +for node in nodes: + pos = {"x": node[0], "y": node[1], "z": 0} + psi.add_node(str(node), meta={"position":pos}) + +for edge in edges: + psi.add_edge(str(edge[0]), str(edge[1])) + + diff --git a/examples/visualization_demo.py b/examples/visualization_demo.py index 8d4d445..c5e7b4d 100644 --- a/examples/visualization_demo.py +++ b/examples/visualization_demo.py @@ -6,7 +6,7 @@ s = VisibleGraphState() for i in range(200): x = 10*np.cos(np.pi*2*i/60) y = 10*np.sin(np.pi*2*i/60) - s.add_node(i, {"position": (round(x, 2), round(y, 2), round(i/50., 2))}) + s.add_node(i, {"position": {"x":round(x, 2), "y":round(y, 2), "z":round(i/50., 2)}}) s.act_local_rotation(i, "hadamard") for i in range(200-1): s.act_cz(i, i+1) diff --git a/static/scripts/anders_briegel.js b/static/scripts/anders_briegel.js index 893ca31..73a316f 100644 --- a/static/scripts/anders_briegel.js +++ b/static/scripts/anders_briegel.js @@ -1,15 +1,9 @@ var abj = {}; -abj.ngbh = {}; -abj.vops = {}; -abj.meta = {}; -ngbh = abj.ngbh; -vops = abj.vops; -meta = abj.meta; abj.add_node = function(node, m) { - ngbh[node] = {}; - vops[node] = tables.clifford.hadamard; - meta[node] = m ? m : {}; + abj.ngbh[node] = {}; + abj.vops[node] = tables.clifford.hadamard; + abj.meta[node] = m ? m : {}; }; abj.add_nodes = function(nodes) { @@ -17,8 +11,8 @@ abj.add_nodes = function(nodes) { }; abj.add_edge = function(a, b) { - ngbh[a][b] = true; - ngbh[b][a] = true; + abj.ngbh[a][b] = true; + abj.ngbh[b][a] = true; }; abj.add_edges = function(edges) { @@ -28,12 +22,12 @@ abj.add_edges = function(edges) { }; abj.del_edge = function(a, b) { - delete ngbh[a][b]; - delete ngbh[b][a]; + delete abj.ngbh[a][b]; + delete abj.ngbh[b][a]; }; abj.has_edge = function(a, b) { - return Object.prototype.hasOwnProperty.call(ngbh[a], b); + return Object.prototype.hasOwnProperty.call(abj.ngbh[a], b); }; abj.toggle_edge = function(a, b) { @@ -45,7 +39,7 @@ abj.toggle_edge = function(a, b) { }; abj.get_swap = function(node, avoid) { - for (var i in ngbh[node]) { + for (var i in abj.ngbh[node]) { if (i != avoid) { return i; } @@ -55,7 +49,7 @@ abj.get_swap = function(node, avoid) { abj.remove_vop = function(node, avoid) { var swap_qubit = get_swap(node, avoid); - var decomposition = decompositions[vops[node]]; + var decomposition = decompositions[abj.vops[node]]; for (var i = decomposition.length - 1; i >= 0; --i) { var v = decomposition[i]; local_complementation(v == "x" ? a : swap_qubit); @@ -63,19 +57,19 @@ abj.remove_vop = function(node, avoid) { }; abj.local_complementation = function(node) { - var keys = Object.keys(ngbh[node]); + var keys = Object.keys(abj.ngbh[node]); for (var i = 0; i < keys.length; ++i) { for (var j = i + 1; j < keys.length; ++j) { toggle_edge(keys[i], keys[j]); } - vops[i] = tables.times_table[vops[keys[i]]][sqz_h]; + abj.vops[i] = tables.times_table[abj.vops[keys[i]]][sqz_h]; } - vops[node] = tables.times_table[vops[node]][msqx_h]; + abj.vops[node] = tables.times_table[abj.vops[node]][msqx_h]; }; abj.act_local_rotation = function(node, operation) { var rotation = tables.clifford[operation]; - vops[node] = tables.times_table[rotation][vops[node]]; + abj.vops[node] = tables.times_table[rotation][abj.vops[node]]; }; abj.act_hadamard = function(node) { @@ -87,19 +81,19 @@ abj.is_sole_member = function(node, group) { }; abj.act_cz = function(a, b) { - if (is_sole_member(ngbh[a], b)) { + if (is_sole_member(abj.ngbh[a], b)) { remove_vop(a, b); } - if (is_sole_member(ngbh[b], a)) { + if (is_sole_member(abj.ngbh[b], a)) { remove_vop(b, a); } - if (is_sole_member(ngbh[a], b)) { + if (is_sole_member(abj.ngbh[a], b)) { remove_vop(a, b); } var edge = has_edge(a, b); - var new_state = tables.cz_table[edge ? 1 : 0][vops[a]][vops[b]]; - vops[a] = new_state[1]; - vops[b] = new_state[2]; + var new_state = tables.cz_table[edge ? 1 : 0][abj.vops[a]][abj.vops[b]]; + abj.vops[a] = new_state[1]; + abj.vops[b] = new_state[2]; if (new_state[0] != edge) { toggle_edge(a, b); } @@ -108,8 +102,8 @@ abj.act_cz = function(a, b) { abj.edgelist = function() { var seen = {}; var output = []; - for (var i in ngbh) { - for (var j in ngbh[i]) { + for (var i in abj.ngbh) { + for (var j in abj.ngbh[i]) { if (!Object.prototype.hasOwnProperty.call(seen, j)) { output.push([i, j]); } @@ -120,7 +114,7 @@ abj.edgelist = function() { }; abj.log_graph_state = function() { - console.log(JSON.stringify(vops)); - console.log(JSON.stringify(ngbh)); + console.log(JSON.stringify(abj.vops)); + console.log(JSON.stringify(abj.ngbh)); }; diff --git a/static/scripts/graph.js b/static/scripts/graph.js index 822639c..5fc2866 100644 --- a/static/scripts/graph.js +++ b/static/scripts/graph.js @@ -7,24 +7,25 @@ graph.hook = function() { }; graph.update = function(json) { - anders_briegel.vops = json.vops; - anders_briegel.ngbh = json.ngbh; - anders_briegel.meta = json.meta; + abj.vops = json.vops; + abj.ngbh = json.ngbh; + abj.meta = json.meta; graph.updateScene(); }; graph.updateScene = function() { - var oldState = scene.getObjectByName("graphstate"); - scene.remove(oldState); - oldState = null; + if (graph.object){gui.scene.remove(graph.object);} + graph.object = null; + console.log("update"); var geometry = new THREE.Geometry(); + geometry.colors = []; for (var i in abj.vops) { var vop = abj.vops[i]; var pos = abj.meta[i].position; var vertex = new THREE.Vector3(pos.x, pos.y, pos.z); geometry.vertices.push(vertex); - geometry.colors[i] = new THREE.Color(colors[abj.vops[i] % colors.length]); + geometry.colors.push(new THREE.Color(graph.colors[abj.vops[i] % graph.colors.length])); } var edges = new THREE.Object3D(); @@ -32,18 +33,18 @@ graph.updateScene = function() { for (i = 0; i < my_edges.length; ++i) { var edge = my_edges[i]; var start = abj.meta[edge[0]].position; - var startpos = new THREE.Vector3(start[0], start[1], start[2]); + var startpos = new THREE.Vector3(start.x, start.y, start.z); var end = abj.meta[edge[1]].position; - var endpos = new THREE.Vector3(end[0], end[1], end[2]); - var newEdge = makeCurve(startpos, endpos); + var endpos = new THREE.Vector3(end.x, end.y, end.z); + var newEdge = materials.makeCurve(startpos, endpos); edges.add(newEdge); } var particles = new THREE.Points(geometry, materials.qubit); - var newState = new THREE.Object3D(); - newState.name = "graphstate"; - newState.add(particles); - newState.add(edges); - scene.add(newState); - render(); + graph.object = new THREE.Object3D(); + graph.object.name = "graphstate"; + graph.object.add(particles); + graph.object.add(edges); + gui.scene.add(graph.object); + gui.render(); }; diff --git a/static/scripts/gui.js b/static/scripts/gui.js index 1f93a42..70cbb48 100644 --- a/static/scripts/gui.js +++ b/static/scripts/gui.js @@ -1,6 +1,8 @@ var gui = {}; gui.construct = function() { - gui.renderer = new THREE.WebGLRenderer(); + gui.renderer = new THREE.WebGLRenderer({ + "antialias": true + }); gui.renderer.setSize(window.innerWidth, window.innerHeight); gui.renderer.setClearColor(0xffffff, 1); document.querySelector("body").appendChild(gui.renderer.domElement); @@ -10,10 +12,10 @@ gui.construct = function() { gui.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.3, 1000); gui.controls = new THREE.OrbitControls(gui.camera); + gui.controls.addEventListener("change", gui.render); gui.controls.center.set(0, 0, 0); gui.controls.rotateSpeed = 0.2; gui.camera.position.set(0, 0, 20); - gui.controls.addEventListener("change", gui.render); }; // Someone resized the window @@ -27,8 +29,9 @@ gui.onWindowResize = function(evt) { // Render the current frame to the screen gui.render = function() { - console.log("render"); - gui.renderer.render(gui.scene, gui.camera); + requestAnimationFrame(function() { + gui.renderer.render(gui.scene, gui.camera); + }); }; // Make the extra bits of gui @@ -41,8 +44,25 @@ gui.makeScene = function() { }; // Put an HTML message to the screen -gui.serverMessage = function(msgtext){ +gui.serverMessage = function(msgtext) { message.innerHTML = msgtext; message.className = "visible"; }; +gui.loop = function() { + gui.controls.update(); + requestAnimationFrame(gui.loop); +} + +// Try to add a qubit at the current mouse position +gui.addQubitAtMouse = function(event) { + this.raycaster.setFromCamera(mouse, camera); + var intersection = this.raycaster.ray.intersectPlane(this.plane); + intersection.x = Math.round(intersection.x); + intersection.y = Math.round(intersection.y); + abj.add_node(Object.keys(vops).length, { + "position": intersection + }); + graph.updateScene(); +} + diff --git a/static/scripts/main.js b/static/scripts/main.js index 2be64e4..602f3e5 100644 --- a/static/scripts/main.js +++ b/static/scripts/main.js @@ -1,5 +1,6 @@ window.onload = function() { graph.hook(); + materials.load(); gui.construct(); - gui.render(); + gui.loop(); }; diff --git a/static/scripts/materials.js b/static/scripts/materials.js index 87bce3e..047dc79 100644 --- a/static/scripts/materials.js +++ b/static/scripts/materials.js @@ -1,38 +1,32 @@ var materials = {}; -materials.textures = { - sprite: new THREE.Texture() -}; -materials.load = function() { - materials.textures.sprite = new THREE.Texture(document.getElementById("ball")); - materials.textures.sprite.needsUpdate = true; +var curveProperties = { + splineDensity: 8, + curvature: 20 }; -materials.curveProperties = { - splineDensity: 10, - curvature: 100 -}; - -materials.materials = { - edge: new THREE.LineBasicMaterial({ +materials.load = function() { + var sprite = new THREE.Texture(document.getElementById("ball")); + sprite.needsUpdate = true; + materials.edge = new THREE.LineBasicMaterial({ color: "gray", transparent: false, linewidth: 1 - }), - point: new THREE.PointsMaterial({ + }); + materials.point = new THREE.PointsMaterial({ size: 0.1, - map: materials.textures.sprite, + map: sprite, alphaTest: 0.5, transparent: true, vertexColors: THREE.VertexColors - }), - qubit: qubit = new THREE.PointsMaterial({ - size: 0.8, - map: materials.textures.sprite, + }); + materials.qubit = new THREE.PointsMaterial({ + size: 0.3, + map: sprite, alphaTest: 0.5, transparent: true, vertexColors: THREE.VertexColors - }) + }); }; materials.makeCurve = function(a, b) { @@ -43,6 +37,6 @@ materials.makeCurve = function(a, b) { var geometry = new THREE.Geometry(); var splinePoints = spline.getPoints(curveProperties.splineDensity); Array.prototype.push.apply(geometry.vertices, splinePoints); - return new THREE.Line(geometry, materials.materials.edge); + return new THREE.Line(geometry, materials.edge); }; diff --git a/static/scripts/orbitcontrols.js b/static/scripts/orbitcontrols.js index f394b42..b46c6ba 100644 --- a/static/scripts/orbitcontrols.js +++ b/static/scripts/orbitcontrols.js @@ -224,6 +224,7 @@ THREE.OrbitControls = function ( object, domElement ) { if ( scope.enabled === false ) return; if ( scope.userRotate === false ) return; + event.preventDefault(); if ( state === STATE.NONE ) diff --git a/static/scripts/websocket.js b/static/scripts/websocket.js index 2f93505..c44b054 100644 --- a/static/scripts/websocket.js +++ b/static/scripts/websocket.js @@ -19,7 +19,7 @@ websocket.connect = function(update){ ws.onclose = function(evt) { - gui.serverMessage("Connection to server lost. Reconnect."); + gui.serverMessage("Connection to server lost. Reconnect."); }; };