File Coverage

blib/lib/AI/Genetic/Pro/Selection/Roulette.pm
Criterion Covered Total %
statement 40 40 100.0
branch 10 12 83.3
condition 1 2 50.0
subroutine 7 7 100.0
pod 0 2 0.0
total 58 63 92.0


line stmt bran cond sub pod time code
1             package AI::Genetic::Pro::Selection::Roulette;
2              
3 10     10   62 use warnings;
  10         20  
  10         456  
4 10     10   54 use strict;
  10         22  
  10         443  
5             #use Data::Dumper; $Data::Dumper::Sortkeys = 1;
6 10     10   57 use List::Util qw(sum min);
  10         23  
  10         979  
7 10     10   72 use List::MoreUtils qw(first_index);
  10         16  
  10         526  
8 10     10   55 use Carp 'croak';
  10         23  
  10         18137  
9              
10             #=======================================================================
11 10     10 0 89 sub new { bless \$_[0], $_[0]; }
12             #=======================================================================
13             sub run {
14 16     16 0 47 my ($self, $ga) = @_;
15            
16 16         65 my ($fitness) = ($ga->_fitness);
17 16         29 my (@parents, @elders);
18             #-------------------------------------------------------------------
19 16         31 my $count = $#{$ga->chromosomes};
  16         69  
20 16         1754 my $const = min values %$fitness;
21 16 100       81 $const = $const < 0 ? abs($const) : 0;
22 16 100       687 my $total = sum( map { $_ < 0 ? $_ + $const : $_ } values %$fitness);
  12948         41304  
23 16   50     382 $total ||= 1;
24            
25             # elders
26 16         69 for my $idx (0..$count){
27 12948         51326 push @elders, $idx for 1..int((($fitness->{$idx} + $const) / $total) * $count);
28             }
29            
30 16 100       126 if((my $add = $count - scalar @elders) > 0){
31 11         99 my $idx = $elders[rand @elders];
32 11         877 push @elders, int rand($count) for 0..$add;
33             }
34            
35 16 50       174 croak "You must set a crossover probability to use the Roulette strategy"
36             unless defined($ga->crossover);
37 16 50       119 croak "You must set a number of parents to use the Roulette strategy"
38             unless defined($ga->parents);
39              
40             # parents
41 16         48 for(0..$count){
42 12948 100       36511 if(rand > $ga->crossover){
43 1287         4142 push @parents, pack 'I*', $elders[ rand @elders ]
44             }else{
45 11661         12578 my @group;
46 11661         61880 push @group, $elders[ rand @elders ] for 1..$ga->parents;
47 11661         35492 push @parents, pack 'I*', @group;
48             }
49             }
50              
51             #-------------------------------------------------------------------
52 16         1515 return \@parents;
53             }
54             #=======================================================================
55              
56             1;