view release on metacpan or search on metacpan
lib/Algorithm/Evolutionary/Experiment.pm view on Meta::CPAN
sub new ($$$$;$) {
my $class = shift;
my $self = { _pop => [] };
if ( index ( ref $_[0], 'Algorithm::Evolutionary') == -1 ) {
#If the first arg is not an algorithm, create one
my $popSize = shift || carp "Pop size = 0, can't create\n";
my $indiType = shift || carp "Empty individual class, can't create\n";
my $indiSize = shift || carp "Empty individual size, no reasonable default, can't create\n";
for ( my $i = 0; $i < $popSize; $i ++ ) {
my $indi = Algorithm::Evolutionary::Individual::Base::new( $indiType,
{ length => $indiSize } );
$indi->randomize();
push @{$self->{_pop}}, $indi;
}
};
@_ || croak "Can't find an algorithm";
push @{$self->{_algo}}, @_;
bless $self, $class;
return $self
}
lib/Algorithm/Evolutionary/Fitness/ECC.pm view on Meta::CPAN
=head1 SYNOPSIS
my $number_of_codewords = 10;
my $min_distance = 1;
my $p_peaks = Algorithm::Evolutionary::Fitness::ECC->new( $number_of_codewords, $min_distance );
=head1 DESCRIPTION
Extracted from article "Effects of scale-free and small-world topologies on binary coded self-adaptive CEA", by Giacobini et al [Ga]. Quoting:
" The ECC problem was presented in
[MW]. We will consider a three-tuple (n, M, d), where n is the length of each codeword
(number of bits), M is the number of codewords, and d is the minimum Hamming
distance between any pair of codewords. Our objective will be to find a code which
has a value for d as large as possible (reflecting greater tolerance to noise and errors),
given previously fixed values for n and M . The problem we have studied is a simplified
version of that in [MW]. In our case we search half of the codewords (M/2) that will
compose the code, and the other half is made up by the complement of the codewords
computed by the algorithm"
[Ga] Mario Giacobini, Mike Preuss, Marco Tomassini: Effects of Scale-Free and Small-World Topologies on Binary Coded Self-adaptive CEA. EvoCOP 2006: 86-98.
lib/Algorithm/Evolutionary/Fitness/ECC.pm view on Meta::CPAN
=cut
sub ecc {
my $self = shift;
my $string = shift || croak "Can't work with a null string";
my $cache = $self->{'_cache'};
if ( $cache->{$string} ) {
return $cache->{$string};
}
my $length = length($string)/$self->{'number_of_codewords'};
my @codewords = ( $string =~ /.{$length}/gs );
my $distance;
for ( my $i = 0; $i <= $#codewords; $i ++ ) {
for ( my $j = $i+1; $j <= $#codewords; $j ++ ) {
my $this_distance = hamming( $codewords[$i], $codewords[$j] );
$distance += 1/(1+$this_distance*$this_distance);
}
}
$cache->{$string} = 1/$distance;
return $cache->{$string};
lib/Algorithm/Evolutionary/Fitness/Knapsack.pm view on Meta::CPAN
my $cache = $self->{'_cache'};
if ( $cache->{$string} ) {
return $cache->{$string};
}
my $profit=0.0;
my $weight=0.0;
my @profits = @{$self->{'profits'}};
my @weights = @{$self->{'weights'}};
for (my $i=0 ; $i < length($string); $i++) { #Compute weight
my $this_bit=substr ($string, $i, 1);
if ($this_bit == 1) {
$profit += $profits[$i];
$weight += $weights[$i];
}
}
if ($weight > $self->{'capacity'}) { # Apply penalty
my $penalty = $self->{'rho'} * ($weight - $self->{'capacity'});
lib/Algorithm/Evolutionary/Fitness/MMDP.pm view on Meta::CPAN
=cut
sub mmdp {
my $self = shift;
my $string = shift;
my $cache = $self->{'_cache'};
if ( $cache->{$string} ) {
return $cache->{$string};
}
my $fitness = 0;
for ( my $i = 0; $i < length($string); $i+= BLOCK_SIZE ) {
my $block = substr( $string, $i, BLOCK_SIZE );
my $ones = grep ( /1/, split(//,$block));
$fitness += $unitation[$ones];
}
$cache->{$string} = $fitness;
return $fitness;
}
=head1 Copyright
lib/Algorithm/Evolutionary/Fitness/Royal_Road.pm view on Meta::CPAN
my $self = shift;
my $string = shift;
my $cache = $self->{'_cache'};
if ( $cache->{$string} ) {
return $cache->{$string};
}
my $fitness = 0;
my $block_size = $self->{'_block_size'};
for ( my $i = 0; $i < length( $string ) / $block_size; $i++ ) {
my $block = 0;
if ( length( substr( $string, $i*$block_size, $block_size )) == $block_size ) {
$block=1;
for ( my $j = 0; $j < $block_size; $j++ ) {
$block &= substr( $string, $i*$block_size+$j, 1 );
}
}
( $fitness += $block_size ) if $block;
}
$cache->{$string} = $fitness;
return $cache->{$string};
lib/Algorithm/Evolutionary/Fitness/Trap.pm view on Meta::CPAN
sub trap {
my $self = shift;
my $string = shift;
my $cache = $self->{'_cache'};
if ( $cache->{$string} ) {
return $cache->{$string};
}
my $l = $self->{'l'};
my $z = $self->{'z'};
my $total = 0;
for ( my $i = 0; $i < length( $string); $i+= $l ) {
my $substr = substr( $string, $i, $l );
my $key = $substr;
if ( !$cache->{$substr} ) {
my $num_ones = 0;
while ( $substr ) {
$num_ones += chop( $substr );
}
if ( $num_ones <= $z ) {
$cache->{$key} = $self->{'a'}*($z-$num_ones)/$z;
} else {
lib/Algorithm/Evolutionary/Individual/BitString.pm view on Meta::CPAN
=head1 NAME
Algorithm::Evolutionary::Individual::BitString - Classic bitstring individual for evolutionary computation; usually called I<chromosome>
=head1 SYNOPSIS
use Algorithm::Evolutionary::Individual::BitString;
my $indi = new Algorithm::Evolutionary::Individual::BitString 10 ; # Build random bitstring with length 10
# Each element in the range 0 .. 1
my $indi3 = new Algorithm::Evolutionary::Individual::BitString;
$indi3->set( { length => 20 } ); #Sets values, but does not build the string
$indi3->randomize(); #Creates a random bitstring with length as above
print $indi3->Atom( 7 ); #Returns the value of the 7th character
$indi3->Atom( 3 ) = 1; #Sets the value
$indi3->addAtom( 1 ); #Adds a new character to the bitstring at the end
my $size = $indi3->size(); #Common interface to all individuals, should return 21
my $indi4 = Algorithm::Evolutionary::Individual::BitString->fromString( '10110101'); #Creates an individual from that string
my $indi5 = $indi4->clone(); #Creates a copy of the individual
lib/Algorithm/Evolutionary/Individual/BitString.pm view on Meta::CPAN
use base 'Algorithm::Evolutionary::Individual::String';
use constant MY_OPERATORS => ( Algorithm::Evolutionary::Individual::String::MY_OPERATORS,
qw(Algorithm::Evolutionary::Op::BitFlip Algorithm::Evolutionary::Op::Mutation ));
use Algorithm::Evolutionary::Utils qw(decode_string);
=head1 METHODS
=head2 new( $length )
Creates a new random bitstring individual, with fixed initial length, and
uniform distribution of bits. Options as in L<Algorithm::Evolutionary::Individual::String>
=cut
sub new {
my $class = shift;
my $chars = [ '0', '1' ];
my $self =
Algorithm::Evolutionary::Individual::String::new( $class, $chars, @_ );
return $self;
lib/Algorithm/Evolutionary/Individual/Bit_Vector.pm view on Meta::CPAN
=head1 NAME
Algorithm::Evolutionary::Individual::Bit_Vector - Classic bitstring individual for evolutionary computation;
usually called chromosome, and using a different implementation from Algorithm::Evolutionary::Individual::BitString
=head1 SYNOPSIS
use Algorithm::Evolutionary::Individual::BitVector;
my $indi = new Algorithm::Evolutionary::Individual::Bit_Vector 10 ; # Build random bitstring with length 10
# Each element in the range 0 .. 1
my $indi3 = new Algorithm::Evolutionary::Individual::Bit_Vector;
$indi3->set( { length => 20 } ); #Sets values, but does not build the string
$indi3->randomize(); #Creates a random bitstring with length as above
print $indi3->Atom( 7 ); #Returns the value of the 7th character
$indi3->Atom( 3 ) = 1; #Sets the value
$indi3->addAtom( 1 ); #Adds a new character to the bitstring at the end
my $indi4 = Algorithm::Evolutionary::Individual::Bit_Vector->fromString( '10110101'); #Creates an individual from that string
my $indi5 = $indi4->clone(); #Creates a copy of the individual
lib/Algorithm/Evolutionary/Individual/Bit_Vector.pm view on Meta::CPAN
use base 'Algorithm::Evolutionary::Individual::Base';
use constant MY_OPERATORS => ( qw(Algorithm::Evolutionary::Op::BitFlip Algorithm::Evolutionary::Op::Mutation ));
=head1 METHODS
=head2 new( $arg )
Creates a new bitstring individual. C<$arg> can be either { length =>
$length} or { string => [binary string] }. With no argument, a
length of 16 is given by default.
=cut
sub new {
my $class = shift;
my $self = Algorithm::Evolutionary::Individual::Base::new( $class );
my $arg = shift || { length => 16};
if ( $arg =~ /^\d+$/ ) { #It's a number
$self->{'_bit_vector'} = _create_bit_vector( $arg );
} elsif ( $arg->{'length'} ) {
$self->{'_bit_vector'} = _create_bit_vector( $arg->{'length'} );
} elsif ( $arg->{'string'} ) {
$self->{'_bit_vector'} =
Bit::Vector->new_Bin( length($arg->{'string'}), $arg->{'string'} );
}
croak "Incorrect creation options" if !$self->{'_bit_vector'};
return $self;
}
sub _create_bit_vector {
my $length = shift || croak "No length!";
my $rander = new String::Random;
my $hex_string = $rander->randregex("[0-9A-F]{".int($length/4)."}");
return Bit::Vector->new_Hex( $length, $hex_string );
}
sub TIEARRAY {
my $class = shift;
my $self = { _bit_vector => Bit::Vector->new_Bin(scalar( @_), join("",@_)) };
bless $self, $class;
return $self;
}
=head2 Atom
lib/Algorithm/Evolutionary/Individual/Bit_Vector.pm view on Meta::CPAN
sub UNSHIFT {
my $self = shift;
my $new_vector = Bit::Vector->new_Bin(scalar(@_), join("",@_));
$self->{'_bit_vector'} = Bit::Vector->Concat_List( $new_vector, $self->{'_bit_vector'}) ;
}
sub POP {
my $self = shift;
my $bit_vector = $self->{'_bit_vector'};
my $length = $bit_vector->Size();
my $pop = $bit_vector->lsb();
$self->{'_bit_vector'}->Delete(0,1);
$self->{'_bit_vector'}->Resize($length-1);
return $pop;
}
sub SHIFT {
my $self = shift;
my $length = $self->{'_bit_vector'}->Size();
my $bit = $self->{'_bit_vector'}->shift_left('0');
$self->{'_bit_vector'}->Reverse( $self->{'_bit_vector'});
$self->{'_bit_vector'}->Resize($length-1);
$self->{'_bit_vector'}->Reverse( $self->{'_bit_vector'});
return $bit;
}
sub SPLICE {
my $self = shift;
my $offset = shift;
my $bits = shift;
my $new_vector;
lib/Algorithm/Evolutionary/Individual/Bit_Vector.pm view on Meta::CPAN
} else {
$self->{'_bit_vector'}->Interval_Substitute( Bit::Vector->new(0), $size-$offset-$bits, $bits,
0, 0 );
}
return split(//,$slice->to_Bin());
}
sub FETCHSIZE {
my $self = shift;
return length( $self->{'_bit_vector'}->Size() );
}
=head2 Copyright
This file is released under the GPL. See the LICENSE file included in this distribution,
or go to http://www.fsf.org/licenses/gpl.txt
CVS Info: $Date: 2010/12/19 21:39:12 $
$Header: /media/Backup/Repos/opeal/opeal/Algorithm-Evolutionary/lib/Algorithm/Evolutionary/Individual/Bit_Vector.pm,v 3.1 2010/12/19 21:39:12 jmerelo Exp $
lib/Algorithm/Evolutionary/Individual/String.pm view on Meta::CPAN
=head1 NAME
Algorithm::Evolutionary::Individual::String - A character string to be evolved. Useful mainly in word games
=head1 SYNOPSIS
use Algorithm::Evolutionary::Individual::String;
my $indi = new Algorithm::Evolutionary::Individual::String ['a'..'z'], 10;
# Build random bitstring with length 10
my $indi3 = new Algorithm::Evolutionary::Individual::String;
$indi3->set( { length => 20,
chars => ['A'..'Z'] } ); #Sets values, but does not build the string
$indi3->randomize(); #Creates a random bitstring with length as above
print $indi3->Atom( 7 ); #Returns the value of the 7th character
$indi3->Atom( 3, 'Q' ); #Sets the value
$indi3->addAtom( 'K' ); #Adds a new character to the bitstring at the end
my $indi4 = Algorithm::Evolutionary::Individual::String->fromString( 'esto es un string'); #Creates an individual from that string
my $indi5 = $indi4->clone(); #Creates a copy of the individual
my @array = qw( a x q W z ñ); #Tie a String individual
lib/Algorithm/Evolutionary/Individual/String.pm view on Meta::CPAN
use constant MY_OPERATORS => qw(Algorithm::Evolutionary::Op::Crossover
Algorithm::Evolutionary::Op::QuadXOver
Algorithm::Evolutionary::Op::StringRand
Algorithm::Evolutionary::Op::Permutation
Algorithm::Evolutionary::Op::IncMutation
Algorithm::Evolutionary::Op::ChangeLengthMutation );
=head2 new
Creates a new random string, with fixed initial length, and uniform
distribution of characters along the character class that is
defined. However, this character class is just used to generate new
individuals and in mutation operators, and the validity is not
enforced unless the client class does it
=cut
sub new {
my $class = shift;
my $self = Algorithm::Evolutionary::Individual::Base::new( $class );
$self->{'_chars'} = shift || ['a'..'z'];
$self->{'_length'} = shift || 10;
$self->randomize();
return $self;
}
sub TIEARRAY {
my $class = shift;
my $self = { _str => join("",@_),
_length => scalar( @_ ),
_fitness => undef };
bless $self, $class;
return $self;
}
=head2 randomize
Assigns random values to the elements
=cut
sub randomize {
my $self = shift;
$self->{'_str'} = ''; # Reset string
for ( my $i = 0; $i < $self->{'_length'}; $i ++ ) {
$self->{'_str'} .= $self->{'_chars'}[ rand( @{$self->{'_chars'}} ) ];
}
}
=head2 addAtom
Adds an atom at the end
=cut
lib/Algorithm/Evolutionary/Individual/String.pm view on Meta::CPAN
=cut
sub fromString {
my $class = shift;
my $str = shift;
my $self = Algorithm::Evolutionary::Individual::Base::new( $class );
$self->{_str} = $str;
my %chars;
map ( $chars{$_} = 1, split(//,$str) );
my @chars = keys %chars;
$self->{_length} = length( $str );
$self->{'_chars'} = \@chars;
return $self;
}
=head2 from_string
Similar to a copy ctor; creates a bitstring individual from a string.
=cut
sub from_string {
my $class = shift;
my $chars = shift;
my $str = shift;
my $self = Algorithm::Evolutionary::Individual::Base::new( $class );
$self->{'_chars'} = $chars;
$self->{'_str'} = $str;
$self->{'_length'} = length( $str );
return $self;
}
=head2 clone
Similar to a copy ctor: creates a new individual from another one
=cut
sub clone {
my $indi = shift || croak "Indi to clone missing ";
my $self = { '_fitness' => undef };
bless $self, ref $indi;
for ( qw( _chars _str _length) ) {
$self->{ $_ } = $indi->{$_};
}
return $self;
}
=head2 asString
Returns the individual as a string with the fitness as a suffix.
lib/Algorithm/Evolutionary/Individual/String.pm view on Meta::CPAN
$self->{_str}.= join("", @_ );
}
sub UNSHIFT {
my $self = shift;
$self->{_str} = join("", @_ ).$self->{_str} ;
}
sub POP {
my $self = shift;
my $pop = substr( $self->{_str}, length( $self->{_str} )-1, 1 );
substr( $self->{_str}, length( $self->{_str} ) -1, 1 ) = '';
return $pop;
}
sub SHIFT {
my $self = shift;
my $shift = substr( $self->{_str}, 0, 1 );
substr( $self->{_str}, 0, 1 ) = '';
return $shift;
}
sub SPLICE {
my $self = shift;
my $offset = shift;
my $length = shift || length( $self->{'_str'} - $offset );
my $sub_string = substr( $self->{_str}, $offset, $length );
# if ( @_ ) {
substr( $self->{_str}, $offset, $length ) = join("", @_ );
# }
return split(//,$sub_string);
}
sub FETCHSIZE {
my $self = shift;
return length( $self->{_str} );
}
=head2 size()
Returns length of the string that stores the info; overloads abstract base method.
=cut
sub size {
my $self = shift;
return length($self->{_str}); #Solves ambiguity
}
=head2 as_string()
Returns the string used as internal representation
=cut
sub as_string {
my $self = shift;
lib/Algorithm/Evolutionary/Individual/Vector.pm view on Meta::CPAN
use strict; #-*-cperl-*-
use warnings;
=head1 NAME
Algorithm::Evolutionary::Individual::Vector - Array as an individual for evolutionary computation
=head1 SYNOPSIS
use Algorithm::Evolutionary::Individual::Vector;
my $indi = new Algorithm::Evolutionary::Individual::Vector 10 ; # Build random vector individual with length 10
# Each element in the range 0 .. 1
my $indi2 = new Algorithm::Evolutionary::Individual::Vector 20, -5, 5; #Same, with range between -5 and 5
#Creating a vector step by step. In Perl, there's always more than one way of doing it
my $indi3 = new Algorithm::Evolutionary::Individual::Vector;
$indi3->set( {length => 20,
rangestart => -5,
rangeend => 5 } ); #Sets values, but does not build the array
$indi3->randomize(); #Creates an array using above parameters
print $indi3->Atom( 7 ); #Returns the value of the 7th character
$indi3->Atom( 3 ) = '2.35'; #Sets the value
$indi3->addAtom( 7.5 ); #Adds a new component to the array at the end
lib/Algorithm/Evolutionary/Individual/Vector.pm view on Meta::CPAN
use Carp;
use Exporter;
our ($VERSION) = ( '$Revision: 3.2 $ ' =~ / (\d+\.\d+)/ );
use base 'Algorithm::Evolutionary::Individual::Base';
=head1 METHODS
=head2 new( [$length = 10] [, $start_of_range = 0] [, $end_of_range = 1] )
Creates a new random array individual, with fixed initial length, and uniform distribution
of values within a range
=cut
sub new {
my $class = shift;
my $self;
$self->{_length} = shift || 10;
$self->{_array} = ();
$self->{_rangestart} = shift || 0;
$self->{_rangeend } = shift || 1;
$self->{_fitness} = undef;
bless $self, $class;
$self->randomize();
return $self;
}
=head2 size()
Returns vector size (dimension)
=cut
sub size {
my $self = shift;
return $self->{'_length'};
}
sub TIEARRAY {
my $class = shift;
my $self = { _array => \@_,
_length => scalar( @_ ),
_fitness => undef };
bless $self, $class;
return $self;
}
=head2 set( $ref_to_hash )
Sets values of an individual; takes a hash as input. The array is
initialized to a null array, and the start and end range are
initialized by default to 0 and 1
lib/Algorithm/Evolutionary/Individual/Vector.pm view on Meta::CPAN
=head2 randomize()
Assigns random values to the elements
=cut
sub randomize {
my $self = shift;
my $range = $self->{_rangeend} - $self->{_rangestart};
for ( my $i = 0; $i < $self->{_length}; $i++ ) {
push @{$self->{_array}}, rand( $range ) + $self->{_rangestart};
}
}
=head2 Atom
Gets or sets the value of an atom
=cut
lib/Algorithm/Evolutionary/Individual/Vector.pm view on Meta::CPAN
=head2 addAtom
Adds an atom at the end
=cut
sub addAtom{
my $self = shift;
my $atom = shift || croak "No atom to add\n";
push( @{$self->{_array}}, $atom );
$self->{_length}++;
}
sub PUSH {
my $self = shift;
push( @{$self->{_array}}, @_ );
$self->{_length}++;
}
sub UNSHIFT {
my $self = shift;
unshift( @{$self->{_array}}, @_ );
$self->{_length}++;
}
sub POP {
my $self = shift;
return pop ( @{$self->{_array}} );
$self->{_length}--;
}
sub SHIFT {
my $self = shift;
return shift @{$self->{_array}} ;
$self->{_length}--;
}
sub SPLICE {
my $self = shift;
splice( @{$self->{_array}}, shift, shift, @_ );
}
sub FETCHSIZE {
my $self = shift;
return @{$self->{_array}} -1;
}
=head2 length()
Returns the number of atoms in the individual
=cut
sub length {
my $self = shift;
return scalar @{$self->{_array}};
}
=head2 fromString( $string )
Similar to a copy ctor; creates a vector individual from a string composed of
stuff separated by a separator
=cut
lib/Algorithm/Evolutionary/Individual/Vector.pm view on Meta::CPAN
=head2 clone()
Similar to a copy ctor: creates a new individual from another one
=cut
sub clone {
my $indi = shift || croak "Indi to clone missing ";
my $self = { _fitness => undef,
_length => $indi->{_length} };
$self->{_array} = ();
push(@{$self->{_array}}, @{$indi->{_array}});
bless $self, ref $indi;
die "Something is wrong " if scalar( @{$self->{_array}} ) > scalar( @{$indi->{_array}} );
return $self;
}
=head2 asString()
lib/Algorithm/Evolutionary/Op/Animated_GIF_Output.pm view on Meta::CPAN
use Carp;
our $VERSION = sprintf "%d.%03d", q$Revision: 1.5 $ =~ /(\d+)\.(\d+)/g;
use base 'Algorithm::Evolutionary::Op::Base';
use GD::Image;
sub new {
my $class = shift;
my $hash = shift || croak "No default values for length ";
my $self = Algorithm::Evolutionary::Op::Base::new( __PACKAGE__, 1, $hash );
$hash->{'pixels_per_bit'} = $hash->{'pixels_per_bit'} || 1;
$self->{'_image'} = GD::Image->new($hash->{'length'}*$hash->{'pixels_per_bit'},
$hash->{'number_of_strings'}*$hash->{'pixels_per_bit'});
$self->{'_length'} = $hash->{'length'};
$self->{'_pixels_per_bit'} = $hash->{'pixels_per_bit'};
$self->{'_white'} = $self->{'_image'}->colorAllocate(0,0,0); #background color
$self->{'_black'} = $self->{'_image'}->colorAllocate(255,255,255);
$self->{'_gifdata'} = $self->{'_image'}->gifanimbegin;
$self->{'_gifdata'} .= $self->{'_image'}->gifanimadd; # first frame
return $self;
}
sub apply {
my $self = shift;
my $population_hashref=shift;
my $frame = GD::Image->new($self->{'_image'}->getBounds);
my $ppb = $self->{'_pixels_per_bit'};
my $l=0;
for my $i (@$population_hashref) {
my $bit_string = $i->{'_str'};
for my $c ( 0..($self->{'_length'}-1) ) {
my $bit = substr( $bit_string, $c, 1 );
if ( $bit ) {
for my $p ( 1..$ppb ) {
for my $q (1..$ppb ) {
$frame->setPixel($l*$ppb+$q, $c*$ppb+$p,
$self->{'_black'})
}
}
}
}
lib/Algorithm/Evolutionary/Op/Animated_GIF_Output.pm view on Meta::CPAN
=head1 NAME
Algorithm::Evolutionary::Op::Animated_GIF_Output - Creates an animated GIF, a frame per generation. Useful for binary strings.
=head1 SYNOPSIS
my $pp = new Algorithm::Evolutionary::Op::Animated_GIF_Output;
my @pop;
my $length = 8;
my $number_of_strings = 10;
for ( 1..$number_of_strings ) {
my $indi= new Algorithm::Evolutionary::Individual::String [0,1], $length;
push @pop, $indi;
}
$pp->apply( \@pop );
my $options = { pixels_per_bit => 2,
length => $length,
number_of_strings => $number_of_strings };
$pp = new Algorithm::Evolutionary::Op::Animated_GIF_Output $options
$pp->apply( \@pop );
$pp->terminate();
my $output_gif = $pp->output(); # Prints final results
=head1 DESCRIPTION
Saves each generation as a frame in an animated GIF. Every individual
gets a line of the number of pixels specified, and bits set to "1" are
represented via black pixels or fat pixels. By default, a bit takes a
single pixel.
=head1 INTERFACE
=head2 new( [$hash_ref] )
C<$hash_ref> is a hashref with 3 options: C<pixels_per_bit>, which
defaults to 1, and C<length> and C<number_of_strings> which have no
default and need to be set in advance to set up the GIF before any
population individual is seen.
=head2 apply( $population_hashref )
Applies the single-member printing function to every population member
=head2 terminate()
Finish the setup of the animated GIF.
lib/Algorithm/Evolutionary/Op/CX.pm view on Meta::CPAN
my $p1 = shift || croak "No victim here!"; #first parent
my $p2 = shift || croak "No victim here!"; #second parent
my $child=$p1->clone(); #Child
my $i; #Iterator
my $j; #Iterator
my $changed;
#Check parents type and size
croak "Incorrect type ".(ref $p1) if !$self->check($p1);
croak "Incorrect type ".(ref $p2) if !$self->check($p2);
croak "Algorithm::Evolutionary::Op::CX Error: Parents don't have the same size " if ($p1->length() != $p2->length() );
my $leng=$p1->length(); #Chrom length
my $no='x';#-( $leng );#Uninitialized gene mark
#Init child
for ($i=0;$i < $leng; $i++)
{ $child->Atom($i, $no);}
my %visto;
map( $visto{$_}++,@{$p1->{_array}} );
#Build child
# print "CX \$leng = $leng\n";
$changed=$i=0;
lib/Algorithm/Evolutionary/Op/ChangeLengthMutation.pm view on Meta::CPAN
use strict;
use warnings;
=head1 NAME
Algorithm::Evolutionary::Op::ChangeLengthMutation - Increases/decreases by one atom the length of the string
=head1 SYNOPSIS
my $xmlStr2=<<EOC;
<op name='ChangeLengthMutation' type='unary' rate='0.5' />
EOC
my $ref2 = XMLin($xmlStr2);
my $op2 = Algorithm::Evolutionary::Op::Base->fromXML( $ref2 );
print $op2->asXML(), "\n*Arity ", $op->arity(), "\n";
my $op = new Algorithm::Evolutionary::Op::ChangeLengthMutation 1, 0.5, 0.5; #Create from scratch
=head1 Base Class
L<Algorithm::Evolutionary::Op::Base|Algorithm::Evolutionary::Op::Base>
=head1 DESCRIPTION
Increases or decreases the length of a string, by adding a random element, or
eliminating it.
=head1 METHODS
=cut
package Algorithm::Evolutionary::Op::ChangeLengthMutation;
our ($VERSION) = ( '$Revision: 3.1 $ ' =~ /(\d+\.\d+)/ );
lib/Algorithm/Evolutionary/Op/ChangeLengthMutation.pm view on Meta::CPAN
croak "Incorrect type ".(ref $victim) if ! $self->check( $victim );
#Select increment or decrement
my $total = $self->{_probplus} + $self->{_probminus};
my $rnd = rand( $total );
if ( $rnd < $self->{_probplus} ) { #Incrementar
my $idx = rand( @{$victim->{_chars}} );
my $char = $victim->{_chars}[$idx];
$victim->addAtom( $char );
} else {
my $idx = rand( length($victim->{_str}) );
substr( $victim->{_str}, $idx, 1 ) ='';
}
$victim->Fitness(undef);
return $victim;
}
=head1 Copyright
This file is released under the GPL. See the LICENSE file included in this distribution,
or go to http://www.fsf.org/licenses/gpl.txt
lib/Algorithm/Evolutionary/Op/Creator.pm view on Meta::CPAN
=head1 SYNOPSIS
my $op = new Algorithm::Evolutionary::Op::Creator; #Creates empty op, with rate
my $xmlStr=<<EOC;
<op name='Creator' type='nullary'>
<param name='number' value='20' />
<param name='class' value='BitString' />
<param name='options'>
<param name='length' value='320 />
</param>
</op>
EOC
my $ref = XMLin($xmlStr); #This step is not really needed; only if it's going to be manipulated by another object
my $op = Algorithm::Evolutionary::Op::Base->fromXML( $ref ); #Takes a hash of parsed XML and turns it into an operator
print $op->asXML(); #print its back in XML shape
my $op2 = new Algorithm::Evolutionary::Op::Creator( 20, 'String', { chars => [a..j], length => '10' });
my @pop;
$op2->apply( \@pop ); #Generates population
=head1 DESCRIPTION
Base class for operators applied to Individuals and Populations and all the rest
=head1 METHODS
lib/Algorithm/Evolutionary/Op/Crossover.pm view on Meta::CPAN
Changes the first parent, and returns it. If you want to change both
parents at the same time, check L<QuadXOver|Algorithm::Evolutionary::Op::QuadXOver>
=cut
sub apply ($$$){
my $self = shift;
my $arg = shift || croak "No victim here!";
my $victim = clone( $arg );
my $victim2 = shift || croak "No victim here!";
my $minlen = ( length( $victim->{_str} ) > length( $victim2->{_str} ) )?
length( $victim2->{_str} ): length( $victim->{_str} );
my $pt1 = int( rand( $minlen ) );
my $range = 1 + int( rand( $minlen - $pt1 ) );
# print "Puntos: $pt1, $range \n";
croak "No number of points to cross defined" if !defined $self->{_numPoints};
if ( $self->{_numPoints} > 1 ) {
$range = int ( rand( length( $victim->{_str} ) - $pt1 ) );
}
substr( $victim->{_str}, $pt1, $range ) = substr( $victim2->{_str}, $pt1, $range );
$victim->{'_fitness'} = undef;
return $victim;
}
=head1 SEE ALSO
=over 4
lib/Algorithm/Evolutionary/Op/EDA_step.pm view on Meta::CPAN
=head2 reset( $population )
Start all over again by resetting the population
=cut
sub reset {
my $self = shift;
my $population = shift;
my $length = $population->[0]->size;
@$population = ();
my @alphabet = @{$self->{'_alphabet'}};
for ( my $p= 0; $p < $self->{'_population_size'}; $p++ ) {
my $string = '';
for ( my $i = 0; $i < $length; $i++ ) {
$string .= $alphabet[rand( @alphabet )];
}
my $new_one = Algorithm::Evolutionary::Individual::String->fromString( $string );
push @$population, $new_one;
}
}
=head2 apply( $population )
Applies the algorithm to the population, which should have
lib/Algorithm/Evolutionary/Op/EDA_step.pm view on Meta::CPAN
}
my @ranked_pop = sort { $b->{_fitness} <=> $a->{_fitness}; } @$pop;
#Eliminate
my $pringaos = @$pop * $self->{_replacementRate} ;
splice( @ranked_pop, -$pringaos );
#Check distribution of remaining pop
my $how_many = @ranked_pop;
my @occurrences;
my $length = $pop->[0]->size;
for my $p ( @ranked_pop ) {
for ( my $i = 0; $i < $length; $i++ ) {
if ( ! defined $occurrences[$i] ) {
$occurrences[$i] = {};
}
my $this_value = $p->Atom($i);
$occurrences[$i]->{$this_value}++;
}
}
my @wheel;
for ( my $i = 0; $i < $length; $i++ ) {
for my $k ( @{$self->{'_alphabet'}} ) {
if ( $occurrences[$i]->{$k} ) {
$occurrences[$i]->{$k} /= $how_many;
} else {
$occurrences[$i]->{$k} = 0.05; #Minimum to avoid stagnation
}
}
$wheel[$i] = new Algorithm::Evolutionary::Hash_Wheel $occurrences[$i];
}
#Generate new population
for ( my $p= 0; $p < $self->{'_population_size'} - $pringaos; $p++ ) {
my $string = '';
for ( my $i = 0; $i < $length; $i++ ) {
$string .= $wheel[$i]->spin;
}
my $new_one = Algorithm::Evolutionary::Individual::String->fromString( $string );
push @ranked_pop, $new_one;
}
@$pop = @ranked_pop; # Population is sorted
}
=head1 SEE ALSO
lib/Algorithm/Evolutionary/Op/FullAlgorithm.pm view on Meta::CPAN
#Or using the constructor
my $m = new Algorithm::Evolutionary::Op::Bitflip; #Changes a single bit
my $c = new Algorithm::Evolutionary::Op::Crossover; #Classical 2-point crossover
my $replacementRate = 0.3; #Replacement rate
my $popSize = 20;
my $selector = new Algorithm::Evolutionary::Op::RouletteWheel $popSize; #One of the possible selectors
my $onemax = sub {
my $indi = shift;
my $total = 0;
my $len = $indi->length();
my $i = 0;
while ($i < $len ) {
$total += substr($indi->{'_str'}, $i, 1);
$i++;
}
return $total;
};
my $generation =
new Algorithm::Evolutionary::Op::GeneralGeneration( $onemax, $selector, [$m, $c], $replacementRate );
my $g100 = new Algorithm::Evolutionary::Op::GenerationalTerm 10;
lib/Algorithm/Evolutionary/Op/Gene_Boundary_Crossover.pm view on Meta::CPAN
sub apply ($$$){
my $self = shift;
my $arg = shift || croak "No victim here!";
# my $victim = $arg->clone();
my $gene_size = $self->{'_gene_size'};
my $victim = clone( $arg );
my $victim2 = shift || croak "No victim here!";
# croak "Incorrect type ".(ref $victim) if !$self->check($victim);
# croak "Incorrect type ".(ref $victim2) if !$self->check($victim2);
my $minlen = ( length( $victim->{_str} ) > length( $victim2->{_str} ) )?
length( $victim2->{_str} )/$gene_size: length( $victim->{_str} )/$gene_size;
croak "Crossover not possible" if ($minlen == 1);
my ($pt1, $range );
if ( $minlen == 2 ) {
$pt1 = $range = 1;
} else {
$pt1 = int( rand( $minlen - 1 ) );
# print "Puntos: $pt1, $range \n";
croak "No number of points to cross defined" if !defined $self->{_numPoints};
if ( $self->{_numPoints} > 1 ) {
$range = int ( 1 + rand( length( $victim->{_str} )/$gene_size - $pt1 - 1) );
} else {
$range = 1 + int( $minlen - $pt1 );
}
}
substr( $victim->{_str}, $pt1*$gene_size, $range*$gene_size )
= substr( $victim2->{_str}, $pt1*$gene_size, $range*$gene_size );
$victim->{'_fitness'} = undef;
return $victim;
}
lib/Algorithm/Evolutionary/Op/GeneralGeneration.pm view on Meta::CPAN
my $m = new Algorithm::Evolutionary::Op::Bitflip; #Changes a single bit
my $c = new Algorithm::Evolutionary::Op::Crossover; #Classical 2-point crossover
my $replacementRate = 0.3; #Replacement rate
use Algorithm::Evolutionary::Op::RouletteWheel;
my $popSize = 20;
my $selector = new Algorithm::Evolutionary::Op::RouletteWheel $popSize; #One of the possible selectors
use Algorithm::Evolutionary::Op::GeneralGeneration;
my $onemax = sub {
my $indi = shift;
my $total = 0;
for ( my $i = 0; $i < $indi->length(); $i ++ ) {
$total += substr( $indi->{_str}, $i, 1 );
}
return $total;
};
my @pop;
my $numBits = 10;
for ( 0..$popSize ) {
my $indi = new Algorithm::Evolutionary::Individual::BitString $numBits ; #Creates random individual
my $fitness = $onemax->( $indi );
$indi->Fitness( $fitness );
lib/Algorithm/Evolutionary/Op/IncMutation.pm view on Meta::CPAN
Issues an error if there is no C<_chars> array, which is needed for computing the next.
=cut
sub apply ($;$){
my $self = shift;
my $arg = shift || croak "No victim here!";
my $victim = clone( $arg );
croak "Incorrect type ".(ref $victim) if ! $self->check( $victim );
my $rnd = int (rand( length( $victim->{_str} ) ));
my $char = $victim->Atom( $rnd );
#Compute its place in the array
my $i = 0;
#Compute order in the array
croak "Can't do nuthin'; there's no alphabet in the victim" if @{$victim->{_chars}}< 0;
while ( ($victim->{_chars}[$i] ne $char )
&& ($i < @{$victim->{_chars}}) ) { $i++;};
#Generate next or previous
my $newpos = ( rand() > 0.5)?$i-1:$i+1;
$newpos = @{$victim->{_chars}}-1 if !$newpos;
lib/Algorithm/Evolutionary/Op/Inverover.pm view on Meta::CPAN
my $self = shift;
my $p1 = shift || croak "No victim here!"; #first parent
my $p2 = shift || croak "No victim here!"; #second parent
my $child=$p1->clone(); #Clone S' (child) from First parent
my $i; #Iterator
#Check parents type and size
croak "Incorrect type ".(ref $p1) if !$self->check($p1);
croak "Incorrect type ".(ref $p2) if !$self->check($p2);
croak "Inver-over Error: Parents haven't sime size " if ($p1->length() != $p2->length() );
my $leng=$p1->length(); #Chrom length
#Select randomly a atom c from S' (child)
my $c=int( rand( $leng/2 ) );
my $c2; #The another atom c' (called c2)
#Build Algorithm::Evolutionary::Op::Inverover child
while ( 1 )
{
if (rand() <= $self->rate)
{ #Select c' (c2) from the remaining cities of S'(child)
lib/Algorithm/Evolutionary/Op/Mutation.pm view on Meta::CPAN
=head1 SYNOPSIS
use Algorithm::Evolutionary::Op::Mutation;
#Create from scratch
my $op = new Algorithm::Evolutionary::Op::Mutation (0.5 );
#All options
my $priority = 1;
my $mutation = new Algorithm::Evolutionary::Op::Mutation 1/$length, $priority;
=head1 Base Class
L<Algorithm::Evolutionary::Op::Base|Algorithm::Evolutionary::Op::Base>
=head1 DESCRIPTION
Mutation operator for a GA
=cut
lib/Algorithm/Evolutionary/Op/Mutation.pm view on Meta::CPAN
L<Algorithm::Evolutionary::Individual::BitString|Algorithm::Evolutionary::Individual::BitString>.
It returns the victim.
=cut
sub apply ($;$) {
my $self = shift;
my $arg = shift || croak "No victim here!";
my $victim = $arg->clone();
croak "Incorrect type ".(ref $victim) if ! $self->check( $victim );
for ( my $i = 0; $i < length( $victim->{_str} ); $i ++ ) {
if ( rand() < $self->{_mutRate} ) {
my $bit = $victim->Atom($i);
$victim->Atom($i, $bit?0:1 );
}
}
$victim->{'_fitness'} = undef ;
return $victim;
}
=head1 Copyright
lib/Algorithm/Evolutionary/Op/Permutation.pm view on Meta::CPAN
=head1 Base Class
L<Algorithm::Evolutionary::Op::Base>
=head1 DESCRIPTION
Class independent permutation operator; any individual that has the
C<_str> instance variable (like
L<Algorithm::Evolutionary::Individual::String> and
L<Algorithm::Evolutionary::Individual::BitString>) will have some
of its elements swapped. Each string of length l has l!
permutations; the C<max_iterations> parameter should not be higher
than that.
This kind of operator is used extensively in combinatorial
optimization problems. See, for instance,
@article{prins2004simple,
title={{A simple and effective evolutionary algorithm for the vehicle routing problem}},
author={Prins, C.},
journal={Computers \& Operations Research},
volume={31},
lib/Algorithm/Evolutionary/Op/QuadXOver.pm view on Meta::CPAN
interchange genetic material.
=cut
sub apply ($$){
my $self = shift;
my $victim = shift || croak "No victim here!";
my $victim2 = shift || croak "No victim here!";
# croak "Incorrect type ".(ref $victim) if !$self->check($victim);
# croak "Incorrect type ".(ref $victim2) if !$self->check($victim2);
my $minlen = ( length( $victim->{_str} ) > length( $victim2->{_str} ) )?
length( $victim2->{_str} ): length( $victim->{_str} );
my $pt1 = 1+int( rand( $minlen - 1 ) ); # first crossover point shouldn't be 0
my $range;
if ( $self->{_numPoints} > 1 ) {
$range= 1 + int( rand( $minlen - $pt1 ) );
} else {
$range = $minlen - $pt1;
}
# print "Puntos: $pt1, $range \n";
my $str = $victim->{_str};
substr( $victim->{_str}, $pt1, $range ) = substr( $victim2->{_str}, $pt1, $range );
lib/Algorithm/Evolutionary/Op/Quad_Crossover_Diff.pm view on Meta::CPAN
interchange genetic material.
=cut
sub apply ($$){
my $self = shift;
my $victim = shift || croak "No victim here!";
my $victim2 = shift || croak "No victim here!";
# croak "Incorrect type ".(ref $victim) if !$self->check($victim);
# croak "Incorrect type ".(ref $victim2) if !$self->check($victim2);
my $minlen = ( length( $victim->{_str} ) > length( $victim2->{_str} ) )?
length( $victim2->{_str} ): length( $victim->{_str} );
my @diffs;
for ( my $i = 0; $i < $minlen; $i ++ ) {
if ( substr( $victim2->{_str}, $i, 1 ) ne substr( $victim->{_str}, $i, 1 ) ) {
push @diffs, $i;
}
}
for ( my $i = 0; $i < $self->{_numPoints}; $i ++ ) {
if ( @diffs ) {
lib/Algorithm/Evolutionary/Op/StringRand.pm view on Meta::CPAN
$xmen->apply( $strChrom ) # will change 'acgt' into 'aagt' or
# 'aggt', for instance
=cut
sub apply ($;$){
my $self = shift;
my $arg = shift || croak "No victim here!";
my $victim = $arg->clone();
croak "Incorrect type ".(ref $victim) if ! $self->check( $victim );
my $rnd = int (rand( length( $victim->{_str} ) ));
my $char = $victim->Atom( $rnd );
#Compute its place in the array
my $i = 0;
#Compute order in the array
while ( ($victim->{_chars}[$i] ne $char )
&& ($i < @{$victim->{_chars}}) ) { $i++;};
#Generate next or previous
my $newpos = ( rand() > 0.5)?$i-1:$i+1;
$newpos = @{$victim->{_chars}}-1 if !$newpos;
$newpos = 0 if $newpos >= @{$victim->{_chars}};
lib/Algorithm/Evolutionary/Op/String_Mutation.pm view on Meta::CPAN
=head2 apply( $chromosome )
Applies mutation operator to a "Chromosome", a string, really.
=cut
sub apply ($;$){
my $self = shift;
my $arg = shift || croak "No victim here!";
my $victim = $arg->clone();
my $size = length($victim->{'_str'});
croak "Too many changes" if $self->{'_howMany'} >= $size;
my @char_array = 0..($size-1); # Avoids double mutation in a single place
for ( my $i = 0; $i < $self->{'_howMany'}; $i++ ) {
my $rnd = int (rand( @char_array ));
my $who = splice(@char_array, $rnd, 1 );
my $what = $victim->Atom( $who );
my @these_chars = @{ $victim->{'_chars'}};
for ( my $c = 0; $c < @{ $victim->{'_chars'}}; $c++ ) { #Exclude this character
if ( $victim->{'_chars'}[$c] eq $what ) {
lib/Algorithm/Evolutionary/Op/Uniform_Crossover.pm view on Meta::CPAN
parents at the same time, check
L<QuadXOver|Algorithm::Evolutionary::Op::QuadXOver>
=cut
sub apply ($$$){
my $self = shift;
my $arg = shift || croak "No victim here!";
my $victim = clone( $arg );
my $victim2 = shift || croak "No victim here!";
my $min_length = ( $victim->size() > $victim2->size() )?
$victim2->size():$victim->size();
for ( my $i = 0; $i < $min_length; $i++ ) {
if ( rand() < $self->{'_crossover_rate'}) {
$victim->Atom($i, $victim2->Atom($i));
}
}
$victim->{'_fitness'} = undef;
return $victim;
}
=head1 Copyright
lib/Algorithm/Evolutionary/Op/Uniform_Crossover_Diff.pm view on Meta::CPAN
sure that what is interchanged is different.
=cut
sub apply ($$){
my $self = shift;
my $arg = shift || croak "No victim here!";
my $arg2 = shift || croak "No victim here!";
my $victim2 = $arg2->clone();
my $victim = $arg->clone();
my $min_length = ( length( $victim->{_str} ) > length( $victim2->{_str} ) )?
length( $victim2->{_str} ): length( $victim->{_str} );
my @diffs;
for ( my $i = 0; $i < $min_length; $i ++ ) {
if ( substr( $victim2->{_str}, $i, 1 ) ne substr( $victim->{_str}, $i, 1 ) ) {
push @diffs, $i;
}
}
for ( my $i = 0; $i < $self->{'_numPoints'}; $i ++ ) {
if ( $#diffs > 0 ) {
my $diff = splice( @diffs, rand(@diffs), 1 );
substr( $victim->{'_str'}, $diff, 1 ) = substr( $victim2->{'_str'}, $diff, 1 );
} else {
lib/Algorithm/Evolutionary/Op/VectorCrossover.pm view on Meta::CPAN
} else {
my $pt1 = int( rand( @{$victim->{'_array'}} - 1 ) ) ; #in int env; contains $# +1
my $possibleRange = @{$victim->{'_array'}} - $pt1 - 1;
my $range;
if ( $self->{'_numPoints'} > 1 ) {
$range = 1+ int ( rand( $possibleRange ) );
} else {
$range = $possibleRange + 1;
}
#Check length to avoid unwanted lengthening
return $victim if ( ( $pt1+$range >= @{$victim->{'_array'}} ) || ( $pt1+$range >= @{$victim2->{'_array'}} ));
@{$victim->{'_array'}}[$pt1..($pt1+$range)] =
@{$victim2->{'_array'}}[$pt1..($pt1+$range)];
$victim->Fitness( undef ); #It's been changed, so fitness is invalid
}
return $victim;
}
=head1 Copyright