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