I have this loop as part of a larger program (it's open source, and it can be downloaded and run within comma, the configuration is there):
my $promise = start react whenever $channel-one -> @crew {
Algorithm::Evolutionary::LogTimelineSchema::Evolutionary.log: {
my %fitness-of;
Algorithm::Evolutionary::LogTimelineSchema::Frequencies
.log( :@crew );
my @unpacked-pop = generate-by-frequencies( $population-size, @crew );
my $population = evaluate( population => @unpacked-pop,
:%fitness-of,
evaluator => &leading-ones);
Algorithm::Evolutionary::LogTimelineSchema::GenerationsStart
.log( :population-size(@unpacked-pop.elems),
:distinct-elements( %fitness-of.keys.elems) );
my atomicint $count = 0;
while ($count⚛++ < $generations) &&
(best-fitness($population) < $max-fitness) {
LAST {
if best-fitness($population) >= $max-fitness {
Algorithm::Evolutionary::LogTimelineSchema::SolutionFound
.log(
{
id => $*THREAD.id,
best => best-fitness($population),
found => True,
finishing-at => DateTime.now.Str
}
);
say "Solution found" => $evaluations;
Algorithm::Evolutionary::LogTimelineSchema::SolutionFound
.log( :$evaluations );
$channel-one.close;
} else {
say "Emitting after $count generations in thread ",
$*THREAD.id, " Best fitness ",best-fitness($population);
if $count < $generations {
Algorithm::Evolutionary::LogTimelineSchema::Weird
.log( id => $*THREAD.id,
best => best-fitness($population),
:$count,
:population-size(@unpacked-pop.elems),
:distinct-elements( %fitness-of.keys.elems)
);
} else {
Algorithm::Evolutionary::LogTimelineSchema::Events.log(
id => $*THREAD.id,
best => best-fitness($population),
:$count
);
}
$to-mix.send( frequencies-best($population, 8) );
}
};
$population = generation( :$population, :%fitness-of,
evaluator => &leading-ones,
:$population-size
);
$evaluations += $population.elems;
}
Algorithm::Evolutionary::LogTimelineSchema::Generations
.log( :generations($count),
individuals => %fitness-of.keys.elems);
$evaluations;
};
};
Check out the loop conditions:
while ($count⚛++ < $generations) &&
(best-fitness($population) < $max-fitness) {
$count
is a local variable that, besides, is atomic, and exceeding that count or achieving the best fitness seem to be the only way out.
Only it's not. The loop ends on its own accord, without meeting any of the conditions there. I have set out two different log events, "Weird", and "EndRun" (which you can see above), "Weird" is called when the loop ends without reaching either the best fitness or the number of generations; that one is almost always called, as seen in this Comma visualization
With the (sparse) triangles on the top showing when the loop ends when it should, the purple triangles below marking the "weird" endings. The printed log also shows the same thing:
Emitting after 8 generations in thread 10 Best fitness 48
Mixing in 12
Emitting after 5 generations in thread 7 Best fitness 47
Mixing in 12
Emitting after 2 generations in thread 8 Best fitness 48
Mixing in 12
Emitting after 1 generations in thread 10 Best fitness 48
Mixing in 8
It almost never reaches 16 generations, which is the value of $generations. I'm using Raku 2019.11, but this kind of thing happened before too. I'm not sure I've bumped into a bug, or I'm simply triggering some mechanism I don't really know about. Any idea?
Update: It also crashes from time to time...
/home/jmerelo/.rakudobrew/moar-2020.01/install/bin/rakudo /home/jmerelo/Papers/2020/2020-evostar-concurrent-eas/code/concurrent-ea-leading-ones.p6
Use of Nil in numeric context
in block at /home/jmerelo/Papers/2020/2020-evostar-concurrent-eas/code/concurrent-ea-leading-ones.p6 line 68
An operation first awaited:
in sub MAIN at /home/jmerelo/Papers/2020/2020-evostar-concurrent-eas/code/concurrent-ea-leading-ones.p6 line 139
in block <unit> at /home/jmerelo/Papers/2020/2020-evostar-concurrent-eas/code/concurrent-ea-leading-ones.p6 line 21
Died with the exception:
A react block:
in code at /home/jmerelo/Papers/2020/2020-evostar-concurrent-eas/code/concurrent-ea-leading-ones.p6 line 55
Died because of the exception:
Type check failed in binding to parameter '@chromosome1'; expected Positional but got Any (Any)
in sub crossover at /home/jmerelo/.rakudobrew/moar-2020.01/install/share/perl6/site/sources/C405508803395DA88D77FC9B113DB20EFC0C1C4C (Algorithm::Evolutionary::Simple) line 96
in sub produce-offspring at /home/jmerelo/.rakudobrew/moar-2020.01/install/share/perl6/site/sources/C405508803395DA88D77FC9B113DB20EFC0C1C4C (Algorithm::Evolutionary::Simple) line 115
in sub generation at /home/jmerelo/.rakudobrew/moar-2020.01/install/share/perl6/site/sources/C405508803395DA88D77FC9B113DB20EFC0C1C4C (Algorithm::Evolutionary::Simple) line 149
in block at /home/jmerelo/Papers/2020/2020-evostar-concurrent-eas/code/concurrent-ea-leading-ones.p6 line 107
in block at /home/jmerelo/.rakudobrew/moar-2020.01/install/share/perl6/site/sources/0F5CDA46B783643CA4E3D746E2329D0C256CB46B (Log::Timeline) line 95
in method log at /home/jmerelo/.rakudobrew/moar-2020.01/install/share/perl6/site/sources/0F5CDA46B783643CA4E3D746E2329D0C256CB46B (Log::Timeline) line 90
in block at /home/jmerelo/Papers/2020/2020-evostar-concurrent-eas/code/concurrent-ea-leading-ones.p6 line 56
Update 2 Trying to golf it down as requested, I've changed the while
to a for
loop and it works like a charm. So at least that works for me, but still I'd like to know what's the deal with the tunneling while