@@ -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); | ||||
}; | }; | ||||