File Coverage

lib/Algorithm/Evolutionary/Individual/String.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


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