File Coverage

lib/Algorithm/Evolutionary/Individual/String.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1 31     31   93352 use strict;
  31         70  
  31         1508  
2 31     31   214 use warnings;
  31         59  
  31         1183  
3              
4 31     31   162 use lib qw(../../..);
  31         60  
  31         348  
5              
6             =encoding utf8
7              
8             =head1 NAME
9              
10             Algorithm::Evolutionary::Individual::String - A character string to be evolved. Useful mainly in word games
11              
12             =head1 SYNOPSIS
13              
14             use Algorithm::Evolutionary::Individual::String;
15              
16             my $indi = new Algorithm::Evolutionary::Individual::String ['a'..'z'], 10;
17             # Build random bitstring with length 10
18              
19             my $indi3 = new Algorithm::Evolutionary::Individual::String;
20             $indi3->set( { length => 20,
21             chars => ['A'..'Z'] } ); #Sets values, but does not build the string
22             $indi3->randomize(); #Creates a random bitstring with length as above
23             print $indi3->Atom( 7 ); #Returns the value of the 7th character
24             $indi3->Atom( 3, 'Q' ); #Sets the value
25              
26             $indi3->addAtom( 'K' ); #Adds a new character to the bitstring at the end
27              
28             my $indi4 = Algorithm::Evolutionary::Individual::String->fromString( 'esto es un string'); #Creates an individual from that string
29              
30             my $indi5 = $indi4->clone(); #Creates a copy of the individual
31              
32             my @array = qw( a x q W z ñ); #Tie a String individual
33             tie my @vector, 'Algorithm::Evolutionary::Individual::String', @array;
34             print tied( @vector )->asXML();
35            
36             print $indi3->as_string(); #Prints the individual
37              
38             =head1 Base Class
39              
40             L
41              
42             =head1 DESCRIPTION
43              
44             String Individual for a evolutionary algorithm. Contains methods to handle strings
45             easily. It is also TIEd so that strings can be handled as arrays.
46              
47             =head1 METHODS
48              
49             =cut
50              
51             package Algorithm::Evolutionary::Individual::String;
52              
53 31     31   6400 use Carp;
  31         57  
  31         3132  
54              
55             our $VERSION = '3.6';
56              
57 31     31   204 use base 'Algorithm::Evolutionary::Individual::Base';
  31         73  
  31         33273  
