##################################
# 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