Simulated annealing: Difference between revisions
Content added Content deleted
(added Perl 6 programming solution) |
|||
Line 644: | Line 644: | ||
path: @[0, 10, 11, 22, 21, 20, 30, 31, 41, 40, 50, 51, 61, 60, 70, 71, 81, 80, 90, 91, 92, 93, 82, 83, 73, 72, 62, 63, 53, 52, 42, 32, 33, 23, 13, 14, 24, 34, 35, 25, 15, 16, 26, 36, 47, 48, 38, 39, 49, 59, 58, 57, 68, 69, 79, 89, 99, 98, 97, 96, 95, 94, 84, 74, 75, 85, 86, 87, 88, 78, 77, 67, 76, 66, 65, 64, 54, 43, 44, 45, 55, 56, 46, 37, 27, 28, 29, 19, 9, 8, 18, 17, 7, 6, 5, 4, 3, 2, 12, 1, 0] |
path: @[0, 10, 11, 22, 21, 20, 30, 31, 41, 40, 50, 51, 61, 60, 70, 71, 81, 80, 90, 91, 92, 93, 82, 83, 73, 72, 62, 63, 53, 52, 42, 32, 33, 23, 13, 14, 24, 34, 35, 25, 15, 16, 26, 36, 47, 48, 38, 39, 49, 59, 58, 57, 68, 69, 79, 89, 99, 98, 97, 96, 95, 94, 84, 74, 75, 85, 86, 87, 88, 78, 77, 67, 76, 66, 65, 64, 54, 43, 44, 45, 55, 56, 46, 37, 27, 28, 29, 19, 9, 8, 18, 17, 7, 6, 5, 4, 3, 2, 12, 1, 0] |
||
</pre> |
</pre> |
||
=={{header|Perl 6}}== |
|||
{{trans|Go}} |
|||
<lang perl6>#!/usr/bin/env perl6 |
|||
my $dists = calcDists; |
|||
my \dirs = <1 -1 10 -10 9 11 -11 -9>; # all 8 neighbors |
|||
sub calcDists { # distances |
|||
loop (my @dists, my $j = 0; $j < 10000; $j++) { |
|||
my ($ab, $cd) = ($j/100).floor, ($j%100).floor; |
|||
my ($a, $b) = ($ab/10).floor, ($ab.Int % 10).floor; |
|||
my ($c, $d) = ($cd/10).floor, ($cd.Int % 10); |
|||
@dists[$j] = sqrt(($a-$c)² + ($b-$d)²) |
|||
} |
|||
return @dists |
|||
} |
|||
sub dist(\ci, \cj) { return @$dists[cj×100+ci] } # index into lookup table |
|||
sub Es(@path) { # energy at s, to be minimized |
|||
loop (my $d = 0,my $i = 0; $i < +@path-1; $i++ ) { |
|||
$d += dist @path[$i], @path[$i+1] |
|||
} |
|||
return $d |
|||
} |
|||
sub T(\k, \kmax, \kT) { # temperature function, decreases to 0 |
|||
return (1 - k/kmax) * kT |
|||
} |
|||
sub dE(\s, \u, \v) { # variation of E, from state s to state s_next |
|||
my ($su, $sv) = s[u], s[v]; |
|||
# old |
|||
my ($a, $b, $c, $d) = dist(s[u-1], $su), dist(s[u+1], $su), dist(s[v-1], $sv), dist(s[v+1], $sv); |
|||
# new |
|||
my ($na, $nb, $nc, $nd) = dist(s[u-1], $sv), dist(s[u+1], $sv), dist(s[v-1], $su), dist(s[v+1], $su); |
|||
if v == u+1 { |
|||
return ($na + $nd) - ($a + $d) |
|||
} elsif u == v+1 { |
|||
return ($nc + $nb) - ($c + $b) |
|||
} else { |
|||
return ($na + $nb + $nc + $nd) - ($a + $b + $c + $d) |
|||
} |
|||
} |
|||
sub P(\ΔE, \k, \kmax, \kT) { # probability to move from s to s_next |
|||
return exp( -ΔE / T(k, kmax, kT)) |
|||
} |
|||
sub PrintPath(\p) { |
|||
say "Path: "; |
|||
loop (my $i = 0; $i < +p; $i++) { |
|||
if $i > 0 and $i%20 == 0 { say " "; } |
|||
print " ", p[$i] |
|||
} |
|||
say " "; |
|||
} |
|||
sub sa(\kmax, \kT) { |
|||
srand(12345); |
|||
my @PathRecord = my @s = flat 0, (1..99).pick(99), 0; |
|||
say "kT =", kT; |
|||
say "E(s0) : ", Es(@s); # random starter |
|||
my $EminRecord = my $Emin = Es(@s); # E0 |
|||
loop (my $k = 0; $k < kmax; $k++ ) { |
|||
if ($k%(kmax/10)) == 0 { |
|||
sprintf("k:%8u T:%4.1f Es: %8.13f",$k,T($k,kmax,kT),Es(@s)).put |
|||
} |
|||
my $u = 1 + (^99).roll; # city index 1 to 99 |
|||
my $cv = @s[$u] + dirs[(^8).roll]; # city number |
|||
next if $cv ≤ 0 or $cv ≥ 100 ; # bogus city |
|||
next if dist(@s[$u], $cv) > 5 ; # check true neighbor (eg 0 9) |
|||
my $v = @s[$cv]; # city index |
|||
my $ΔE = dE(@s, $u, $v); |
|||
if $ΔE < 0 or P($ΔE,$k,kmax,kT) ≥ 1.rand { #always move if negative |
|||
(@s[$u], @s[$v]) = (@s[$v], @s[$u]); |
|||
$Emin += $ΔE; |
|||
if $Emin < $EminRecord { |
|||
$EminRecord = $Emin; |
|||
@PathRecord = @s |
|||
} |
|||
} |
|||
} |
|||
say "\nE(s_final) : ", $Emin; |
|||
PrintPath @s; |
|||
say "Global optium : ",$EminRecord; |
|||
PrintPath @PathRecord; |
|||
} |
|||
sa(1e6, 1)</lang> |
|||
{{out}} |
|||
<pre>kT =1 |
|||
E(s0) : 492.6876644465769 |
|||
k: 0 T: 1.0 Es: 492.6876644465769 |
|||
k: 100000 T: 0.9 Es: 182.6232539415397 |
|||
k: 200000 T: 0.8 Es: 178.1973980739033 |
|||
k: 300000 T: 0.7 Es: 166.7332678035799 |
|||
k: 400000 T: 0.6 Es: 142.9907760779216 |
|||
k: 500000 T: 0.5 Es: 141.8232565352380 |
|||
k: 600000 T: 0.4 Es: 131.9340245844944 |
|||
k: 700000 T: 0.3 Es: 118.1083199652142 |
|||
k: 800000 T: 0.2 Es: 113.0995529529691 |
|||
k: 900000 T: 0.1 Es: 115.0995529529691 |
|||
E(s_final) : 115.0995529529687 |
|||
Path: |
|||
0 1 10 20 21 11 12 2 3 4 15 14 13 23 22 31 41 32 33 44 |
|||
34 24 25 35 36 37 27 17 8 7 6 5 16 26 45 46 56 58 48 47 |
|||
38 28 18 19 9 29 39 49 59 69 79 89 99 98 97 88 78 68 67 77 |
|||
87 96 86 76 65 54 55 57 66 74 75 84 85 95 94 93 92 91 90 80 |
|||
70 71 81 82 83 73 72 61 51 52 42 43 53 64 63 62 60 50 40 30 |
|||
0 |
|||
Global optium : 113.0995529529687 |
|||
Path: |
|||
0 1 10 20 21 11 12 2 3 4 5 14 13 23 22 31 41 32 33 44 |
|||
34 24 25 35 36 37 27 17 8 7 6 16 15 26 45 46 57 58 48 47 |
|||
38 28 18 19 9 29 39 49 59 69 79 89 99 98 97 88 78 68 67 77 |
|||
87 96 86 76 65 54 55 56 66 74 75 85 95 94 84 93 92 91 90 80 |
|||
70 71 81 82 83 73 72 62 51 52 42 43 53 64 63 61 60 50 40 30 |
|||
0 |
|||
</pre> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
{{trans|zkl}} |
{{trans|zkl}} |