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   6 use strict;
  1         2  
  1         36  
2 1     1   6 use warnings;
  1         1  
  1         66  
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   5 use lib qw(../../..);
  1         2  
  1         5  
60              
61             our ($VERSION) = ( '$Revision: 1.7 $ ' =~ / (\d+\.\d+)/ ) ;
62              
63 1     1   177 use Carp;
  1         2  
  1         65  
64              
65 1     1   6 use base 'Algorithm::Evolutionary::Op::Base';
  1         2  
  1         85  
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. Checks that the
98             offspring is different from parents before inserting it.
99              
100             =cut
101              
102             sub apply ($) {
103             my $self = shift;
104             my $pop = shift || croak "No population here";
105             my $output_size = shift || @$pop; # Defaults to pop size
106             my @ops = @{$self->{_ops}};
107              
108             #Select for breeding
109             my $selector = $self->{_selector};
110             my @genitors = $selector->apply( $pop );
111              
112             #Reproduce
113             my $totRate = 0;
114             my @rates;
115             for ( @ops ) {
116             push( @rates, $_->{rate});
117             }
118             my $op_wheel = new Algorithm::Evolutionary::Wheel @rates;
119              
120             my @new_population;
121             my $i = 0;
122             while ( @new_population < $output_size ) {
123             my @offspring;
124             my $selected_op = $ops[ $op_wheel->spin()];
125             my $chosen = $genitors[ $i++ % @genitors]; #Chosen in turn
126             push( @offspring, $chosen->clone() );
127             if( $selected_op->{'_arity'} == 2 ) {
128             my $another_one;
129             do {
130             $another_one = $genitors[ rand( @genitors )];
131             } until ( $another_one->{'_str'} ne $chosen->{'_str'} );
132             push( @offspring, $another_one );
133             } elsif ( $selected_op->{'_arity'} > 2 ) {
134             for ( my $j = 1; $j < $selected_op->arity(); $j ++ ) {
135             my $chosen = $genitors[ rand( @genitors )];
136             push( @offspring, $chosen->clone() );
137             }
138             }
139             my $mutant = $selected_op->apply( @offspring );
140             my $equal;
141             for my $o (@offspring) {
142             $equal += $o->{'_str'} eq $mutant->{'_str'};
143             }
144             if ( !$equal ) {
145             push( @new_population, $mutant );
146             }
147              
148             }
149             return \@new_population;
150             }
151              
152             =head1 SEE ALSO
153              
154             More or less in the same ballpark, alternatives to this one
155              
156             =over 4
157              
158             =item *
159              
160             L
161              
162             =item *
163              
164             L
165              
166             =back
167              
168             =head1 Copyright
169            
170             This file is released under the GPL. See the LICENSE file included in this distribution,
171             or go to http://www.fsf.org/licenses/gpl.txt
172              
173             CVS Info: $Date: 2013/01/07 13:54:20 $
174             $Header: /media/Backup/Repos/opeal/opeal/Algorithm-Evolutionary/lib/Algorithm/Evolutionary/Op/Breeder_Diverser.pm,v 1.7 2013/01/07 13:54:20 jmerelo Exp $
175             $Author: jmerelo $
176             $Revision: 1.7 $
177              
178             =cut
179              
180             "The truth is out there";