量子コンピュータ
量子アニーリング

【シミュレータ】Javascriptで量子アニーリング


はじめに

量子コンピュータの活用に関しては必ずしも実機が手に入りません。そのため、シミュレータを活用することが多々あります。今回はJavascriptで量子アニーリングのシミュレータを確認することで、様々なインターフェイスを導入することができます。


コードの確認

早速コードを確認してみたいと思います。

下記は150量子ビットで並列数に対応するトロッタ数が50の量子アニーリングです。Jijという量子ビット間の相互作用は固定です。

1、量子ビットをランダムに初期化します。今回は150量子ビットに対して50トロッタあるので、全部で150*50量子ビットの初期化を-1か+1で行います。

2、早速量子モンテカルロ計算です。スケジュールはあらかじめG=10から0.999倍の減衰を2000回繰り返しながら横磁場を減らしていく計算を行います。また、各Gに対して50000回程度の平衡状態の計算を行います。

3、トロッタを選び、量子ビットを選びトライアルをします。量子ビット間のエネルギーの変化をみながら、異なるトロッタの間のエネルギーの変化もみます。

4、変化するエネルギー差dEをみて、メトロポリス法にかけます。そして、条件を満たす場合には量子ビットを反転させます。

5、以上の操作を繰り返します。

 //パラメータ類

var N = 150;
var kT = 0.02;
var G = 10;
var q = [];
var m = 50 ;
var jij = 1;
var loop = 50000;

//量子ビット初期化
for(var j=0;j<m;j++){
q[j] = [];
for(var i=0;i<N;i++){
q[j][i] = Math.floor(Math.random()-0.5)*2+1;
};
};

//量子モンテカルロ計算
for(var l=0;l<2000;l++){
for(var k=0;k<loop;k++){
var y = Math.floor(Math.random()*m); //トロッタのランダム選択
var x = Math.floor(Math.random()*N); //量子ビットのランダム選択
var dE = (jij*2*q[y][x]*q[y][(N+x-1)%N] + jij*2*q[y][x]*q[y][(x+1)%N])/m; //エネルギー計算
var kk = G/kT/m;
var kk1 = Math.exp(kk);
var kk2 = Math.exp(-kk);
dE += q[y][x]*(q[(m+y-1)%m][x]+q[(y+1)%m][x])*Math.log((kk1+kk2)/(kk1-kk2))/kT;
if(dE<0 || Math.exp(-dE/kT)>Math.random()){ //メトロポリス法
q[y][x] = -q[y][x]; //量子ビットの反転
};
};

G = G*0.999;
};


キメラグラフの実装

キメラグラフが実装したい場合には、接続を制限します。ほとんど同じですが、途中の接続部分を工夫しています。制限方法は他にもありそうです。


var N = 512;
var kT = 0.02;
var G = 10;
var q = [];
var m = 256;
var jij = 1;
var hcell = 8;
var hq = hcell*8;

for(var j=0;j<m;j++){
q[j] = [];
for(var i=0;i<N;i++){
q[j][i] = Math.floor(Math.random()-0.5)*2+1;
};
};

for(var l=0;l<600;l++){
for(var k=0;k<N*m;k++){
var x = Math.floor(Math.random()*N);
var y = Math.floor(Math.random()*m);
var xcell = Math.floor(x/8)*8;
if(x%8<4){
var dE = jij*2*q[y][x]*(q[y][xcell+4]+q[y][xcell+5]+q[y][xcell+6]+q[y][xcell+7]);
if(x<N-hq){
dE += jij*2*q[y][x]*(q[y][x+hq]);
}
if(x>hq-1){
dE += jij*2*q[y][x]*(q[y][x-hq]);
}
}else{
var dE = jij*2*q[y][x]*(q[y][xcell+0]+q[y][xcell+1]+q[y][xcell+2]+q[y][xcell+3]);
if(x%hq>7){
dE += jij*2*q[y][x]*q[y][x-8];
}
if(x%hq<hq-8){
dE += jij*2*q[y][x]*q[y][x+8];
}
}

dE = dE/m;
var kk = G/kT/m;
var kk1 = Math.exp(kk);
var kk2 = Math.exp(-kk);
dE += q[y][x]*(q[(m+y-1)%m][x]+q[(y+1)%m][x])*Math.log((kk1+kk2)/(kk1-kk2))/kT;
if(dE<0 || Math.exp(-dE/kT)>Math.random()){
q[y][x] = -q[y][x];
};
};

G = G*0.99;
};


SAでキメラグラフの実装

SQAはシミュレーテッドアニーリングが元になっているので、SAでもできます。下記の通りです。

var N = 2048;

var kT = 5;
var q = [];
var jij = -1;
var hcell = 16;
var hq = hcell*8;

for(var i=0;i<N;i++){
q[i] = Math.floor(Math.random()-0.5)*2+1;
};

for(var i=0;i<550;i++){
for(var k=0;k<N;k++){
var x = Math.floor(Math.random()*N);
var xcell = Math.floor(x/8)*8;
if(x%8<4){
var dE = jij*2*q[x]*(q[xcell+4]+q[xcell+5]+q[xcell+6]+q[xcell+7]);
if(x<N-hq){
dE += jij*2*q[x]*(q[x+hq]);
}
if(x>hq-1){
dE += jij*2*q[x]*(q[x-hq]);
}
}else{
var dE = jij*2*q[x]*(q[xcell+0]+q[xcell+1]+q[xcell+2]+q[xcell+3]);
if(x%hq>7){
dE += jij*2*q[x]*q[x-8];
}
if(x%hq<hq-8){
dE += jij*2*q[x]*q[x+8];
}
}
if(dE<0 || Math.exp(-dE/kT)>Math.random()){
q[x] = -q[x];
};
}

kT= kT*0.99;
};

