File Coverage

lib/Algorithm/Evolutionary/Op/CanonicalGA.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 1     1   6 use strict;
  1         4  
  1         42  
2 1     1   6 use warnings;
  1         3  
  1         58  
3              
4             =head1 NAME
5              
6             Algorithm::Evolutionary::Op::CanonicalGA - Canonical Genetic Algorithm, with any representation
7              
8             =head1 SYNOPSIS
9              
10             # Straightforward instance, with all defaults (except for fitness function)
11             my $algo = new Algorithm::Evolutionary::Op::CanonicalGA( $eval );
12              
13             #Define an easy single-generation algorithm with predefined mutation and crossover
14             my $m = new Algorithm::Evolutionary::Op::Bitflip; #Changes a single bit
15             my $c = new Algorithm::Evolutionary::Op::QuadXOver; #Classical 2-point crossover
16             my $generation = new Algorithm::Evolutionary::Op::CanonicalGA( $rr, 0.2, [$m, $c] );
17              
18             =head1 Base Class
19              
20             L
21              
22             =head1 DESCRIPTION
23              
24             The canonical classical genetic algorithm evolves a population of
25             bitstrings until they reach the optimum fitness. It performs mutation
26             on the bitstrings by flipping a single bit, crossover interchanges a
27             part of the two parents.
28              
29             The first operator should be unary (a la mutation) and the second
30             binary (a la crossover) they will be applied in turn to couples of the
31             population.
32              
33             =head1 METHODS
34              
35             =cut
36              
37             package Algorithm::Evolutionary::Op::CanonicalGA;
38              
39 1     1   7 use lib qw(../../..);
  1         4  
  1         8  
40              
41             our $VERSION = sprintf "%d.1%02d", q$Revision: 3.6 $ =~ /(\d+)\.(\d+)/g; # Hack for avoiding version mismatch
42              
43              
44 1     1   215 use Carp;
  1         3  
  1         81  
45              
46 1         11 use Algorithm::Evolutionary qw(Wheel
47             Op::Bitflip
48 1     1   11 Op::QuadXOver );
  1         3  
49              
50             use base 'Algorithm::Evolutionary::Op::Easy';
51              
52             # Class-wide constants
53             our $APPLIESTO = 'ARRAY';
54             our $ARITY = 1;
55              
56             =head2 new( $fitness[, $selection_rate][,$operators_ref_to_array] )
57              
58             Creates an algorithm, with the usual operators. Includes a default mutation
59             and crossover, in case they are not passed as parameters. The first
60             element in the array ref should be an unary, and the second a
61             binary operator.
62              
63             =cut
64              
65             sub new {
66             my $class = shift;
67             my $self = {};
68             $self->{_eval} = shift || croak "No eval function found";
69             $self->{_selrate} = shift || 0.4;
70             if ( @_ ) {
71             $self->{_ops} = shift;
72             } else {
73             #Create mutation and crossover
74             my $mutation = new Algorithm::Evolutionary::Op::Bitflip;
75             push( @{$self->{_ops}}, $mutation );
76             my $xover = new Algorithm::Evolutionary::Op::QuadXOver;
77             push( @{$self->{_ops}}, $xover );
78             }
79             bless $self, $class;
80             return $self;
81              
82             }
83              
84             =head2 apply( $population)
85              
86             Applies a single generation of the algorithm to the population; checks
87             that it receives a ref-to-array as input, croaks if it does
88             not. Returns a sorted, culled, evaluated population for next
89             generation.
90              
91             =cut
92              
93             sub apply ($) {
94             my $self = shift;
95             my $pop = shift || croak "No population here";
96             croak "Incorrect type ".(ref $pop) if ref( $pop ) ne $APPLIESTO;
97              
98             my $eval = $self->{_eval};
99             for ( @$pop ) {
100             if ( !defined ($_->Fitness() ) ) {
101             $_->evaluate( $eval );
102             }
103             }
104              
105             my @newPop;
106             @$pop = sort { $b->{_fitness} <=> $a->{_fitness} } @$pop;
107             my @rates = map( $_->Fitness(), @$pop );
108              
109             #Creates a roulette wheel from the op priorities. Theoretically,
110             #they might have changed
111             my $popWheel= new Algorithm::Evolutionary::Wheel @rates;
112             my $popSize = scalar @$pop;
113             my @ops = @{$self->{_ops}};
114             for ( my $i = 0; $i < $popSize*(1-$self->{_selrate})/2; $i ++ ) {
115             my $clone1 = $ops[0]->apply( $pop->[$popWheel->spin()] ); # This should be a mutation-like op
116             my $clone2 = $ops[0]->apply( $pop->[$popWheel->spin()] );
117             $ops[1]->apply( $clone1, $clone2 ); #This should be a
118             #crossover-like op
119             $clone1->evaluate( $eval );
120             $clone2->evaluate( $eval );
121             push @newPop, $clone1, $clone2;
122             }
123             #Re-sort
124             @{$pop}[$popSize*$self->{_selrate}..$popSize-1] = @newPop;
125             @$pop = sort { $b->{_fitness} <=> $a->{_fitness} } @$pop;
126             }
127              
128              
129             =head1 SEE ALSO
130              
131             =over 4
132              
133             =item L
134              
135             =item L
136              
137             =item L
138              
139             =back
140              
141             Probably you will also be able to find a
142             L example within this
143             bundle. Check it out for usage examples
144              
145             =head1 Copyright
146            
147             This file is released under the GPL. See the LICENSE file included in this distribution,
148             or go to http://www.fsf.org/licenses/gpl.txt
149              
150             CVS Info: $Date: 2011/02/14 06:55:36 $
151             $Header: /media/Backup/Repos/opeal/opeal/Algorithm-Evolutionary/lib/Algorithm/Evolutionary/Op/CanonicalGA.pm,v 3.6 2011/02/14 06:55:36 jmerelo Exp $
152             $Author: jmerelo $
153             $Revision: 3.6 $
154             $Name $
155              
156             =cut
157              
158             "The truth is out there";