File Coverage

lib/Algorithm/Evolutionary/Individual/Base.pm
Criterion Covered Total %
statement 40 68 58.8
branch 7 18 38.8
condition 1 11 9.0
subroutine 11 19 57.8
pod 12 12 100.0
total 71 128 55.4


line stmt bran cond sub pod time code
1 36     36   810 use strict; #-*-cperl,hi-lock,auto-fill-*-
  36         49  
  36         1170  
2 36     36   146 use warnings;
  36         43  
  36         930  
3              
4 36     36   163 use lib qw( ../../../../lib );
  36         41  
  36         198  
5              
6             =head1 NAME
7              
8             Algorithm::Evolutionary::Individual::Base - Base class for chromosomes that knows how to build them, and has some helper methods.
9            
10             =head1 SYNOPSIS
11              
12             use Algorithm::Evolutionary::Individual::Base;
13              
14             my $indi = Algorithm::Evolutionary::Individual::Base->fromParam( $param_hashref ); #From parametric description
15              
16             $binIndi2->Fitness( 3.5 ); #Sets or gets fitness
17             print $binIndi2->Fitness();
18              
19             my $emptyIndi = new Algorithm::Evolutionary::Individual::Base;
20              
21             =head1 DESCRIPTION
22              
23             Base class for individuals, that is, "chromosomes" in evolutionary
24             computation algorithms. However, chromosomes needn't be bitstrings, so
25             the name is a bit misleading. This is, however, an "empty" base class,
26             that acts as a boilerplate for deriving others.
27              
28             =cut
29              
30             package Algorithm::Evolutionary::Individual::Base;
31              
32 36     36   19872 use YAML qw(Dump Load LoadFile);
  36         224457  
  36         2481  
33 36     36   264 use Carp;
  36         47  
  36         2488  
34              
35             our $VERSION = '3.3';
36              
37 36     36   162 use constant MY_OPERATORS => qw(None);
  36         52  
  36         23014  
