@@ -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])) | |||||
@@ -6,7 +6,7 @@ s = VisibleGraphState() | |||||
for i in range(200): | for i in range(200): | ||||
x = 10*np.cos(np.pi*2*i/60) | x = 10*np.cos(np.pi*2*i/60) | ||||
y = 10*np.sin(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") | s.act_local_rotation(i, "hadamard") | ||||
for i in range(200-1): | for i in range(200-1): | ||||
s.act_cz(i, i+1) | s.act_cz(i, i+1) | ||||
@@ -1,15 +1,9 @@ | |||||
var abj = {}; | var abj = {}; | ||||
abj.ngbh = {}; | |||||
abj.vops = {}; | |||||
abj.meta = {}; | |||||
ngbh = abj.ngbh; | |||||
vops = abj.vops; | |||||
meta = abj.meta; | |||||
abj.add_node = function(node, m) { | 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) { | abj.add_nodes = function(nodes) { | ||||
@@ -17,8 +11,8 @@ abj.add_nodes = function(nodes) { | |||||
}; | }; | ||||
abj.add_edge = function(a, b) { | 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) { | abj.add_edges = function(edges) { | ||||
@@ -28,12 +22,12 @@ abj.add_edges = function(edges) { | |||||
}; | }; | ||||
abj.del_edge = function(a, b) { | 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) { | 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) { | abj.toggle_edge = function(a, b) { | ||||
@@ -45,7 +39,7 @@ abj.toggle_edge = function(a, b) { | |||||
}; | }; | ||||
abj.get_swap = function(node, avoid) { | abj.get_swap = function(node, avoid) { | ||||
for (var i in ngbh[node]) { | |||||
for (var i in abj.ngbh[node]) { | |||||
if (i != avoid) { | if (i != avoid) { | ||||
return i; | return i; | ||||
} | } | ||||
@@ -55,7 +49,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[vops[node]]; | |||||
var decomposition = decompositions[abj.vops[node]]; | |||||
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); | ||||
@@ -63,19 +57,19 @@ abj.remove_vop = function(node, avoid) { | |||||
}; | }; | ||||
abj.local_complementation = function(node) { | 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 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]); | ||||
} | } | ||||
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) { | abj.act_local_rotation = function(node, operation) { | ||||
var rotation = tables.clifford[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) { | abj.act_hadamard = function(node) { | ||||
@@ -87,19 +81,19 @@ abj.is_sole_member = function(node, group) { | |||||
}; | }; | ||||
abj.act_cz = function(a, b) { | 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); | remove_vop(a, b); | ||||
} | } | ||||
if (is_sole_member(ngbh[b], a)) { | |||||
if (is_sole_member(abj.ngbh[b], a)) { | |||||
remove_vop(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); | 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][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) { | if (new_state[0] != edge) { | ||||
toggle_edge(a, b); | toggle_edge(a, b); | ||||
} | } | ||||
@@ -108,8 +102,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 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)) { | if (!Object.prototype.hasOwnProperty.call(seen, j)) { | ||||
output.push([i, j]); | output.push([i, j]); | ||||
} | } | ||||
@@ -120,7 +114,7 @@ abj.edgelist = function() { | |||||
}; | }; | ||||
abj.log_graph_state = 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)); | |||||
}; | }; | ||||
@@ -7,24 +7,25 @@ graph.hook = function() { | |||||
}; | }; | ||||
graph.update = function(json) { | 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(); | ||||
}; | }; | ||||
graph.updateScene = function() { | 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(); | var geometry = new THREE.Geometry(); | ||||
geometry.colors = []; | |||||
for (var i in abj.vops) { | for (var i in abj.vops) { | ||||
var vop = abj.vops[i]; | var vop = abj.vops[i]; | ||||
var pos = abj.meta[i].position; | var pos = abj.meta[i].position; | ||||
var vertex = new THREE.Vector3(pos.x, pos.y, pos.z); | var vertex = new THREE.Vector3(pos.x, pos.y, pos.z); | ||||
geometry.vertices.push(vertex); | 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(); | var edges = new THREE.Object3D(); | ||||
@@ -32,18 +33,18 @@ graph.updateScene = function() { | |||||
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.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 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); | edges.add(newEdge); | ||||
} | } | ||||
var particles = new THREE.Points(geometry, materials.qubit); | 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(); | |||||
}; | }; |
@@ -1,6 +1,8 @@ | |||||
var gui = {}; | var gui = {}; | ||||
gui.construct = function() { | gui.construct = function() { | ||||
gui.renderer = new THREE.WebGLRenderer(); | |||||
gui.renderer = new THREE.WebGLRenderer({ | |||||
"antialias": true | |||||
}); | |||||
gui.renderer.setSize(window.innerWidth, window.innerHeight); | gui.renderer.setSize(window.innerWidth, window.innerHeight); | ||||
gui.renderer.setClearColor(0xffffff, 1); | gui.renderer.setClearColor(0xffffff, 1); | ||||
document.querySelector("body").appendChild(gui.renderer.domElement); | 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.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.3, 1000); | ||||
gui.controls = new THREE.OrbitControls(gui.camera); | gui.controls = new THREE.OrbitControls(gui.camera); | ||||
gui.controls.addEventListener("change", gui.render); | |||||
gui.controls.center.set(0, 0, 0); | gui.controls.center.set(0, 0, 0); | ||||
gui.controls.rotateSpeed = 0.2; | gui.controls.rotateSpeed = 0.2; | ||||
gui.camera.position.set(0, 0, 20); | gui.camera.position.set(0, 0, 20); | ||||
gui.controls.addEventListener("change", gui.render); | |||||
}; | }; | ||||
// Someone resized the window | // Someone resized the window | ||||
@@ -27,8 +29,9 @@ gui.onWindowResize = function(evt) { | |||||
// Render the current frame to the screen | // Render the current frame to the screen | ||||
gui.render = function() { | 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 | // Make the extra bits of gui | ||||
@@ -41,8 +44,25 @@ gui.makeScene = function() { | |||||
}; | }; | ||||
// Put an HTML message to the screen | // Put an HTML message to the screen | ||||
gui.serverMessage = function(msgtext){ | |||||
gui.serverMessage = function(msgtext) { | |||||
message.innerHTML = msgtext; | message.innerHTML = msgtext; | ||||
message.className = "visible"; | 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(); | |||||
} | |||||
@@ -1,5 +1,6 @@ | |||||
window.onload = function() { | window.onload = function() { | ||||
graph.hook(); | graph.hook(); | ||||
materials.load(); | |||||
gui.construct(); | gui.construct(); | ||||
gui.render(); | |||||
gui.loop(); | |||||
}; | }; |
@@ -1,38 +1,32 @@ | |||||
var materials = {}; | 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", | color: "gray", | ||||
transparent: false, | transparent: false, | ||||
linewidth: 1 | linewidth: 1 | ||||
}), | |||||
point: new THREE.PointsMaterial({ | |||||
}); | |||||
materials.point = new THREE.PointsMaterial({ | |||||
size: 0.1, | size: 0.1, | ||||
map: materials.textures.sprite, | |||||
map: sprite, | |||||
alphaTest: 0.5, | alphaTest: 0.5, | ||||
transparent: true, | transparent: true, | ||||
vertexColors: THREE.VertexColors | 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, | alphaTest: 0.5, | ||||
transparent: true, | transparent: true, | ||||
vertexColors: THREE.VertexColors | vertexColors: THREE.VertexColors | ||||
}) | |||||
}); | |||||
}; | }; | ||||
materials.makeCurve = function(a, b) { | materials.makeCurve = function(a, b) { | ||||
@@ -43,6 +37,6 @@ materials.makeCurve = function(a, b) { | |||||
var geometry = new THREE.Geometry(); | var geometry = new THREE.Geometry(); | ||||
var splinePoints = spline.getPoints(curveProperties.splineDensity); | var splinePoints = spline.getPoints(curveProperties.splineDensity); | ||||
Array.prototype.push.apply(geometry.vertices, splinePoints); | Array.prototype.push.apply(geometry.vertices, splinePoints); | ||||
return new THREE.Line(geometry, materials.materials.edge); | |||||
return new THREE.Line(geometry, materials.edge); | |||||
}; | }; | ||||
@@ -224,6 +224,7 @@ THREE.OrbitControls = function ( object, domElement ) { | |||||
if ( scope.enabled === false ) return; | if ( scope.enabled === false ) return; | ||||
if ( scope.userRotate === false ) return; | if ( scope.userRotate === false ) return; | ||||
event.preventDefault(); | event.preventDefault(); | ||||
if ( state === STATE.NONE ) | if ( state === STATE.NONE ) | ||||
@@ -19,7 +19,7 @@ websocket.connect = function(update){ | |||||
ws.onclose = function(evt) | ws.onclose = function(evt) | ||||
{ | { | ||||
gui.serverMessage("Connection to server lost. <a href='#' onclick='javascript:connect_to_server()'>Reconnect</a>."); | |||||
gui.serverMessage("Connection to server lost. <a href='#' onclick='javascript:websocket.connect()'>Reconnect</a>."); | |||||
}; | }; | ||||
}; | }; | ||||