File Coverage

lib/Algorithm/MasterMind/Evolutionary_MO.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Algorithm::MasterMind::Evolutionary_MO;
2              
3 1     1   913 use warnings;
  1         2  
  1         44  
4 1     1   9 use strict;
  1         4  
  1         49  
5 1     1   7 use Carp;
  1         1  
  1         73  
6              
7 1     1   6 use lib qw(../../lib ../../../../Algorithm-Evolutionary/lib/ ../../Algorithm-Evolutionary/lib/);
  1         1  
  1         7  
8              
9             our $VERSION = sprintf "%d.%03d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/g;
10              
11 1     1   312 use base 'Algorithm::MasterMind';
  1         2  
  1         115  
12              
13 1     1   6 use Algorithm::MasterMind qw(entropy);
  1         1  
  1         48  
14              
15 1     1   565 use Algorithm::Evolutionary::Op::String_Mutation;
  0            
  0            
16             # use Algorithm::Evolutionary::Op::Permutation;
17             use Algorithm::Evolutionary::Op::Crossover;
18             use Algorithm::Evolutionary::Op::Easy_MO;
19             use Algorithm::Evolutionary::Individual::String;
20              
21             # ---------------------------------------------------------------------------
22              
23             sub fitness {
24             my $self = shift;
25             my $object = shift;
26             my $combination = $object->{'_str'};
27             my $matches = $self->matches( $combination );
28             $object->{'_matches'} = $matches->{'matches'};
29             my $fitness = 0;
30             my @rules = @{$self->{'_rules'}};
31             my $rules_string = $combination;
32             for ( my $r = 0; $r <= $#rules; $r++) {
33             $rules_string .= $rules[$r]->{'combination'};
34             $fitness += abs( $rules[$r]->{'blacks'} - $matches->{'result'}->[$r]->{'blacks'} ) +
35             abs( $rules[$r]->{'whites'} - $matches->{'result'}->[$r]->{'whites'} );
36             }
37            
38             return [ $fitness, entropy($rules_string)];
39             }
40              
41              
42             sub initialize {
43             my $self = shift;
44             my $options = shift;
45             for my $o ( keys %$options ) {
46             $self->{"_$o"} = $options->{$o};
47             }
48              
49             # Variation operators
50             my $m = new Algorithm::Evolutionary::Op::String_Mutation; # Rate = 1
51             # my $p = new Algorithm::Evolutionary::Op::Permutation; # Rate = 1
52             my $c = Algorithm::Evolutionary::Op::Crossover->new(2, 8 ); # Rate = 4
53              
54             my $fitness = sub { $self->fitness(@_) };
55             my $moga = new Algorithm::Evolutionary::Op::Easy_MO( $fitness,
56             $options->{'replacement_rate'},
57             [ $m, $c] );
58             $self->{'_fitness'} = $fitness;
59             $self->{'_moga'} = $moga;
60              
61            
62              
63             }
64              
65             sub issue_first {
66             my $self = shift;
67              
68             #Initialize population for next step
69             my @pop;
70             for ( 0.. ($self->{'_pop_size'}-1) ) {
71             my $indi = Algorithm::Evolutionary::Individual::String->new( $self->{'_alphabet'},
72             $self->{'_length'} );
73             push( @pop, $indi );
74             }
75            
76             $self->{'_pop'}= \@pop;
77            
78             return $self->{'_last'} = $self->issue_first_Knuth();;
79             }
80              
81             sub issue_next {
82             my $self = shift;
83             my $rules = $self->number_of_rules();
84             my @alphabet = @{$self->{'_alphabet'}};
85             my $length = $self->{'_length'};
86             my $pop = $self->{'_pop'};
87             my $moga = $self->{'_moga'};
88             map( $_->evaluate( $self->{'_fitness'}), @$pop );
89             my @ranked_pop = sort { $a->{_fitness}[0] <=> $b->{_fitness}[0]; } @$pop;
90              
91             if ( $ranked_pop[0]->{'_matches'} == $rules ) { #Already found!
92             return $self->{'_last'} = $ranked_pop[0]->{'_str'};
93             } else {
94             my @pop_by_matches;
95             my $best;
96             do {
97             $moga->apply( $pop );
98             # print "Población ", scalar @$pop, "\n";
99             map( $_->{'_matches'} = $_->{'_matches'}?$_->{'_matches'}:-1, @$pop ); #To avoid warnings
100             @pop_by_matches = sort { $b->{'_matches'} <=> $a->{'_matches'} } @$pop;
101             $best = $pop_by_matches[0];
102             } while ( $best->{'_matches'} < $rules );
103             return $self->{'_last'} = $best->{'_str'};
104             }
105              
106             }
107              
108             "some blacks, 0 white"; # Magic true value required at end of module
109              
110             __END__