58              
59             use constant MY_OPERATORS => qw(Algorithm::Evolutionary::Op::Crossover
60             Algorithm::Evolutionary::Op::QuadXOver
61             Algorithm::Evolutionary::Op::StringRand
62             Algorithm::Evolutionary::Op::Permutation
63             Algorithm::Evolutionary::Op::IncMutation
64             Algorithm::Evolutionary::Op::ChangeLengthMutation );
65              
66             =head2 new
67              
68             Creates a new random string, with fixed initial length, and uniform
69             distribution of characters along the character class that is
70             defined. However, this character class is just used to generate new
71             individuals and in mutation operators, and the validity is not
72             enforced unless the client class does it
73              
74             =cut
75              
76             sub new {
77             my $class = shift;
78             my $self = Algorithm::Evolutionary::Individual::Base::new( $class );
79             $self->{'_chars'} = shift || ['a'..'z'];
80             $self->{'_length'} = shift || 10;
81             $self->randomize();
82             return $self;
83             }
84              
85             sub TIEARRAY {
86             my $class = shift;
87             my $self = { _str => join("",@_),
88             _length => scalar( @_ ),
89             _fitness => undef };
90             bless $self, $class;
91             return $self;
92             }
93              
94             =head2 randomize
95              
96             Assigns random values to the elements
97              
98             =cut
99              
100             sub randomize {
101             my $self = shift;
102             $self->{'_str'} = ''; # Reset string
103             for ( my $i = 0; $i < $self->{'_length'}; $i ++ ) {
104             $self->{'_str'} .= $self->{'_chars'}[ rand( @{$self->{'_chars'}} ) ];
105             }
106             }
107              
108             =head2 addAtom
109              
110             Adds an atom at the end
111              
112             =cut
113              
114             sub addAtom{
115             my $self = shift;
116             my $atom = shift;
117             $self->{_str}.= $atom;
118             }
119              
120             =head2 fromString
121              
122             Similar to a copy ctor; creates a bitstring individual from a string. Will be deprecated soon
123              
124             =cut
125              
126             sub fromString {
127             my $class = shift;
128             my $str = shift;
129             my $self = Algorithm::Evolutionary::Individual::Base::new( $class );
130             $self->{_str} = $str;
131             my %chars;
132             map ( $chars{$_} = 1, split(//,$str) );
133             my @chars = keys %chars;
134             $self->{_length} = length( $str );
135             $self->{'_chars'} = \@chars;
136             return $self;
137             }
138              
139             =head2 from_string
140              
141             Similar to a copy ctor; creates a bitstring individual from a string.
142              
143             =cut
144              
145             sub from_string {
146             my $class = shift;
147             my $chars = shift;
148             my $str = shift;
149             my $self = Algorithm::Evolutionary::Individual::Base::new( $class );
150             $self->{'_chars'} = $chars;
151             $self->{'_str'} = $str;
152             $self->{'_length'} = length( $str );
153             return $self;
154             }
155              
156             =head2 clone
157              
158             Similar to a copy ctor: creates a new individual from another one
159              
160             =cut
161              
162             sub clone {
163             my $indi = shift || croak "Indi to clone missing ";
164             my $self = { '_fitness' => undef };
165             bless $self, ref $indi;
166             for ( qw( _chars _str _length) ) {
167             $self->{ $_ } = $indi->{$_};
168             }
169             return $self;
170             }
171              
172              
173             =head2 asString
174              
175             Prints it
176              
177             =cut
178              
179             sub asString {
180             my $self = shift;
181             my $str = $self->{_str} . " -> ";
182             if ( defined $self->{_fitness} ) {
183             $str .=$self->{_fitness};
184             }
185             return $str;
186             }
187              
188             =head2 Atom
189              
190             Sets or gets the value of the n-th character in the string. Counting
191             starts at 0, as usual in Perl arrays.
192              
193             =cut
194              
195             sub Atom {
196             my $self = shift;
197             my $index = shift;
198             if ( @_ ) {
199             substr( $self->{_str}, $index, 1 ) = substr(shift,0,1);
200             } else {
201             substr( $self->{_str}, $index, 1 );
202             }
203             }
204              
205             =head2 TIE methods
206              
207             String implements FETCH, STORE, PUSH and the rest, so an String
208             can be tied to an array and used as such.
209              
210             =cut
211              
212             sub FETCH {
213             my $self = shift;
214             return $self->Atom( @_ );
215             }
216              
217             sub STORE {
218             my $self = shift;
219             $self->Atom( @_ );
220             }
221              
222             sub PUSH {
223             my $self = shift;
224             $self->{_str}.= join("", @_ );
225             }
226              
227             sub UNSHIFT {
228             my $self = shift;
229             $self->{_str} = join("", @_ ).$self->{_str} ;
230             }
231              
232             sub POP {
233             my $self = shift;
234             my $pop = substr( $self->{_str}, length( $self->{_str} )-1, 1 );
235             substr( $self->{_str}, length( $self->{_str} ) -1, 1 ) = '';
236             return $pop;
237             }
238              
239             sub SHIFT {
240             my $self = shift;
241             my $shift = substr( $self->{_str}, 0, 1 );
242             substr( $self->{_str}, 0, 1 ) = '';
243             return $shift;
244             }
245              
246             sub SPLICE {
247             my $self = shift;
248             my $offset = shift;
249             my $length = shift || length( $self->{'_str'} - $offset );
250             my $sub_string = substr( $self->{_str}, $offset, $length );
251             # if ( @_ ) {
252             substr( $self->{_str}, $offset, $length ) = join("", @_ );
253             # }
254             return split(//,$sub_string);
255             }
256              
257             sub FETCHSIZE {
258             my $self = shift;
259             return length( $self->{_str} );
260             }
261              
262             =head2 size()
263              
264             Returns length of the string that stores the info; overloads abstract base method.
265              
266             =cut
267              
268             sub size {
269             my $self = shift;
270             return length($self->{_str}); #Solves ambiguity
271             }
272              
273             =head2 as_string()
274            
275             Returns the string used as internal representation
276              
277             =cut
278              
279             sub as_string {
280             my $self = shift;
281             return $self->{_str};
282             }
283              
284              
285             =head2 asXML()
286              
287             Prints it as XML. See L for more info on this
288              
289             =cut
290              
291             sub asXML {
292             my $self = shift;
293             my $str = $self->SUPER::asXML();
294             my $str2 = "> " .join( "", map( "$_ ", split( "", $self->{_str} )));
295             $str =~ s/\/>/$str2/e ;
296             return $str."\n";
297             }
298              
299              
300             =head2 Chrom
301              
302             Sets or gets the variable that holds the chromosome. Not very nice, and
303             I would never ever do this in C++
304              
305             =cut
306              
307             sub Chrom {
308             my $self = shift;
309             if ( defined $_[0] ) {
310             $self->{_str} = shift;
311             }
312             return $self->{_str}
313             }
314              
315             =head1 Known subclasses
316              
317             =over 4
318              
319             =item *
320              
321             L
322              
323             =back
324              
325             =head2 Copyright
326            
327             This file is released under the GPL. See the LICENSE file included in this distribution,
328             or go to http://www.fsf.org/licenses/gpl.txt
329              
330             =cut