Simulated annealing: Difference between revisions

Line 2,643:
28 38 48 49 39 29 19 9 8 7 6 5 4 14 13 12 11 2 3 1
0</pre>
 
=={{header|RATFOR}}==
{{trans|Fortran}}
 
{{works with|ratfor77|[https://sourceforge.net/p/chemoelectric/ratfor77/ public domain 1.0]}}
{{works with|gfortran|11.3.0}}
 
 
<lang ratfor>#
# The Rosetta Code simulated annealing task, in Ratfor 77.
#
# This implementation uses the RANDOM_NUMBER intrinsic and therefore
# will not work with f2c. It will work with gfortran. (One could
# substitute a random number generator from the Fullerton Function
# Library, or from elsewhere.)
#
 
function rndint (imin, imax)
implicit none
 
integer imin, imax, rndint
 
real rndnum
 
call random_number (rndnum)
rndint = imin + floor ((imax - imin + 1) * rndnum)
end
 
function icoord (loc)
implicit none
 
integer loc, icoord
 
icoord = loc / 10
end
 
function jcoord (loc)
implicit none
 
integer loc, jcoord
 
jcoord = mod (loc, 10)
end
 
function locatn (i, j) # Location.
implicit none
 
integer i, j, locatn
 
locatn = (10 * i) + j
end
 
subroutine rndpth (path) # Randomize a path.
implicit none
 
integer path(0:99)
 
integer rndint
 
integer i, j, xi, xj
 
for (i = 0; i <= 99; i = i + 1)
path(i) = i
 
# Fisher-Yates shuffle of elements 1 .. 99.
for (i = 1; i <= 98; i = i + 1)
{
j = rndint (i + 1, 99)
xi = path(i)
xj = path(j)
path(i) = xj
path(j) = xi
}
end
 
function dstnce (loc1, loc2) # Distance.
implicit none
 
integer loc1, loc2
real dstnce
 
integer icoord, jcoord
 
integer i1, j1
integer i2, j2
integer di, dj
 
i1 = icoord (loc1)
j1 = jcoord (loc1)
i2 = icoord (loc2)
j2 = jcoord (loc2)
di = i1 - i2
dj = j1 - j2
dstnce = sqrt (real ((di * di) + (dj * dj)))
end
 
function pthlen (path) # Path length.
implicit none
 
integer path(0:99)
real pthlen
 
real dstnce
 
real len
integer i
 
len = dstnce (path(0), path(99))
for (i = 0; i <= 98; i = i + 1)
len = len + dstnce (path(i), path(i + 1))
pthlen = len
end
 
subroutine addnbr (nbrs, numnbr, nbr) # Add neighbor.
implicit none
 
integer nbrs(1:8)
integer numnbr
integer nbr
 
if (nbr != 0)
{
numnbr = numnbr + 1
nbrs(numnbr) = nbr
}
end
 
subroutine fndnbr (loc, nbrs, numnbr) # Find neighbors.
implicit none
 
integer loc
integer nbrs(1:8)
integer numnbr
 
integer icoord, jcoord
integer locatn
 
integer i, j
integer c1, c2, c3, c4, c5, c6, c7, c8
 
c1 = 0
c2 = 0
c3 = 0
c4 = 0
c5 = 0
c6 = 0
c7 = 0
c8 = 0
 
i = icoord (loc)
j = jcoord (loc)
 
if (i < 9)
{
c1 = locatn (i + 1, j)
if (j < 9)
c2 = locatn (i + 1, j + 1)
if (0 < j)
c3 = locatn (i + 1, j - 1)
}
if (0 < i)
{
c4 = locatn (i - 1, j)
if (j < 9)
c5 = locatn (i - 1, j + 1)
if (0 < j)
c6 = locatn (i - 1, j - 1)
}
if (j < 9)
c7 = locatn (i, j + 1)
if (0 < j)
c8 = locatn (i, j - 1)
 
numnbr = 0
call addnbr (nbrs, numnbr, c1)
call addnbr (nbrs, numnbr, c2)
call addnbr (nbrs, numnbr, c3)
call addnbr (nbrs, numnbr, c4)
call addnbr (nbrs, numnbr, c5)
call addnbr (nbrs, numnbr, c6)
call addnbr (nbrs, numnbr, c7)
call addnbr (nbrs, numnbr, c8)
end
 
subroutine nbrpth (path, nbrp) # Make a neighbor path.
implicit none
 
integer path(0:99), nbrp(0:99)
 
integer rndint
 
integer u, v
integer nbrs(1:8)
integer numnbr
integer j, iu, iv
 
for (j = 0; j <= 99; j = j + 1)
nbrp(j) = path(j)
 
u = rndint (1, 99)
call fndnbr (u, nbrs, numnbr)
v = nbrs(rndint (1, numnbr))
 
j = 1
iu = 0
iv = 0
while (iu == 0 || iv == 0)
{
if (nbrp(j) == u)
iu = j
else if (nbrp(j) == v)
iv = j
j = j + 1
}
nbrp(iu) = v
nbrp(iv) = u
end
 
function temp (kT, kmax, k) # Temperature.
implicit none
 
real kT
integer kmax, k
real temp
 
real kf, kmaxf
 
kf = real (k)
kmaxf = real (kmax)
temp = kT * (1.0 - (kf / kmaxf))
end
 
function prob (deltaE, T) # Probability.
implicit none
 
real deltaE, T, prob
real x
 
if (T == 0.0)
prob = 0.0
else
{
x = -(deltaE / T)
if (x < -80)
prob = 0 # Avoid underflow.
else
prob = exp (-(deltaE / T))
}
end
 
subroutine show (k, T, E)
implicit none
 
integer k
real T, E
 
10 format (1X, I7, 1X, F7.1, 1X, F10.2)
 
write (*, 10) k, T, E
end
 
subroutine dsplay (path)
implicit none
 
integer path(0:99)
 
100 format (8(I2, ' -> '))
 
write (*, 100) path
end
 
subroutine sa (kT, kmax, path)
implicit none
 
real kT
integer kmax
integer path(0:99)
 
real pthlen
real temp, prob
 
integer kshow
integer k
integer j
real E, Etrial, T
integer trial(0:99)
real rndnum
 
kshow = kmax / 10
 
E = pthlen (path)
for (k = 0; k <= kmax; k = k + 1)
{
T = temp (kT, kmax, k)
if (mod (k, kshow) == 0)
call show (k, T, E)
call nbrpth (path, trial)
Etrial = pthlen (trial)
if (Etrial <= E)
{
for (j = 0; j <= 99; j = j + 1)
path(j) = trial(j)
E = Etrial
}
else
{
call random_number (rndnum)
if (rndnum <= prob (Etrial - E, T))
{
for (j = 0; j <= 99; j = j + 1)
path(j) = trial(j)
E = Etrial
}
}
}
end
 
program simanl
implicit none
 
real pthlen
 
integer path(0:99)
real kT
integer kmax
 
kT = 1.0
kmax = 1000000
 
10 format ()
20 format (' kT: ', F0.2)
30 format (' kmax: ', I0)
40 format (' k T E(s)')
50 format (' --------------------------')
60 format ('Final E(s): ', F0.2)
 
write (*, 10)
write (*, 20) kT
write (*, 30) kmax
write (*, 10)
write (*, 40)
write (*, 50)
call rndpth (path)
call sa (kT, kmax, path)
write (*, 10)
call dsplay (path)
write (*, 10)
write (*, 60) pthlen (path)
write (*, 10)
end</lang>
 
{{out}}
An example run:
<pre>$ ratfor77 simanneal.r > sa.f && gfortran -O3 -std=legacy sa.f && ./a.out
 
kT: 1.00
kmax: 1000000
 
k T E(s)
--------------------------
0 1.0 547.76
100000 0.9 190.62
200000 0.8 187.74
300000 0.7 171.72
400000 0.6 153.08
500000 0.5 131.15
600000 0.4 119.57
700000 0.3 111.20
800000 0.2 105.31
900000 0.1 103.07
1000000 0.0 102.89
 
0 -> 1 -> 2 -> 12 -> 11 -> 32 -> 33 -> 43 ->
42 -> 52 -> 51 -> 41 -> 31 -> 30 -> 40 -> 50 ->
60 -> 61 -> 62 -> 63 -> 53 -> 54 -> 44 -> 34 ->
24 -> 25 -> 14 -> 15 -> 16 -> 26 -> 36 -> 35 ->
45 -> 55 -> 56 -> 46 -> 47 -> 57 -> 58 -> 68 ->
67 -> 77 -> 86 -> 76 -> 66 -> 65 -> 64 -> 74 ->
75 -> 85 -> 84 -> 83 -> 73 -> 72 -> 71 -> 70 ->
80 -> 90 -> 91 -> 81 -> 82 -> 92 -> 93 -> 94 ->
95 -> 96 -> 97 -> 87 -> 98 -> 99 -> 89 -> 88 ->
78 -> 79 -> 69 -> 59 -> 49 -> 48 -> 39 -> 38 ->
37 -> 27 -> 17 -> 18 -> 28 -> 29 -> 19 -> 9 ->
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 13 -> 23 ->
22 -> 21 -> 20 -> 10 ->
 
Final E(s): 102.89
</pre>
 
 
 
=={{header|Scheme}}==
1,448

edits