@@ -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): | |||
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) | |||
@@ -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)); | |||
}; | |||
@@ -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(); | |||
}; |
@@ -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(); | |||
} | |||
@@ -1,5 +1,6 @@ | |||
window.onload = function() { | |||
graph.hook(); | |||
materials.load(); | |||
gui.construct(); | |||
gui.render(); | |||
gui.loop(); | |||
}; |
@@ -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); | |||
}; | |||
@@ -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 ) | |||
@@ -19,7 +19,7 @@ websocket.connect = function(update){ | |||
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>."); | |||
}; | |||
}; | |||