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 )