use strict; #-*-cperl-*-
use warnings;
use lib qw(../../../../lib);
=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
my @array = qw( 0 1 0 1 0 0 1 ); #Create a tied array
tie my @vector, 'Algorithm::Evolutionary::Individual::Bit_Vector', @array;
print tied( @vector )->asXML();
print $indi3->asString(); #Prints the individual
print $indi3->asXML() #Prints it as XML. See L<Algorithm::Evolutionary::XML>
print $indi3->as_yaml() #Change of convention, I know...
=head1 Base Class
L<Algorithm::Evolutionary::Individual::String|Algorithm::Evolutionary::Individual::String>
=head1 DESCRIPTION
Bitstring Individual for a Genetic Algorithm. Used, for instance, in a canonical GA
=cut
package Algorithm::Evolutionary::Individual::Bit_Vector;
use Carp;
use Bit::Vector;
use String::Random; # For initial string generation
our ($VERSION) = ( '$Revision: 3.1 $ ' =~ / (\d+\.\d+)/ );
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
Sets or gets the value of the n-th character in the string. Counting
starts at 0, as usual in Perl arrays.
=cut
sub Atom: lvalue {
my $self = shift;
my $index = shift;
my $last_index = $self->{'_bit_vector'}->Size()-1;
if ( @_ ) {
$self->{'_bit_vector'}->Bit_Copy($last_index-$index, shift );
} else {
$self->{'_bit_vector'}->bit_test($last_index - $index);
}
}
=head2 size()
Returns size in bits
=cut
sub size {
my $self = shift;
return $self->{'_bit_vector'}->Size();
}
=head2 clone()
Clones using native methods. Does not work with general Clone::Fast, since it's implemented as an XS
=cut
sub clone {
my $self = shift;
my $clone = Algorithm::Evolutionary::Individual::Base::new( ref $self );
$clone->{'_bit_vector'} = $self->{'_bit_vector'}->Clone();
return $clone;
}
=head2 as_string()
Overrides the default; prints the binary chromosome
=cut
sub as_string {
my $self = shift;
return $self->{'_bit_vector'}->to_Bin();
}
=head2 Chrom()
Returns the internal bit_vector
=cut
sub Chrom {
my $self = shift;
return $self->{'_bit_vector'};
}
=head2 TIE methods
String implements FETCH, STORE, PUSH and the rest, so an String
can be tied to an array and used as such.
=cut
sub FETCH {
my $self = shift;
my $bit_vector = $self->{'_bit_vector'};
return $bit_vector->bit_test( $bit_vector->Size() - 1 - shift );
}
sub STORE {
my $self = shift;
my $bit_vector = $self->{'_bit_vector'};
my $index = shift;
$self->{'_bit_vector'}->Bit_Copy($bit_vector->Size()- 1 -$index, shift );
}
sub PUSH {
my $self = shift;
my $new_vector = Bit::Vector->new_Bin(scalar(@_), join("",@_));
$self->{'_bit_vector'} = $self->{'_bit_vector'}->Concat( $new_vector );
}
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;
my $slice = Bit::Vector->new($bits);
my $size = $self->{'_bit_vector'}->Size();
$slice->Interval_Copy( $self->{'_bit_vector'}, 0, $size-$offset-$bits, $bits );
if ( @_ ) {
$new_vector = Bit::Vector->new_Bin(scalar(@_), join("",@_));
$self->{'_bit_vector'}->Interval_Substitute( $new_vector,
$size-$offset-$bits, 0 , 0,
$new_vector->Size() );
} 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 $
$Author: jmerelo $
$Revision: 3.1 $
$Name $
=cut