だいぶ短いですね。


量子アニーリングの見える化

htmlとjsですので、sqaの途中過程をhtml canvasで書き出すことで可視化ができます。

2e48d16da2e386445efb1044e2238825-1-1024x441.png

<!doctype html>

<html>
<head>
<style>body{font-size:10px;}</style>
</head>
<body>
kT=0.02<br>
G=<span id="GG"></span><br><br>
<canvas id="main" width="2000" height="900"></canvas>
<script>
//parameters
var N = 150;
var kT = 0.02;
var G = 10;
var q = [];
var m = 50 ;
var jij = 1;
var loop = 50000;
//qbit initialize
for(var j=0;j<m;j++){
q[j] = [];
for(var i=0;i<N;i++){
q[j][i] = Math.floor(Math.random()-0.5)*2+1;
};
};
//html5 canvas
var canvas = document.getElementById('main');
var ctx = canvas.getContext('2d');
var anneal = setInterval(function(){
//monte carlo loop start
for(var k=0;k<loop;k++){
var y = Math.floor(Math.random()*m); //select random trotter
var x = Math.floor(Math.random()*N); //select random qbit
var dE = (jij*2*q[y][x]*q[y][(N+x-1)%N] + jij*2*q[y][x]*q[y][(x+1)%N])/m; //Energy difference calc
var kk = G/kT/m;
var kk1 = Math.exp(kk);
var kk2 = Math.exp(-kk);
dE += q[y][x]*(q[(m+y-1)%m][x]+q[(y+1)%m][x])*Math.log((kk1+kk2)/(kk1-kk2))/kT; //Quantum flactuation calc
if(dE<0 || Math.exp(-dE/kT)>Math.random()){ // Metropolis
q[y][x] = -q[y][x]; //flipping qbit
};
};
//updating drawing
ctx.clearRect(0,0,2000,900);
ctx.beginPath();
for(var j=0;j<m;j++){
for(var i=0;i<N;i++){
if(q[j][i]==1){
ctx.fillStyle = 'rgb(255,0,0)';
}else{
ctx.fillStyle = 'rgb(255,255,255)';
}
ctx.fillRect(i*7,j*8,5,5);
};
};
G = G*0.999;
if(G<0.1){ //finishing
clearInterval(anneal);
};
document.getElementById('GG').innerHTML = G;
},1);
</script>
</body>
</html>

動いてる動画は楽しいのでぜひやってみてください。


キメラグラフの可視化

こちらもcanvas使って簡単にできます。

1b58e849b1734553f8296f7aa9dca949.png

<!doctype html>

<html>
<head>
<style>body{font-size:10px;}</style>
</head>
<body>
G=<span id="GG"></span><br><br>
<canvas id="main" width="2000" height="900"></canvas>
<script>
var N = 512;
var kT = 0.02;
var G = 10;
var q = [];
var m = 256;
var jij = 1;
var hcell = 8;
var hq = hcell*8;
var drawtrotter = 10;
var alpha = 1/drawtrotter;
for(var j=0;j<m;j++){
q[j] = [];
for(var i=0;i<N;i++){
q[j][i] = Math.floor(Math.random()-0.5)*2+1;
};
};
var canvas = document.getElementById('main');
var ctx = canvas.getContext('2d');
var anneal = setInterval(function(){
for(var k=0;k<N*m;k++){
var x = Math.floor(Math.random()*N);
var y = Math.floor(Math.random()*m);
var xcell = Math.floor(x/8)*8;
if(x%8<4){
var dE = jij*2*q[y][x]*(q[y][xcell+4]+q[y][xcell+5]+q[y][xcell+6]+q[y][xcell+7]);
if(x<N-hq){
dE += jij*2*q[y][x]*(q[y][x+hq]);
}
if(x>hq-1){
dE += jij*2*q[y][x]*(q[y][x-hq]);
}
}else{
var dE = jij*2*q[y][x]*(q[y][xcell+0]+q[y][xcell+1]+q[y][xcell+2]+q[y][xcell+3]);
if(x%hq>7){
dE += jij*2*q[y][x]*q[y][x-8];
}
if(x%hq<hq-8){
dE += jij*2*q[y][x]*q[y][x+8];
}
}
dE = dE/m;
var kk = G/kT/m;
var kk1 = Math.exp(kk);
var kk2 = Math.exp(-kk);
dE += q[y][x]*(q[(m+y-1)%m][x]+q[(y+1)%m][x])*Math.log((kk1+kk2)/(kk1-kk2))/kT;
if(dE<0 || Math.exp(-dE/kT)>Math.random()){
q[y][x] = -q[y][x];
};
};
ctx.clearRect(0,0,2000,900);
for(var j=0;j<10;j++){
for(var i=0;i<N;i++){
if(q[j][i]==1){
ctx.fillStyle = 'rgba(255,0,0,'+alpha+')';
}else{
ctx.fillStyle = 'rgba(0,0,0,0)';
}
if(i%8<4){
ctx.fillRect(3+i%8*7+Math.floor(i%hq/8)*40,Math.floor(i/hq)*40,3,30);
}else{
ctx.fillRect(Math.floor(i%hq/8)*40,i%8*7-25+Math.floor(i/hq)*40,30,3);
}
};
};
G = G*0.999;
document.getElementById('GG').innerHTML = G;
if(G<0.05){
clearInterval(anneal);
}
},1);
</script>
</body>
</html>


まとめ

このようにjavascriptを使って可視化知ることで計算過程のチェックや理解に役立てることができます。