File Coverage

lib/Algorithm/Evolutionary/Individual/String.pm
Criterion Covered Total %
statement 83 102 81.3
branch 2 6 33.3
condition 6 10 60.0
subroutine 22 26 84.6
pod 11 11 100.0
total 124 155 80.0


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