@@ -1,12 +1,12 @@ | |||
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) { | |||
@@ -14,8 +14,8 @@ abj.add_nodes = function(nodes) { | |||
}; | |||
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) { | |||
@@ -25,12 +25,12 @@ abj.add_edges = function(edges) { | |||
}; | |||
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) { | |||
return Object.prototype.hasOwnProperty.call(abj.ngbh[a], b); | |||
return Object.prototype.hasOwnProperty.call(abj.adj[a], b); | |||
}; | |||
abj.toggle_edge = function(a, b) { | |||
@@ -42,7 +42,7 @@ abj.toggle_edge = function(a, b) { | |||
}; | |||
abj.get_swap = function(node, avoid) { | |||
for (var i in abj.ngbh[node]) { | |||
for (var i in abj.adj[node]) { | |||
if (i != avoid) { | |||
return i; | |||
} | |||
@@ -52,7 +52,7 @@ abj.get_swap = function(node, avoid) { | |||
abj.remove_vop = function(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) { | |||
var v = decomposition[i]; | |||
local_complementation(v == "x" ? a : swap_qubit); | |||
@@ -60,19 +60,19 @@ abj.remove_vop = function(node, avoid) { | |||
}; | |||
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 j = i + 1; j < keys.length; ++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) { | |||
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) { | |||
@@ -84,19 +84,19 @@ abj.is_sole_member = function(node, group) { | |||
}; | |||
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); | |||
} | |||
if (is_sole_member(abj.ngbh[b], a)) { | |||
if (is_sole_member(abj.adj[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); | |||
} | |||
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) { | |||
toggle_edge(a, b); | |||
} | |||
@@ -105,8 +105,8 @@ abj.act_cz = function(a, b) { | |||
abj.edgelist = function() { | |||
var seen = {}; | |||
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)) { | |||
output.push([i, j]); | |||
} | |||
@@ -117,17 +117,16 @@ abj.edgelist = 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.vops = newState.vops; | |||
abj.ngbh = newState.ngbh; | |||
abj.meta = newState.meta; | |||
abj.node = newState.node; | |||
abj.adj = newState.adj; | |||
}; | |||
abj.order = function(){ | |||
return Object.keys(abj.vops).length; | |||
return Object.keys(abj.node).length; | |||
}; | |||
@@ -1,26 +1,22 @@ | |||
var editor = {}; | |||
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.orientations[1].makeRotationX(pi2); | |||
editor.orientations[2].makeRotationX(pi2); | |||
editor.orientations[2].makeRotationZ(pi2); | |||
editor.plane = editor.planes[editor.orientation]; | |||
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"); | |||
} else { | |||
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() { | |||
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 { | |||
//TODO: ghastly | |||
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) { | |||
if (evt.keyCode == 32) { | |||
editor.grid.rotation.x += Math.PI / 2; | |||
editor.orientation = (editor.orientation+1) % 3; | |||
editor.orientation = (editor.orientation + 1) % 3; | |||
console.log(editor.orientation); | |||
var m = editor.orientations[editor.orientation]; | |||
editor.plane.applyMatrix4(m); | |||
@@ -79,20 +83,17 @@ editor.makeGrid = function() { | |||
editor.grid = new THREE.GridHelper(10, 1); | |||
editor.grid.rotation.x = Math.PI / 2; | |||
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); | |||
}; | |||
editor.update = function(){ | |||
}; | |||
editor.update = function() {}; | |||
// 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; | |||
@@ -14,21 +14,19 @@ graph.update = function(newState) { | |||
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.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 my_edges = abj.edgelist(); | |||
for (i = 0; i < my_edges.length; ++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 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 newEdge = materials.makeCurve(startpos, endpos); | |||
edges.add(newEdge); | |||
@@ -76,15 +76,3 @@ gui.loop = function() { | |||
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) { | |||
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); | |||
}; | |||