File Coverage

lib/Algorithm/Evolutionary/Op/Breeder_Diverser.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   4 use strict;
  1         2  
  1         34  
2 1     1   5 use warnings;
  1         2  
  1         57  
3              
4             =head1 NAME
5             Algorithm::Evolutionary::Op::Breeder_Diverser - Like Breeder, only it tries to cross only individuals that are different
6              
7             =head1 SYNOPSIS
8              
9             use Algorithm::Evolutionary qw( Individual::BitString
10             Op::Mutation Op::Crossover
11             Op::RouletteWheel
12             Op::Breeder_Diverser);
13              
14             use Algorithm::Evolutionary::Utils qw(average);
15              
16             my @pop;
17             my $number_of_bits = 20;
18             my $population_size = 20;
19             my $replacement_rate = 0.5;
20             for ( 1..$population_size ) {
21             my $indi = new Algorithm::Evolutionary::Individual::BitString $number_of_bits ; #Creates random individual
22             $indi->evaluate( $onemax );
23             push( @pop, $indi );
24             }
25              
26             my $m = new Algorithm::Evolutionary::Op::Mutation 0.5;
27             my $c = new Algorithm::Evolutionary::Op::Crossover; #Classical 2-point crossover
28              
29             my $selector = new Algorithm::Evolutionary::Op::RouletteWheel $population_size; #One of the possible selectors
30              
31             my $generation =
32             new Algorithm::Evolutionary::Op::Breeder_Diverser( $selector, [$m, $c] );
33              
34             my @sortPop = sort { $b->Fitness() <=> $a->Fitness() } @pop;
35             my $bestIndi = $sortPop[0];
36             my $previous_average = average( \@sortPop );
37             $generation->apply( \@sortPop );
38              
39             =head1 Base Class
40              
41             L
42              
43             =head1 DESCRIPTION
44              
45             Breeder part of the evolutionary algorithm; takes a population and
46             returns another created from the first. Different from
47             L: tries to avoid crossover
48             among the same individuals and also re-creating an individual already
49             in the pool. In that sense it "diverses", tries to diversify the
50             population. In general, it works better in environments where high
51             diversity is needed (like, for instance, in L.
52              
53             =head1 METHODS
54              
55             =cut
56              
57             package Algorithm::Evolutionary::Op::Breeder_Diverser;
58              
59 1     1   6 use lib qw(../../..);
  1         1  
  1         11  
60              
61             our ($VERSION) = ( '$Revision: 1.5 $ ' =~ / (\d+\.\d+)/ ) ;
62              
63 1     1   179 use Carp;
  1         2  
  1         84  
64              
65 1     1   7 use base 'Algorithm::Evolutionary::Op::Base';
  1         3  
  1         78  
66              
67             use Algorithm::Evolutionary qw(Wheel
68             Op::Tournament_Selection);
69              
70             # Class-wide constants
71             our $APPLIESTO = 'ARRAY';
72             our $ARITY = 1;
73              
74             =head2 new( $ref_to_operator_array[, $selector = new Algorithm::Evolutionary::Op::Tournament_Selection 2 ] )
75              
76             Creates a breeder, with a selector and array of operators
77              
78             =cut
79              
80             sub new {
81             my $class = shift;
82             my $self = {};
83             $self->{_ops} = shift || croak "No operators found";
84             $self->{_selector} = shift
85             || new Algorithm::Evolutionary::Op::Tournament_Selection 2;
86             bless $self, $class;
87             return $self;
88             }
89              
90             =head2 apply( $population[, $how_many || $population_size] )
91              
92             Applies the algorithm to the population, which should have
93             been evaluated first; checks that it receives a
94             ref-to-array as input, croaks if it does not. Returns a sorted,
95             culled, evaluated population for next generation.
96              
97             It is valid only for string-denominated chromosomes.
98              
99             =cut
100              
101             sub apply ($) {
102             my $self = shift;
103             my $pop = shift || croak "No population here";
104             my $output_size = shift || @$pop; # Defaults to pop size
105             my @ops = @{$self->{_ops}};
106              
107             #Select for breeding
108             my $selector = $self->{_selector};
109             my @genitors = $selector->apply( $pop );
110              
111             #Reproduce
112             my $totRate = 0;
113             my @rates;
114             for ( @ops ) {
115             push( @rates, $_->{rate});
116             }
117             my $op_wheel = new Algorithm::Evolutionary::Wheel @rates;
118              
119             my @new_population;
120             my $i = 0;
121             while ( @new_population < $output_size ) {
122             my @offspring;
123             my $selected_op = $ops[ $op_wheel->spin()];
124             my $chosen = $genitors[ $i++ % @genitors]; #Chosen in turn
125             push( @offspring, $chosen->clone() );
126             if( $selected_op->arity() == 2 ) {
127             my $another_one;
128             do {
129             $another_one = $genitors[ rand( @genitors )];
130             } until ( $another_one->{'_str'} ne $chosen->{'_str'} );
131             push( @offspring, $another_one );
132             } elsif ( $selected_op->arity() > 2 ) {
133             for ( my $j = 1; $j < $selected_op->arity(); $j ++ ) {
134             my $chosen = $genitors[ rand( @genitors )];
135             push( @offspring, $chosen->clone() );
136             }
137             }
138             my $mutant = $selected_op->apply( @offspring );
139             my $equal;
140             for my $o (@offspring) {
141             $equal += $o->{'_str'} eq $mutant->{'_str'};
142             }
143             if ( !$equal ) {
144             push( @new_population, $mutant );
145             }
146              
147             }
148             return \@new_population;
149             }
150              
151             =head1 SEE ALSO
152              
153             More or less in the same ballpark, alternatives to this one
154              
155             =over 4
156              
157             =item *
158              
159             L
160              
161             =item *
162              
163             L
164              
165             =back
166              
167             =head1 Copyright
168            
169             This file is released under the GPL. See the LICENSE file included in this distribution,
170             or go to http://www.fsf.org/licenses/gpl.txt
171              
172             CVS Info: $Date: 2012/05/15 11:58:01 $
173             $Header: /cvsroot/opeal/Algorithm-Evolutionary/lib/Algorithm/Evolutionary/Op/Breeder_Diverser.pm,v 1.5 2012/05/15 11:58:01 jmerelo Exp $
174             $Author: jmerelo $
175             $Revision: 1.5 $
176              
177             =cut
178              
179             "The truth is out there";