diff --git a/semi_annealing_2x2/annealer_2x2.py b/semi_annealing_2x2/annealer_2x2.py new file mode 100644 index 0000000000000000000000000000000000000000..393141c30b42fbc52f9a13d2e71e93a0c9fe5359 --- /dev/null +++ b/semi_annealing_2x2/annealer_2x2.py @@ -0,0 +1,72 @@ +def annealer( + list_spin, + interact0, + interact1, + interact2, + interact3, + interact4, + interact5, +): + spin = [0, 0, 0, 0] + spin[0] = list_spin[0] * 2 - 1 + spin[1] = list_spin[1] * 2 - 1 + spin[2] = list_spin[2] * 2 - 1 + spin[3] = list_spin[3] * 2 - 1 + + H = [0, 0, 0, 0, 0] + + while 1: + H[4] = ( -1 * interact0 * spin[0] * spin[1] ) \ + + ( -1 * interact1 * spin[0] * spin[2] ) \ + + ( -1 * interact2 * spin[0] * spin[3] ) \ + + ( -1 * interact3 * spin[1] * spin[2] ) \ + + ( -1 * interact4 * spin[1] * spin[3] ) \ + + ( -1 * interact5 * spin[2] * spin[3] ) + + H[0] = ( interact0 * spin[0] * spin[1] ) \ + + ( interact1 * spin[0] * spin[2] ) \ + + ( interact2 * spin[0] * spin[3] ) \ + + ( -1 * interact3 * spin[1] * spin[2] ) \ + + ( -1 * interact4 * spin[1] * spin[3] ) \ + + ( -1 * interact5 * spin[2] * spin[3] ) + + H[1] = ( interact0 * spin[0] * spin[1] ) \ + + ( -1 * interact1 * spin[0] * spin[2] ) \ + + ( -1 * interact2 * spin[0] * spin[3] ) \ + + ( interact3 * spin[1] * spin[2] ) \ + + ( interact4 * spin[1] * spin[3] ) \ + + ( -1 * interact5 * spin[2] * spin[3] ) + + H[2] = ( -1 * interact0 * spin[0] * spin[1] ) \ + + ( interact1 * spin[0] * spin[2] ) \ + + ( -1 * interact2 * spin[0] * spin[3] ) \ + + ( interact3 * spin[1] * spin[2] ) \ + + ( -1 * interact4 * spin[1] * spin[3] ) \ + + ( interact5 * spin[2] * spin[3] ) + + H[3] = ( -1 * interact0 * spin[0] * spin[1] ) \ + + ( -1 * interact1 * spin[0] * spin[2] ) \ + + ( interact2 * spin[0] * spin[3] ) \ + + ( -1 * interact3 * spin[1] * spin[2] ) \ + + ( interact4 * spin[1] * spin[3] ) \ + + ( interact5 * spin[2] * spin[3] ) + + if ( H[0] < H[1] ): + invert_tmp0 = 0 + else: + invert_tmp0 = 1 + + if ( H[2] < H[3] ): + invert_tmp1 = 2 + else: + invert_tmp1 = 3 + + if ( H[invert_tmp0] < H[invert_tmp1] ): + invert = invert_tmp0 + else: + invert = invert_tmp1 + + if ( H[4] > H[invert] ): + spin[invert] = -spin[invert] + else: + return spin diff --git a/semi_annealing_2x2/annealer_2x2.v b/semi_annealing_2x2/annealer_2x2.v index 0a010319f3c67ad0a9f5ce14c7b451cc89785f08..a0d5666e7a92a5ad2506a23db2d219f1d16f8e40 100644 --- a/semi_annealing_2x2/annealer_2x2.v +++ b/semi_annealing_2x2/annealer_2x2.v @@ -18,10 +18,10 @@ module annealer_2x2( // 2x2のアニーリングマシン,外部磁場を考 reg [3:0] spin; // スピンの値,今回は1, 0で表す(+1 --> 1, -1 --> 0) reg [3:0] J0, J1, J2, J3, J4, J5; // 相互作用係数 - reg [6:0] H [4:0]; // ハミルトニアン(エネルギー),相互作用係数から42 ~ -42の値をとるので7ビット必要, + wire [6:0] H [4:0]; // ハミルトニアン(エネルギー),相互作用係数から42 ~ -42の値をとるので7ビット必要, // また,現在の状態 + ある1つのスピンの値が反転した場合の合計5通りの計算をしておく. reg state_init, state_busy, state_end; - reg invert; // どのスピンを反転させるか + wire [1:0] invert, invert_tmp; // どのスピンを反転させるか wire [6:0] Jscale [5:0]; // Jを7ビットに拡張する,7ビットのwireが6本 wire [6:0] Sscale [3:0]; // スピンの値を7ビットに拡張する,スピンの値を符号ビットのように扱う. @@ -40,6 +40,51 @@ module annealer_2x2( // 2x2のアニーリングマシン,外部磁場を考 assign Sscale[1] = { spin[1], 6'b000000 }; assign Sscale[2] = { spin[2], 6'b000000 }; assign Sscale[3] = { spin[3], 6'b000000 }; + + assign H[4] = ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ^ 7'b1000000 ) + + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ^ 7'b1000000 ) + + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ^ 7'b1000000 ) + + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ^ 7'b1000000 ) + + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ^ 7'b1000000 ) + + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ^ 7'b1000000 ); + // ハミルトニアンの計算,シグマの前の符号は各項に分配している(7'b1000000でXORを取ることで符号を反転させている) + assign H[0] = ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ) + + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ) + + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ) + + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ^ 7'b1000000 ) + + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ^ 7'b1000000 ) + + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ^ 7'b1000000 ); + // spin[0]が反転した時を想定したハミルトニアンの計算, + // spin[0]が使われている(Sscale[0]を含む)項の符号を反転させなければ良い + assign H[1] = ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ) + + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ^ 7'b1000000 ) + + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ^ 7'b1000000 ) + + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ) + + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ) + + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ^ 7'b1000000 ); + // spin[1]の反転 + assign H[2] = ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ^ 7'b1000000 ) + + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ) + + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ^ 7'b1000000 ) + + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ) + + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ^ 7'b1000000 ) + + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ); + // spin[2]の反転 + assign H[3] = ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ^ 7'b1000000 ) + + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ^ 7'b1000000 ) + + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ) + + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ^ 7'b1000000 ) + + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ) + + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ); + // spin[3]の反転 + + // ハミルトニアンが最小となる反転を見つける. + // Hはunsignedなので,キャストしてから比較 + assign invert_tmp[0] = ($signed(H[0]) > $signed(H[1])); + assign invert_tmp[1] = ($signed(H[2]) > $signed(H[3])); + + assign invert[1] = ($signed(H[{1'b0, invert_tmp[0]}]) > $signed(H[{1'b1, invert_tmp[1]}])); + assign invert[0] = invert_tmp[invert[1]]; always @( posedge clk or negedge reset_N ) begin if ( !reset_N ) @@ -53,65 +98,7 @@ module annealer_2x2( // 2x2のアニーリングマシン,外部磁場を考 { state_init, state_busy, state_end } <= 3'b010; end else if ( { state_init, state_busy, state_end } == 3'b010 ) begin - H[0] <= ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ^ 7'b1000000 ) - + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ^ 7'b1000000 ) - + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ^ 7'b1000000 ) - + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ^ 7'b1000000 ) - + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ^ 7'b1000000 ) - + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ^ 7'b1000000 ); - // ハミルトニアンの計算,シグマの前の符号は各項に分配している(7'b1000000でXORを取ることで符号を反転させている) - H[1] <= ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ) - + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ) - + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ) - + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ^ 7'b1000000 ) - + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ^ 7'b1000000 ) - + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ^ 7'b1000000 ); - // spin[0]が反転した時を想定したハミルトニアンの計算, - // spin[0]が使われている(Sscale[0]を含む)項の符号を反転させなければ良い - H[2] <= ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ) - + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ^ 7'b1000000 ) - + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ^ 7'b1000000 ) - + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ) - + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ) - + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ^ 7'b1000000 ); - // spin[1]の反転 - H[3] <= ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ^ 7'b1000000 ) - + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ) - + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ^ 7'b1000000 ) - + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ) - + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ^ 7'b1000000 ) - + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ); - // spin[2]の反転 - H[3] <= ( Jscale[0] ^ Sscale[0] ^ Sscale[1] ^ 7'b1000000 ) - + ( Jscale[1] ^ Sscale[0] ^ Sscale[2] ^ 7'b1000000 ) - + ( Jscale[2] ^ Sscale[0] ^ Sscale[3] ) - + ( Jscale[3] ^ Sscale[1] ^ Sscale[2] ^ 7'b1000000 ) - + ( Jscale[4] ^ Sscale[1] ^ Sscale[3] ) - + ( Jscale[5] ^ Sscale[2] ^ Sscale[3] ); - // spin[3]の反転 - - // ハミルトニアンが最小となる反転を見つける. - if( $signed(H[1]) < $signed(H[2]) ) // Hはunsignedなので,キャストしてから比較 - if( $signed(H[1]) < $signed(H[3]) ) - if( $signed(H[1]) < $signed(H[4]) ) - invert <= 1; - else - invert <= 4; - else if ( $signed(H[3]) < $signed(H[4]) ) - invert <= 3; - else - invert <= 4; - else if ( $signed(H[2]) < $signed(H[3]) ) - if ( $signed(H[2]) < $signed(H[4]) ) - invert <= 2; - else - invert <= 4; - else if ( $signed(H[3]) < $signed(H[4]) ) - invert <= 3; - else - invert <= 4; - - if ( $signed(H[invert]) < $signed(H[0]) ) // 反転させた方がエネルギーが小さくなった場合 + if ( $signed(H[invert]) < $signed(H[4]) ) // 反転させた方がエネルギーが小さくなった場合 spin[invert] <= ~spin[invert]; else {state_init, state_busy, state_end} <= 3'b001; diff --git "a/semi_annealing_2x2/annealer\343\201\253\343\201\244\343\201\204\343\201\246.md" "b/semi_annealing_2x2/annealer\343\201\253\343\201\244\343\201\204\343\201\246.md" index 777bd185e9e4c4310de9ae51381af9fc3b94649c..c8c685bbe5d2779f810fde45674207a74ed9b3ae 100644 --- "a/semi_annealing_2x2/annealer\343\201\253\343\201\244\343\201\204\343\201\246.md" +++ "b/semi_annealing_2x2/annealer\343\201\253\343\201\244\343\201\204\343\201\246.md" @@ -1,3 +1,5 @@ # annealerについて -2x2,4つのスピンがそれぞれ他の3つのスピンと繋がっている想定で作ってみた.構文エラーは無くしたが,果たして意図した通りに動くかは謎.もっと言えば,エネルギーが悪化するスピンの反転を認めていないので,アニーリングにもなってない代物. \ No newline at end of file +2x2,4つのスピンがそれぞれ他の3つのスピンと繋がっている想定で作ってみた.構文エラーは無くしたが,果たして意図した通りに動くかは謎.もっと言えば,エネルギーが悪化するスピンの反転を認めていないので,アニーリングにもなってない代物. + +verilogの内容を一応pythonでも書いてみたり. \ No newline at end of file