File Coverage

lib/Algorithm/MasterMind/Evolutionary_Partitions.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             package Algorithm::MasterMind::Evolutionary_Partitions;
2              
3 1     1   868 use warnings;
  1         2  
  1         45  
4 1     1   7 use strict;
  1         2  
  1         45  
5 1     1   5 use Carp;
  1         2  
  1         76  
6              
7 1         6 use lib qw(../../lib ../../../../Algorithm-Evolutionary/lib/
8             ../../Algorithm-Evolutionary/lib/
9 1     1   6 ../../../lib);
  1         1  
10              
11             our $VERSION = sprintf "%d.%03d", q$Revision: 1.6 $ =~ /(\d+)\.(\d+)/g;
12              
13 1     1   390 use base 'Algorithm::MasterMind::Evolutionary';
  1         2  
  1         592  
14              
15             use Algorithm::MasterMind qw(partitions);
16              
17             use Algorithm::Evolutionary::Op::String_Mutation;
18             use Algorithm::Evolutionary::Op::Permutation;
19             use Algorithm::Evolutionary::Op::Crossover;
20             use Algorithm::Evolutionary::Op::Easy;
21             use Algorithm::Evolutionary::Individual::String;
22              
23             # ---------------------------------------------------------------------------
24              
25              
26             sub issue_next {
27             my $self = shift;
28             my $rules = $self->number_of_rules();
29             my @alphabet = @{$self->{'_alphabet'}};
30             my $length = $self->{'_length'};
31             my $pop = $self->{'_pop'};
32             my $ga = $self->{'_ga'};
33             map( $_->evaluate( $self->{'_fitness'}), @$pop );
34             my @ranked_pop = sort { $b->{_fitness} <=> $a->{_fitness}; } @$pop;
35              
36             my %consistent;
37             # print "Consistent in ", scalar keys %{$self->{'_consistent'}}, "\n";
38             if ( $self->{'_consistent'} ) { #Check for consistency
39             %consistent = %{$self->{'_consistent'}};
40             for my $c (keys %consistent ) {
41             my $match = $self->matches( $c );
42             if ( $match->{'matches'} < $rules ) {
43             delete $consistent{$c};
44             }
45             }
46             } else {
47             %consistent = ();
48             }
49             # print "Consistent out ", scalar keys %consistent, "\n";
50            
51             while ( $ranked_pop[0]->{'_matches'} == $rules ) {
52             $consistent{$ranked_pop[0]->{'_str'}} = $ranked_pop[0];
53             shift @ranked_pop;
54             }
55             my $generations_equal = 0;
56             # The 20 was computed in NICSO paper, valid for normal mastermind
57             my $number_of_consistent = keys %consistent;
58            
59             # print "Consistent new ", scalar keys %consistent, "\n";
60             while ( $number_of_consistent < 20 ) {
61             my $this_number_of_consistent = $number_of_consistent;
62             $ga->apply( $pop );
63             for my $p( @$pop ) {
64             my $matches = $self->matches( $p->{'_str'} );
65             # print "* ", $p->{'_str'}, " ", $matches->{'matches'}, "\n";
66             if ( $matches->{'matches'} == $rules ) {
67             # print "Combination ", $p->{'_str'}, " matches ", $p->{'_matches'}, "\n";
68             $consistent{$p->{'_str'}} = $p;
69             }
70             }
71             $number_of_consistent = keys %consistent;
72             if ( $this_number_of_consistent == $number_of_consistent ) {
73             $generations_equal++;
74             } else {
75             $generations_equal = 0;
76             }
77              
78             if ($generations_equal == 15 ) {
79             $ga->reset( $pop );
80             $generations_equal = 0;
81             }
82              
83             # print "G $generations_equal $number_of_consistent \n";
84             last if ( ( $generations_equal >= 3 ) && ( $number_of_consistent >= 1 ) );
85             }
86              
87             # print "After GA combinations ", join( " ", keys %consistent ), "\n";
88             $self->{'_consistent'} = \%consistent;
89             if ( $number_of_consistent > 1 ) {
90             # print "Consistent ", scalar keys %consistent, "\n";
91             #Use whatever we've got to compute number of partitions
92             my $partitions = partitions( keys %consistent );
93            
94             my $max_partitions = 0;
95             my %max_c;
96             for my $c ( keys %$partitions ) {
97             my $this_max = keys %{$partitions->{$c}};
98             $max_c{$c} = $this_max;
99             if ( $this_max > $max_partitions ) {
100             $max_partitions = $this_max;
101             }
102             }
103             # Find all partitions with that max
104             my @max_c = grep( $max_c{$_} == $max_partitions, keys %max_c );
105             # Break ties
106             my $string = $max_c[ rand( @max_c )];
107             # Obtain next
108             return $self->{'_last'} = $string;
109             } else {
110             return $self->{'_last'} = (keys %consistent)[0];
111             }
112            
113             }
114              
115             "some blacks, 0 white"; # Magic true value required at end of module
116              
117             __END__