Algorithm-Evolve
view release on metacpan or search on metacpan
lib/Algorithm/Evolve.pm view on Meta::CPAN
package Algorithm::Evolve;
use strict;
use Carp qw/croak carp/;
use List::Util qw/shuffle/;
our (%SELECTION, %REPLACEMENT);
our $VERSION = '0.03';
our $DEBUG = 0;
my $rand_max = (1 << 31); ## close enough
###########################
sub debug {
print @_, "\n" if $DEBUG;
}
sub new {
my $pkg = shift;
my $p = bless {
generations => 0,
parents_per_gen => 2,
@_
}, $pkg;
$p->{random_seed} ||= int(rand $rand_max);
srand( $p->random_seed );
$p->{selection} ||= $p->{replacement};
$p->{replacement} ||= $p->{selection};
$p->{children_per_gen} ||= $p->{parents_per_gen};
$p->_validate_args;
return $p;
}
sub _validate_args {
my $p = shift;
{
no strict 'refs';
croak "Invalid selection/replacement criteria"
unless *{"Algorithm::Evolve::selection::" . $p->selection}{CODE}
and *{"Algorithm::Evolve::replacement::" . $p->replacement}{CODE};
}
croak "Please specify the size of the population" unless $p->size;
croak "parents_per_gen must be even" if $p->parents_per_gen % 2;
croak "parents_per_gen must divide children_per_gen"
if $p->children_per_gen % $p->parents_per_gen;
croak "parents_per_gen and children_per_gen must be no larger than size"
if $p->children_per_gen > $p->size
or $p->parents_per_gen > $p->size;
$p->{children_per_parent} = $p->children_per_gen / $p->parents_per_gen;
}
############################
sub start {
my $p = shift;
$p->_initialize;
until ($p->is_suspended) {
no strict 'refs';
my @parent_indices
= ("Algorithm::Evolve::selection::" . $p->selection)
->($p, $p->parents_per_gen);
my @children;
while (@parent_indices) {
my @parents = @{$p->critters}[ splice(@parent_indices, 0, 2) ];
push @children, $p->critter_class->crossover(@parents)
for (1 .. $p->children_per_parent);
}
lib/Algorithm/Evolve.pm view on Meta::CPAN
=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.
=item C<$critter-E<gt>fitness()>
This method will also be called as an instance method, with no arguments. It
should return the critter's fitness measure within the problem space, which
should always be a nonnegative number. This method need not be memo-ized, as
it is only called once per critter by Algorithm::Evolve.
This method may be omitted only if using gladitorial selection/replacement
(see below).
=item C<Class-E<gt>compare( $critter1, $critter2 )>
This method is used for L</Co_Evolution|co-evolution> with the gladitorial
selection method. It should return a number less than zero if $critter1 is
"better," 0 if the two are equal, or a number greater than zero if $critter2
is "better."
=back
You may also want to use the C<DESTROY> method as a hook for detecting when
critters are removed from the population.
See the F<examples/> directory for example critter classes. Also, take a look
at L<Algorithm::Evolve::Util> which provides some useful utilities for
implementing a critter class.
=head2 Algorithm::Evolve population interface
=over
=item C<$p = Algorithm::Evolve-E<gt>new( option =E<gt> value, ... )>
Takes a hash of arguments and returns a population object. The relevant options
are:
B<critter_class>, the name of the critter class whose objects are to be
evolved. This class should already be C<use>'d or C<require>'d by your code.
B<selection> and B<replacement>, the type of selection and replacement methods
to use. Available methods for both currently include:
=over
=item *
( run in 0.644 second using v1.01-cache-2.11-cpan-39bf76dae61 )