| @@ -1,12 +1,12 @@ | |||||
| var abj = {}; | var abj = {}; | ||||
| abj.vops = {}; | |||||
| abj.ngbh = {}; | |||||
| abj.meta = {}; | |||||
| abj.node = {}; | |||||
| abj.adj = {}; | |||||
| abj.add_node = function(node, m) { | |||||
| abj.ngbh[node] = {}; | |||||
| abj.vops[node] = tables.clifford.hadamard; | |||||
| abj.meta[node] = m ? m : {}; | |||||
| abj.add_node = function(node, meta) { | |||||
| abj.adj[node] = {}; | |||||
| abj.node[node] = {}; | |||||
| abj.node[node].vop = tables.clifford.hadamard; | |||||
| Object.assign(abj.node[node], meta); | |||||
| }; | }; | ||||
| abj.add_nodes = function(nodes) { | abj.add_nodes = function(nodes) { | ||||
| @@ -14,8 +14,8 @@ abj.add_nodes = function(nodes) { | |||||
| }; | }; | ||||
| abj.add_edge = function(a, b) { | abj.add_edge = function(a, b) { | ||||
| abj.ngbh[a][b] = true; | |||||
| abj.ngbh[b][a] = true; | |||||
| abj.adj[a][b] = {}; | |||||
| abj.adj[b][a] = {}; | |||||
| }; | }; | ||||
| abj.add_edges = function(edges) { | abj.add_edges = function(edges) { | ||||
| @@ -25,12 +25,12 @@ abj.add_edges = function(edges) { | |||||
| }; | }; | ||||
| abj.del_edge = function(a, b) { | abj.del_edge = function(a, b) { | ||||
| delete abj.ngbh[a][b]; | |||||
| delete abj.ngbh[b][a]; | |||||
| delete abj.adj[a][b]; | |||||
| delete abj.adj[b][a]; | |||||
| }; | }; | ||||
| abj.has_edge = function(a, b) { | abj.has_edge = function(a, b) { | ||||
| return Object.prototype.hasOwnProperty.call(abj.ngbh[a], b); | |||||
| return Object.prototype.hasOwnProperty.call(abj.adj[a], b); | |||||
| }; | }; | ||||
| abj.toggle_edge = function(a, b) { | abj.toggle_edge = function(a, b) { | ||||
| @@ -42,7 +42,7 @@ abj.toggle_edge = function(a, b) { | |||||
| }; | }; | ||||
| abj.get_swap = function(node, avoid) { | abj.get_swap = function(node, avoid) { | ||||
| for (var i in abj.ngbh[node]) { | |||||
| for (var i in abj.adj[node]) { | |||||
| if (i != avoid) { | if (i != avoid) { | ||||
| return i; | return i; | ||||
| } | } | ||||
| @@ -52,7 +52,7 @@ abj.get_swap = function(node, avoid) { | |||||
| abj.remove_vop = function(node, avoid) { | abj.remove_vop = function(node, avoid) { | ||||
| var swap_qubit = get_swap(node, avoid); | var swap_qubit = get_swap(node, avoid); | ||||
| var decomposition = decompositions[abj.vops[node]]; | |||||
| var decomposition = decompositions[abj.node[node].vop]; | |||||
| for (var i = decomposition.length - 1; i >= 0; --i) { | for (var i = decomposition.length - 1; i >= 0; --i) { | ||||
| var v = decomposition[i]; | var v = decomposition[i]; | ||||
| local_complementation(v == "x" ? a : swap_qubit); | local_complementation(v == "x" ? a : swap_qubit); | ||||
| @@ -60,19 +60,19 @@ abj.remove_vop = function(node, avoid) { | |||||
| }; | }; | ||||
| abj.local_complementation = function(node) { | abj.local_complementation = function(node) { | ||||
| var keys = Object.keys(abj.ngbh[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]); | toggle_edge(keys[i], keys[j]); | ||||
| } | } | ||||
| abj.vops[i] = tables.times_table[abj.vops[keys[i]]][sqz_h]; | |||||
| abj.node[i].vop = tables.times_table[abj.node[keys[i]].vop][sqz_h]; | |||||
| } | } | ||||
| abj.vops[node] = tables.times_table[abj.vops[node]][msqx_h]; | |||||
| abj.node[node].vop = tables.times_table[abj.node[node].vop][msqx_h]; | |||||
| }; | }; | ||||
| abj.act_local_rotation = function(node, operation) { | abj.act_local_rotation = function(node, operation) { | ||||
| var rotation = tables.clifford[operation]; | var rotation = tables.clifford[operation]; | ||||
| abj.vops[node] = tables.times_table[rotation][abj.vops[node]]; | |||||
| abj.node[node].vop = tables.times_table[rotation][abj.node[node].vop]; | |||||
| }; | }; | ||||
| abj.act_hadamard = function(node) { | abj.act_hadamard = function(node) { | ||||
| @@ -84,19 +84,19 @@ abj.is_sole_member = function(node, group) { | |||||
| }; | }; | ||||
| abj.act_cz = function(a, b) { | abj.act_cz = function(a, b) { | ||||
| if (is_sole_member(abj.ngbh[a], b)) { | |||||
| if (is_sole_member(abj.adj[a], b)) { | |||||
| remove_vop(a, b); | remove_vop(a, b); | ||||
| } | } | ||||
| if (is_sole_member(abj.ngbh[b], a)) { | |||||
| if (is_sole_member(abj.adj[b], a)) { | |||||
| remove_vop(b, a); | remove_vop(b, a); | ||||
| } | } | ||||
| if (is_sole_member(abj.ngbh[a], b)) { | |||||
| if (is_sole_member(abj.adj[a], b)) { | |||||
| remove_vop(a, b); | remove_vop(a, b); | ||||
| } | } | ||||
| var edge = has_edge(a, b); | var edge = has_edge(a, b); | ||||
| 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]; | |||||
| var new_state = tables.cz_table[edge ? 1 : 0][abj.node[a].vop][abj.node[b].vop]; | |||||
| abj.node[a].vop = new_state[1]; | |||||
| abj.node[b].vop = new_state[2]; | |||||
| if (new_state[0] != edge) { | if (new_state[0] != edge) { | ||||
| toggle_edge(a, b); | toggle_edge(a, b); | ||||
| } | } | ||||
| @@ -105,8 +105,8 @@ abj.act_cz = function(a, b) { | |||||
| abj.edgelist = function() { | abj.edgelist = function() { | ||||
| var seen = {}; | var seen = {}; | ||||
| var output = []; | var output = []; | ||||
| for (var i in abj.ngbh) { | |||||
| for (var j in abj.ngbh[i]) { | |||||
| for (var i in abj.adj) { | |||||
| for (var j in abj.adj[i]) { | |||||
| if (!Object.prototype.hasOwnProperty.call(seen, j)) { | if (!Object.prototype.hasOwnProperty.call(seen, j)) { | ||||
| output.push([i, j]); | output.push([i, j]); | ||||
| } | } | ||||
| @@ -117,17 +117,16 @@ abj.edgelist = function() { | |||||
| }; | }; | ||||
| abj.log_graph_state = function() { | abj.log_graph_state = function() { | ||||
| console.log(JSON.stringify(abj.vops)); | |||||
| console.log(JSON.stringify(abj.ngbh)); | |||||
| console.log(JSON.stringify(abj.node)); | |||||
| console.log(JSON.stringify(abj.adj)); | |||||
| }; | }; | ||||
| abj.update = function(newState) { | abj.update = function(newState) { | ||||
| abj.vops = newState.vops; | |||||
| abj.ngbh = newState.ngbh; | |||||
| abj.meta = newState.meta; | |||||
| abj.node = newState.node; | |||||
| abj.adj = newState.adj; | |||||
| }; | }; | ||||
| abj.order = function(){ | abj.order = function(){ | ||||
| return Object.keys(abj.vops).length; | |||||
| return Object.keys(abj.node).length; | |||||
| }; | }; | ||||
| @@ -1,26 +1,22 @@ | |||||
| var editor = {}; | var editor = {}; | ||||
| var pi2 = Math.PI / 2; | var pi2 = Math.PI / 2; | ||||
| editor.nearest = undefined; | |||||
| editor.selection = undefined; | |||||
| editor.orientations = [ | |||||
| new THREE.Matrix4(), | |||||
| new THREE.Matrix4(), | |||||
| new THREE.Matrix4() | |||||
| editor.planes = [ | |||||
| new THREE.Plane(new THREE.Vector3(0, 0, 1), 0), | |||||
| new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), | |||||
| new THREE.Plane(new THREE.Vector3(1, 0, 0), 0) | |||||
| ]; | ]; | ||||
| editor.orientation = 0; | editor.orientation = 0; | ||||
| editor.orientations[1].makeRotationX(pi2); | |||||
| editor.orientations[2].makeRotationX(pi2); | |||||
| editor.orientations[2].makeRotationZ(pi2); | |||||
| editor.plane = editor.planes[editor.orientation]; | |||||
| editor.onFreeMove = function() { | editor.onFreeMove = function() { | ||||
| var n = editor.nearestNode(mouse.ray); | |||||
| if (editor.nearest !== n) { | |||||
| editor.nearest = n; | |||||
| if (n) { | |||||
| gui.nodeMessage("Node " + n + " (VOP:" + abj.vops[n] + ")" + | |||||
| var found = editor.findNodeOnRay(mouse.ray); | |||||
| if (editor.selection !== found) { | |||||
| editor.selection = found; | |||||
| if (found) { | |||||
| gui.nodeMessage("Node " + found + " (VOP:" + abj.node[found].vop + ")" + | |||||
| "<br/>" + "Click to edit neighbourhood"); | "<br/>" + "Click to edit neighbourhood"); | ||||
| } else { | } else { | ||||
| gui.hideNodeMessage(); | gui.hideNodeMessage(); | ||||
| @@ -28,29 +24,37 @@ editor.onFreeMove = function() { | |||||
| } | } | ||||
| }; | }; | ||||
| editor.focus = function(node) { | |||||
| editor.grid.position.copy(abj.node[node].position); | |||||
| gui.controls.target.copy(abj.node[node].position); | |||||
| gui.hideNodeMessage(); | |||||
| editor.selection = node; | |||||
| gui.serverMessage("Selected node " + node + ""); | |||||
| }; | |||||
| editor.addQubitAtPoint = function(point) { | |||||
| if (point === null) { | |||||
| return; | |||||
| } | |||||
| point.round(); | |||||
| abj.add_node(abj.order(), { | |||||
| position: point | |||||
| }); | |||||
| editor.grid.position.copy(point); | |||||
| gui.controls.target.copy(point); | |||||
| graph.update(); | |||||
| gui.serverMessage("Created node at " + JSON.stringify(point)); | |||||
| }; | |||||
| editor.onClick = function() { | editor.onClick = function() { | ||||
| var n = editor.nearestNode(mouse.ray); | |||||
| if (n) { | |||||
| var p = abj.meta[n].position; | |||||
| editor.grid.position.set(p.x, p.y, p.z); | |||||
| gui.controls.target.set(p.x, p.y, p.z); | |||||
| gui.hideNodeMessage(); | |||||
| editor.nearest = undefined; | |||||
| gui.serverMessage("Selected node " + n + ""); | |||||
| var found = editor.findNodeOnRay(mouse.ray); | |||||
| if (found) { | |||||
| editor.focus(found); | |||||
| } else { | } else { | ||||
| //TODO: ghastly | |||||
| var intersection = mouse.ray.intersectPlane(editor.plane); | var intersection = mouse.ray.intersectPlane(editor.plane); | ||||
| intersection.x = Math.round(intersection.x, 0); | |||||
| intersection.y = Math.round(intersection.y, 0); | |||||
| intersection.z = Math.round(intersection.z, 0); | |||||
| var newNode = abj.order(); | |||||
| abj.add_node(newNode, { | |||||
| position: intersection | |||||
| }); | |||||
| editor.grid.position.set(intersection.x, intersection.y, intersection.z); | |||||
| gui.controls.target.set(intersection.x, intersection.y, intersection.z); | |||||
| graph.update(); | |||||
| gui.serverMessage("Created node " + newNode + " at "); | |||||
| if (intersection !== null) { | |||||
| editor.addQubitAtPoint(intersection); | |||||
| } | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -64,7 +68,7 @@ editor.prepare = function() { | |||||
| editor.onKey = function(evt) { | editor.onKey = function(evt) { | ||||
| if (evt.keyCode == 32) { | if (evt.keyCode == 32) { | ||||
| editor.grid.rotation.x += Math.PI / 2; | editor.grid.rotation.x += Math.PI / 2; | ||||
| editor.orientation = (editor.orientation+1) % 3; | |||||
| editor.orientation = (editor.orientation + 1) % 3; | |||||
| console.log(editor.orientation); | console.log(editor.orientation); | ||||
| var m = editor.orientations[editor.orientation]; | var m = editor.orientations[editor.orientation]; | ||||
| editor.plane.applyMatrix4(m); | editor.plane.applyMatrix4(m); | ||||
| @@ -79,20 +83,17 @@ editor.makeGrid = function() { | |||||
| editor.grid = new THREE.GridHelper(10, 1); | editor.grid = new THREE.GridHelper(10, 1); | ||||
| editor.grid.rotation.x = Math.PI / 2; | editor.grid.rotation.x = Math.PI / 2; | ||||
| editor.grid.setColors(0xbbbbbb, 0xeeeeee); | editor.grid.setColors(0xbbbbbb, 0xeeeeee); | ||||
| editor.grid.matrixAutoUpdate = false; | |||||
| editor.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0); | |||||
| editor.grid.matrixAutoUpdate = true; | |||||
| gui.scene.add(editor.grid); | gui.scene.add(editor.grid); | ||||
| }; | }; | ||||
| editor.update = function(){ | |||||
| }; | |||||
| editor.update = function() {}; | |||||
| // Gets a reference to the node nearest to the mouse cursor | // Gets a reference to the node nearest to the mouse cursor | ||||
| // TODO: get rid of meta{} | |||||
| editor.nearestNode = function(ray) { | |||||
| for (var j in abj.meta) { | |||||
| if (ray.distanceSqToPoint(abj.meta[j].position) < 0.03) { | |||||
| return j; | |||||
| editor.findNodeOnRay = function(ray) { | |||||
| for (var n in abj.node) { | |||||
| if (ray.distanceSqToPoint(abj.node[n].position) < 0.03) { | |||||
| return n; | |||||
| } | } | ||||
| } | } | ||||
| return undefined; | return undefined; | ||||
| @@ -14,21 +14,19 @@ graph.update = function(newState) { | |||||
| var geometry = new THREE.Geometry(); | var geometry = new THREE.Geometry(); | ||||
| geometry.colors = []; | 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.push(new THREE.Color(graph.colors[abj.vops[i] % graph.colors.length])); | |||||
| for (var i in abj.node) { | |||||
| var color = graph.colors[abj.node[i].vop % graph.colors.length]; | |||||
| geometry.vertices.push(abj.node[i].position); | |||||
| geometry.colors.push(new THREE.Color(color)); | |||||
| } | } | ||||
| var edges = new THREE.Object3D(); | var edges = new THREE.Object3D(); | ||||
| var my_edges = abj.edgelist(); | var my_edges = abj.edgelist(); | ||||
| for (i = 0; i < my_edges.length; ++i) { | for (i = 0; i < my_edges.length; ++i) { | ||||
| var edge = my_edges[i]; | var edge = my_edges[i]; | ||||
| var start = abj.meta[edge[0]].position; | |||||
| var start = abj.node[edge[0]].position; | |||||
| var startpos = new THREE.Vector3(start.x, start.y, start.z); | var startpos = new THREE.Vector3(start.x, start.y, start.z); | ||||
| var end = abj.meta[edge[1]].position; | |||||
| var end = abj.node[edge[1]].position; | |||||
| var endpos = new THREE.Vector3(end.x, end.y, end.z); | var endpos = new THREE.Vector3(end.x, end.y, end.z); | ||||
| var newEdge = materials.makeCurve(startpos, endpos); | var newEdge = materials.makeCurve(startpos, endpos); | ||||
| edges.add(newEdge); | edges.add(newEdge); | ||||
| @@ -76,15 +76,3 @@ gui.loop = function() { | |||||
| requestAnimationFrame(gui.loop); | 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.update(); | |||||
| }; | |||||
| @@ -12,9 +12,9 @@ websocket.connect = function(update) { | |||||
| ws.onmessage = function(evt) { | ws.onmessage = function(evt) { | ||||
| json = JSON.parse(evt.data); | json = JSON.parse(evt.data); | ||||
| for (var i in json.meta) { | |||||
| var pos = json.meta[i].position; | |||||
| json.meta[i].position = new THREE.Vector3(pos.x, pos.y, pos.z); | |||||
| for (var i in json.node) { | |||||
| var pos = json.node[i].position; | |||||
| json.node[i].position = new THREE.Vector3(pos.x, pos.y, pos.z); | |||||
| } | } | ||||
| update(json); | update(json); | ||||
| }; | }; | ||||