Введение
Мы только что представили симулятор квантового отжига с использованием javascript. Теперь мы пытаемся на WebGL использовать ресурсы нашего ПК намного эффективнее.
Выполнение
Это просто, мы можем визуализировать большое изображение с помощью webGL. Мы вычисляем Квантовый Монте-Карло, используя javascript и отдельно webGL вместе. Вы можете визуализировать довольно большое изображение, а не только javascript.
<!doctype html> <html>
<head> <style> body { font-size: 10px; } </style> </head> <script id="qbit_vs" type="x-shader/x-vertex"> #version 300 es precision highp float; uniform int N; uniform int m; uniform float point_size; layout(location=0) in float state; layout(location=1) in float index; out vec4 vColor; void main() { // MEMO GL's 2D[-1:1], center of pixelは(0.5, 0.5) float x = (float(int(index) % N) + 0.5) / float(N) * 2.0 - 1.0; float y = (float(int(index) / N) + 0.5) / float(m) * 2.0 - 1.0; gl_Position = vec4(x, y, 0.0, 1.0); gl_PointSize = point_size; if(state > 0.0) vColor = vec4(1.0, 0.0, 0.0, 1.0); else vColor = vec4(0.0, 0.0, 1.0, 1.0); } </script> <script id="qbit_fs" type="x-shader/x-fragment"> #version 300 es precision highp float; in vec4 vColor; out vec4 outColor; void main() { outColor = vColor; } </script> <body> G=<span id="GG"></span> <br><br> <canvas id="gl_canvas" width="150" height="50"></canvas> <script> //parameters const N = 1500 const m = 750 const kT = 0.0005 const loop = 50000 let G = 5 let q = new Float32Array(N * m) let jij = 1
const point_size = 1
let index = new Float32Array(N * m) for(let i = 0; i < N * m; i++) index[i] = i
//qbit initialize for(let i = 0; i < N * m; i++) q[i] = Math.floor(Math.random() - 0.5) * 2 + 1
// WebGL variables let gl_canvas, gl, qbit_vbo, index_vbo window.onload = function() { gl_canvas = document.getElementById('gl_canvas') gl = gl_canvas.getContext("webgl2") gl.clearColor(0.8, 0.8, 0.8, 1.0) gl.canvas.width = N * point_size gl.canvas.height = m * point_size index_vbo = createVbo(index) qbit_vbo = createDynamicVbo(q) draw_program = createProgram(document.getElementById('qbit_vs').text, document.getElementById('qbit_fs').text) update() } // main function update() { // calculate if (G < 0.001) { G = 5 for(let i = 0; i < N * m; i++) q[i] = Math.floor(Math.random() - 0.5) * 2 + 1 } anneal() // draw gl.viewport(0, 0, gl.canvas.width, gl.canvas.height) gl.clear(gl.COLOR_BUFFER_BIT) gl.useProgram(draw_program) gl.bindBuffer(gl.ARRAY_BUFFER, qbit_vbo) // VBOをBindして gl.bufferSubData(gl.ARRAY_BUFFER, 0, q) // 更新 gl.uniform1i(gl.getUniformLocation(draw_program, 'N'), N) gl.uniform1i(gl.getUniformLocation(draw_program, 'm'), m) gl.uniform1f(gl.getUniformLocation(draw_program, 'point_size'), point_size) setAttribute(qbit_vbo, 0, 1) setAttribute(index_vbo, 1, 1) gl.drawArrays(gl.POINTS, 0, N * m)
window.requestAnimationFrame(update) }
function anneal() { //monte carlo loop start for (var k = 0; k < loop; k++) { const y = Math.floor(Math.random() * m) //select random trotter const x = Math.floor(Math.random() * N) //select random qbit //Energy difference calc let dE = (jij * 2 * q[y*N + x] * q[y*N + (N + x - 1) % N] + jij * 2 * q[y*N + x] * q[y*N + (x + 1) % N]) / m const kk = G / kT / m const kk1 = Math.exp(kk) const kk2 = Math.exp(-kk) //Quantum flactuation calc dE += q[y*N + x] * (q[((m + y - 1) % m)*N + x] + q[((y + 1) % m)*N + x]) * Math.log((kk1 + kk2) / (kk1 - kk2)) / kT if (dE < 0 || Math.exp(-dE / kT) > Math.random()) // Metropolis q[y*N + x] = -q[y*N + x] //flipping qbit } G *= 0.99 document.getElementById('GG').innerHTML = G }
// WebGL functions function setAttribute(vbo, attrib_loc, stride) { gl.enableVertexAttribArray(attrib_loc) gl.bindBuffer(gl.ARRAY_BUFFER, vbo) gl.vertexAttribPointer(attrib_loc, stride, gl.FLOAT, false, 0, 0) gl.bindBuffer(gl.ARRAY_BUFFER, null) }
function compileShader(prog, src, type) { const sh = gl.createShader(type) gl.shaderSource(sh, src.replace(/^\n/, "")) gl.compileShader(sh) if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) alert(gl.getShaderInfoLog(sh)) gl.attachShader(prog, sh) gl.deleteShader(sh) }
function createProgram(vs, fs) { const program = gl.createProgram() compileShader(program, vs, gl.VERTEX_SHADER) compileShader(program, fs, gl.FRAGMENT_SHADER) gl.linkProgram(program) return program }
function createVbo(data) { const vbo = gl.createBuffer() gl.bindBuffer(gl.ARRAY_BUFFER, vbo) gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW) gl.bindBuffer(gl.ARRAY_BUFFER, null) return vbo }
function createDynamicVbo(data) { const vbo = gl.createBuffer() gl.bindBuffer(gl.ARRAY_BUFFER, vbo) gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.DYNAMIC_DRAW) gl.bindBuffer(gl.ARRAY_BUFFER, null) return vbo } </script> </body>
</html>
В последнее время мы можем использовать многие веб-технологии, такие как webGL или webGPU. Он доступен без какой-либо настройки среды, которая беспокоит много раз.