Algorithm-Evolve
view release on metacpan or search on metacpan
lib/Algorithm/Evolve.pm view on Meta::CPAN
unless $gladitorial_attempts_warn++;
my $remaining = $p->parents_per_gen - @gladitorial_select_indices;
push @gladitorial_replace_indices,
(shuffle @available_indices)[0 .. $remaining-1];
push @gladitorial_select_indices,
(shuffle @available_indices)[0 .. $remaining-1];
last;
}
my $cmp = $p->critter_class->compare( @{$p->critters}[$i1, $i2] );
next if $cmp == 0; ## tie
my ($select, $remove) = $cmp > 0 ? ($i1,$i2) : ($i2,$i1);
@available_indices = grep { $_ != $remove } @available_indices;
push @gladitorial_replace_indices, $remove;
push @gladitorial_select_indices, $select;
$fetched++;
}
return @gladitorial_select_indices;
};
sub Algorithm::Evolve::replacement::gladitorial {
my ($p, $num) = @_;
croak "parents_per_gen must equal children_per_gen with gladitorial selection"
if @gladitorial_replace_indices != $num;
croak "Can't use gladitorial replacement without gladitorial selection"
unless ($p->selection eq 'gladitorial');
return @gladitorial_replace_indices;
};
#######################################
BEGIN {
## creates very basic readonly accessors - very loosely based on an
## idea by Juerd in http://perlmonks.org/index.pl?node_id=222941
my @fields = qw/critters size generations callback critter_class
random_seed is_suspended use_fitness fitnesses
parents_per_gen children_per_gen children_per_parent/;
no strict 'refs';
for my $f (@fields) {
*$f = sub { carp "$f method is readonly" if $#_; $_[0]->{$f} };
}
}
##########################################
##########################################
##########################################
1;
__END__
=head1 NAME
Algorithm::Evolve - An extensible and generic framework for executing
evolutionary algorithms
=head1 SYNOPSIS
#!/usr/bin/perl -w
use Algorithm::Evolve;
use MyCritters; ## Critter class providing appropriate methods
sub callback {
my $p = shift; ## get back the population object
## Output some stats every 10 generations
print $p->avg_fitness, $/ unless $p->generations % 10;
## Stop after 2000 generations
$p->suspend if $p->generations >= 2000;
}
my $p = Algorithm::Evolve->new(
critter_class => MyCritters,
selection => rank,
size => 400,
callback => \&callback,
);
$p->start;
## Print out final population statistics, cleanup, etc..
=cut
=head1 DESCRIPTION
This module is intended to be a useful tool for quick and easy implementation
of evolutionary algorithms. It aims to be flexible, yet simple. For this
reason, it is not a comprehensive implementation of all possible evolutionary
algorithm configurations. The flexibility of Perl allows the evolution of
any type of object conceivable: a simple string or array, a deeper structure
like a hash of arrays, or even something as complex as graph object from
another CPAN module, etc.
It's also worth mentioning that evolutionary algorithms are generally very
CPU-intensive. There are a great deal of calls to C<rand()> and a lot of
associated floating-point math. If you want a lightning-fast framework, then
searching CPAN at all is probably a bad place to start. However, this doesn't
mean that I've ignored efficiency. The fitness function is often the biggest
bottleneck.
=head2 Framework Overview
The configurable parts of an evolutionary algorithm can be split up into two
categories:
=over
=item Dependent on the internal representation of genes to evolve:
These include fitness function, crossover and mutation operators. For example,
evolving string genes requires a different mutation operator than evolving
array genes.
=item Independent of representation:
These include selection and replacement methods, population size, number of
mating events, etc.
=back
In Algorithm::Evolve, the first group of options is implemented by the user
for maximum flexibility. These functions are abstracted to class of evolvable
objects (a B<critter class> in this document). The module itself handles the
representation-independent parts of the algorithm using simple configuration
switches and methods.
=head1 USAGE
If you're of the ilk that prefers to learn things hands-on, you should
probably stop here and look at the contents of the F<examples/> directory
first.
=head2 Designing a class of critter objects (interface specification)
Algorithm::Evolve maintains a population of critter objects to be evolved. You
may evolve any type of objects you want, provided the class supplies the
following methods:
=over
=item C<Class-E<gt>new()>
This method will be called as a class method with no arguments. It must return
a blessed critter object. It is recommended that the returned critter's genes
be randomly initialized.
=item C<Class-E<gt>crossover( $critter1, $critter2 )>
This method will also be called as a class method, with two critter objects as
arguments. It should return a list of two new critter objects based on the
genes of the passed objects.
=item C<$critter-E<gt>mutate()>
This method will be called as an instance method, with no arguments. It should
randomly modify the genes of the critter. Its return value is ignored.
( run in 2.877 seconds using v1.01-cache-2.11-cpan-df04353d9ac )