38              
39             =head1 METHODS
40              
41              
42             =head2 AUTOLOAD
43              
44             Creates methods for instance variables automatically
45              
46             =cut
47              
48             sub AUTOLOAD {
49 0     0   0 my $self = shift;
50 0         0 my $attr = our $AUTOLOAD;
51 0         0 $attr =~ s/.*:://;
52 0 0       0 return unless $attr =~ /[^A-Z]/; # skip DESTROY and all-cap methods
53 0         0 my $instance_variable = "_$attr";
54 0 0       0 $self->{$instance_variable} = shift if @_;
55 0         0 return $self->{$instance_variable};
56             }
57              
58             =head2 new( $options )
59              
60             Creates a new Base individual of the required class, with a fitness, and sets fitnes to undef.
61             Takes as params a hash to the options of the individual, that will be passed
62             on to the object of the class when it iss initialized.
63              
64             =cut
65              
66             sub new {
67 9     9 1 13 my $class = shift;
68 9 50       41 if ( $class !~ /Algorithm::Evolutionary/ ) {
69 0         0 $class = "Algorithm::Evolutionary::Individual::$class";
70             }
71 9         13 my $options = shift;
72 9         19 my $self = { _fitness => undef }; # Avoid error
73 9         21 bless $self, $class; # And bless it
74              
75             #If the class is not loaded, we load it.
76 9 50       38 if ( !$INC{"$class\.pm"} ) {
77 9 100       491 eval "require $class" || croak "Can't find $class Module";
78             }
79 8 50       28 if ( $options ) {
80 0         0 $self->set( $options );
81             }
82              
83 8         21 return $self;
84             }
85              
86             =head2 create( $ref_to_hash )
87              
88             Creates a new individual, but uses a different interface: takes a
89             ref-to-hash, with named parameters, which gives it a common interface
90             to all the hierarchy. The main difference with respect to new is that
91             after creation, it is initialized with random values.
92              
93             =cut
94              
95             sub create {
96 0     0 1 0 my $class = shift;
97 0   0     0 my $ref = shift || croak "Can't find the parameters hash";
98 0         0 my $self = Algorithm::Evolutionary::Individual::Base::new( $class, $ref );
99 0         0 $self->randomize();
100 0         0 return $self;
101             }
102              
103             =head2 set( $ref_to_hash )
104              
105             Sets values of an individual; takes a hash as input. Keys are prepended an
106             underscore and turn into instance variables
107              
108             =cut
109              
110             sub set {
111 1     1 1 13 my $self = shift;
112 1   33     3 my $hash = shift || croak "No params here";
113 1         2 for ( keys %{$hash} ) {
  1         7  
114 2         6 $self->{"_$_"} = $hash->{$_};
115             }
116             }
117              
118             =head2 as_yaml()
119              
120             Prints it as YAML.
121              
122             =cut
123              
124             sub as_yaml {
125 4     4 1 55995 my $self = shift;
126 4         16 return Dump($self);
127             }
128              
129             =head2 as_string()
130              
131             Prints it as a string in the most meaningful representation possible
132              
133             =cut
134              
135             sub as_string {
136 0     0 1 0 croak "This function is not defined at this level, you should override it in a subclass\n";
137             }
138              
139             =head2 as_string_with_fitness( [$separator] )
140              
141             Prints it as a string followed by fitness. Separator by default is C<;>
142              
143             =cut
144              
145             sub as_string_with_fitness {
146 0     0 1 0 my $self = shift;
147 0   0     0 my $separator = shift || "; ";
148 0         0 return $self->as_string().$separator.$self->Fitness();
149             }
150              
151             =head2 Atom( $index [, $value )
152              
153             Sets or gets the value of an atom. Each individual is divided in atoms, which
154             can be accessed sequentially. If that does not apply, Atom can simply return the
155             whole individual
156              
157             =cut
158              
159             sub Atom {
160 0     0 1 0 croak "This function is not defined at this level, you should override it in a subclass\n";
161             }
162              
163             =head2 Fitness( [$value] )
164              
165             Sets or gets fitness
166              
167             =cut
168              
169             sub Fitness {
170 2     2 1 370 my $self = shift;
171 2 100       7 if ( defined $_[0] ) {
172 1         3 $self->{_fitness} = shift;
173             }
174 2         6 return $self->{_fitness};
175             }
176              
177             =head2 my_operators()
178              
179             Operators that can act on this data structure. Returns an array with the names of the known operators
180              
181             =cut
182              
183             sub my_operators {
184 2     2 1 1288 my $self = shift;
185 2         43 return $self->MY_OPERATORS;
186             }
187              
188             =head2 evaluate( $fitness )
189              
190             Evaluates using the $fitness thingy given. Can be a L object or a ref-to-sub
191              
192             =cut
193              
194             sub evaluate {
195 0     0 1   my $self = shift;
196 0   0       my $fitness_func = shift || croak "Need a fitness function";
197 0 0         if ( ref $fitness_func eq 'CODE' ) {
    0          
198 0           return $self->Fitness( $fitness_func->($self) );
199             } elsif ( ( ref $fitness_func ) =~ 'Fitness' ) {
200 0           return $self->Fitness( $fitness_func->apply($self) );
201             } else {
202 0           croak "$fitness_func can't be used to evaluate";
203             }
204              
205             }
206              
207             =head2 Chrom()
208              
209             Sets or gets the chromosome itself, that is, the data
210             structure evolved. Since each derived class has its own
211             data structure, and its own name, it is left to them to return
212             it
213              
214             =cut
215              
216             sub Chrom {
217 0     0 1   my $self = shift;
218 0           croak "To be implemented in derived classes!";
219             }
220              
221             =head2 size()
222              
223             OK, OK, this is utter inconsistence, but I'll re-consistence it
224             eventually. Returns a meaningful size; but should be reimplemented
225             by siblings
226              
227             =cut
228              
229             sub size() {
230 0     0 1   croak "To be implemented in derived classes!";
231             }
232              
233             =head1 Known subclasses
234              
235             There are others, but I'm not so sure they work.
236              
237             =over 4
238              
239             =item *
240              
241             L
242              
243             =item *
244              
245             L
246              
247             =item *
248              
249             L
250              
251             =item *
252              
253             L
254              
255             =back
256              
257             =head1 Copyright
258            
259             This file is released under the GPL. See the LICENSE file included in this distribution,
260             or go to http://www.fsf.org/licenses/gpl.txt
261              
262              
263             =cut
264              
265             "The plain truth";
266