Genesis

Concurrent evolutionary algorithms with Perl 6

JJ Merelo, @jjmerelo

EAs are optimization methods

Optimize this

sub road-royale ( @χ ) {
    @χ.rotor(4).map( {so @_.all + so @_.none}).sum;
}
	    

Evolutionary algorithms evolve encoded solutions in populations

    my @population = ( Bool.pick() xx $length ) xx $population-size;

... through evaluation...

my $evaluated = @population.unique.map( { @$_ => road-royale( @$_ ) } ).Mix;

... to select the best

          my @reproductive-pool = $evaluated.roll( $population-size );

... and interchange bits ...

    my @pairs = @x Z @y;
    my $xover1point = @x.keys.pick;
    my $xover2point = ($xover1point^..@x.elems).pick;
    my @crossed =  gather for @pairs.kv -> $index, @value {
        take ( ($xover1point <= $index <= $xover2point) ?? @value.reverse !!
            @value );
    }
    return ([Z] @crossed).Slip;
@population.append:
  @reproductive-pool.pick( $population-size / 5 ).rotor(2)
    .map( { xover( @$_[0], @$_[1] ) } );

... which mutate ...

sub mutate ( @x is copy ) {
    @x[ (^@x.elems).pick ] ?^= True;
    @x;
}
@population.append:
    @reproductive-pool.pick( $population-size*3/5).map( {mutate(@$_)} );

Repeat until solution is found

my $best-so-far = $evaluated.values.max;
@best = $evaluated.grep( *.value == $best-so-far );
if any( $evaluated.values ) == $length/4 {
    last;
}  

We ♥ just the way you are

@population.append: @reproductive-pool.pick( $population-size / 5 );

First iteration

EA demonstration

Evolving...

EA demonstration with elitism

But we have concurrency!

Add Perl6 for instant data-paralellism

my @unique-population = @population.unique;
    my @evaluations = @unique-population.race.map( { $^p => $evaluator( $^p ) } );
    my MixHash $pop-bag;
    for @evaluations -> $pair {
        $pop-bag{$pair.key.item} = $pair.value;
    }
    return $pop-bag.Mix;
}

2x increment in speed!

Task paralellism: Communicating sequential processes

Stateless process writes to/reads from channels

Stateless⇒ 1 to 1 mapping input/output

For all functions.

We need a reactive/functional EA

Let's de-state-ify evolutionary algorithms

Using channels!

Channelize

 # Read from $channel-one and repeat...
$population = generation( population => $population,
    fitness-of => %fitness-of,
    evaluator => &royal-road,
    population-size => $population-size);
$to-mix.send( frequencies-best($population, 8) );

Threading threads

$to-mix.send( @pair.pick ); # To avoid getting it hanged up
    my @new-population =  crossover-frequencies( @pair[0], @pair[1] );
    $channel-one.send( @new-population);
	    

Does it scale?

scaling chart

Concluding

Science

Open!

New algorithms!