################################## # Hopfieldネットワーク( TSP ) # Coded by Y.Suganuma ################################## ################## # ユニットの出力 ################## def out(x) return 0.5 * (1.0 + Math.tanh(x)) # return 1.0 / (1.0 + Math.exp(-x)) end #***************/ # 微係数の計算 */ #***************/ snx = Proc.new { |time, u, du| for x in 0 ... $n for i in 0 ... $n k = $n * x + i du[k] = 0.0 for j in 0 ... $n if j != i du[k] -= $aa * out(u[$n*x+j]) end end for y in 0 ... $n if y != x du[k] -= $bb * out(u[$n*y+i]) end end nn = 0.0 for xx in 0 ... $n for ii in 0 ... $n nn += out(u[$n*xx+ii]) end end du[k] -= $cc * (nn - $n) for y in 0 ... $n m1 = (i + 1) % $n m2 = i - 1 if m2 < 0 m2 = $n - 1 end du[k] -= $dd * $d[x][y] * (out(u[$n*y+m1]) + out(u[$n*y+m2])) end end end } #******************************************/ # ルンゲ・クッタ法 dx/dt=f(t,x) */ # time : 現在の時間 */ # h : 時間刻み幅 */ # x : 現在の状態 */ # dx : 微係数(f(t,x):snxで計算する)*/ # g : 作業域(g[4][n]) */ # n : 微分方程式の次数 */ # snx : 微係数を計算する関数の名前 */ # return : time+h */ #******************************************/ def rkg(time, h, x, dx, g, n, &sub) h2 = 0.5 * h sub.call(time, x, dx) for i1 in 0 ... n g[0][i1] = h * dx[i1] end time += h2 for i1 in 0 ... n g[1][i1] = x[i1] + 0.5 * g[0][i1] end sub.call(time, g[1], dx) for i1 in 0 ... n g[1][i1] = h * dx[i1] end for i1 in 0 ... n g[2][i1] = x[i1] + 0.5 * g[1][i1] end sub.call(time, g[2], dx) for i1 in 0 ... n g[2][i1] = h * dx[i1] end time += h2 for i1 in 0 ... n g[3][i1] = x[i1] + g[2][i1] end sub.call(time, g[3], dx) for i1 in 0 ... n g[3][i1] = h * dx[i1] end for i1 in 0 ... n x[i1] = x[i1] + (g[0][i1] + 2.0 * g[1][i1] + 2.0 * g[2][i1] + g[3][i1]) / 6.0 end return time end $n = 4 $nn = $n * $n $aa = 10.0 $bb = 10.0 $cc = 10.0 $dd = 2.0 $d = Array.new($n) for i1 in 0 ... $n $d[i1] = Array.new($n) end # 距離 r = Math.sqrt(2.0) for i1 in 0 ... $n for i2 in 0 ... $n if i1 == i2 $d[i1][i2] = 0.0 else $d[i1][i2] = 1.0 end end end $d[0][2] = r $d[1][3] = r $d[2][0] = r $d[3][1] = r # 初期状態 srand() u = Array.new($n) for i1 in 0 ... $n u[i1] = Array.new($n) for i2 in 0 ... $n u[i1][i2] = 0.1 * rand(0) - 0.05 end end print("初期状態(出力):\n") for i1 in 0 ... $n for i2 in 0 ... $n print(" " + String(out(u[i1][i2]))) end print("\n") end # 更新 time = 0.0 dx = Array.new(16) g = Array.new(4) for i1 in 0 ... 4 g[i1] = Array.new(16) end k = 0 uu = Array.new(16) for i1 in 0 ... 4 for i2 in 0 ... 4 uu[k] = u[i1][i2] k += 1 end end for i1 in 0 ... 100 time = rkg(time, 1, uu, dx, g, $n*$n, &snx) end print("最終状態(出力):\n") k = 0 for i1 in 0 ... $n for i2 in 0 ... $n print(" " + String(out(uu[k]))) k += 1 end print("\n") end