Evolutionary computation in Perl | ||
---|---|---|
<<< Previous | Next >>> |
This chapter revisits the evolutionary algorithms we have seen so far, and then some, by using an evolutionary algorithm module (which might be in CPAN by the time you read this) called (what else?) Algorithm::Evolutionary. This module has been designed by the author to be flexible, integrated with XML, Perlish and easy to extend. We will also show how this library works with other Perl modules.
So far, there have been many attempts to create evolutionary algorithm modules and programs in Perl; most have concentrated in implementing Genetic Programming, and some have been geared to a particular application, like the GlotBot. The closest thing one can get in CPAN is the AI::Gene modules, which were intended for creating the basic infrastructure for an evolutionary algorithm devoted to fighting spam. The canonical genetic algorithm, implemented using AI::Gene, would be as follows: ( cga-ai-gene.pl):
use AI::Gene::AI::Gene::Simple; (1) package MyGene; our @ISA = qw (AI::Gene::Simple); sub render_gene { my $self = shift; return (join '', @{$self->[0]}); } sub mutate_minor { my $self = shift; my $num = +$_[0] || 1; my $rt = 0; for (1..$num) { my $glen = scalar @{$self->[0]}; my $pos = defined $_[1] ? $_[1] : int rand $glen; next if $pos >= $glen; # pos lies outside of gene my $token = $self->generate_token(); $self->[0][$pos] = $token; $rt++; } return $rt; } (1) package main; use Algorithm::Evolutionary::Wheel; my $generations = shift || 500; #Which might be enough my $popSize = 100; # No need to keep it variable my $targetString = 'yetanother'; my $strLength = length( $targetString ); (2) sub fitness ($;$) { my $ary = shift; my $distance = 0; for ( 0..($strLength -1)) { $distance += abs( ord( $ary->[$_]) - ord( substr( $targetString, $_, 1))); } return $distance; (2) } sub printPopulation { my $pop = shift; for (@$pop) { print $_->render_gene(), " -> $_->[1] \n"; } } (3) sub crossover { my ($chr1, $chr2) = @_; my $length = scalar( @{$chr1->[0]}); my $crossoverPoint = int (rand( $length)); my $range = int( rand( $length - $crossoverPoint )); my @tmpAry = @{$chr1->[0]}; @{$chr1->[0]}[ $crossoverPoint..($crossoverPoint+ $range)] = @{$chr2->[0]}[$crossoverPoint..($crossoverPoint+ $range)]; @{$chr2->[0]}[ $crossoverPoint..($crossoverPoint+ $range)] = @tmpAry[ $crossoverPoint..($crossoverPoint+ $range)]; (3) } my @population; for ( 1..$popSize ) { (4) my $chromosome = MyGene->new(); $chromosome->mutate_insert( $strLength ); $chromosome->[1] = fitness( $chromosome->[0] ); (4) push @population, $chromosome; } printPopulation( \@population); @population = sort { $a->[1] <=> $b->[1] } @population; for ( 1..$generations ) { my @newPop; my @rates; for ( @population ) { push @rates, 1/$_->[1]; } my $popWheel=new Algorithm::Evolutionary::Wheel @rates; for ( my $i = 0; $i < $popSize/2; $i ++ ) { my $chr1 = $population[$popWheel->spin()]; my $chr2 = $population[$popWheel->spin()]; my $clone1 = $chr1->clone(); my $clone2 = $chr2->clone(); (5) $clone1->mutate_minor(1); $clone2->mutate_minor(1); crossover( $clone1, $clone2 ); $clone1->[1] = fitness( $clone1->[0] ); $clone2->[1] = fitness( $clone2->[0] ); push @newPop, $clone1, $clone2; } @population = sort { $a->[1] <=> $b->[1] } @newPop; print "Best so far: ", $population[0]->render_gene(), "\n"; printPopulation( \@population ); last if $population[0]->[1] == 0; } |
![]() | AI::Gene can be a good CPAN starting point for evolutionary computation, but it has some way to go to become a complete evolutionary algorithm solution. |
There are several other published tools you can use to perform genetic algorithms with Perl. Two of them,AI::GA and Algorithm::Genetic are simple and straightforward implementations of a genetic algorithm. An article by Todor Zlatanov, Cultured Perl: Genetic algorithms applied with Perl Create your own Darwinian breeding grounds, describes a system for doing Genetic Programming with Perl, and includes sample code; this article gets the most mentions in the Perl community. A library, MyBeasties, stands out among the rest. It is a very complex and general implementation of an evolutionary algorithm for any kind of genotype, which, besides, has its own language for describing them and its transformations and evaluations. It features many classes for mutation and recombination, but it lacks classes for higher-level operations, and for implementing different kind of algorithms. Its learning curve is somewhat steep, anyhow.
<<< Previous | Home | Next >>> |
The Canonical Genetic Algorithm | Canonical GA with Algorithm::Evolutionary |