File Coverage

blib/lib/AI/Genetic/OpSelection.pm
Criterion Covered Total %
statement 3 56 5.3
branch 0 6 0.0
condition 0 16 0.0
subroutine 1 7 14.2
pod 6 6 100.0
total 10 91 10.9


line stmt bran cond sub pod time code
1              
2             package AI::Genetic::OpSelection;
3              
4 1     1   4 use strict;
  1         2  
  1         634  
5              
6             my @wheel;
7             my $wheelPop;
8              
9             # sub init():
10             # initializes the roulette wheel array.
11             # must be called whenever the population changes.
12             # only useful for roulette().
13              
14             sub initWheel {
15 0     0 1   my $pop = shift;
16              
17 0           my $tot = 0;
18 0           $tot += $_->score for @$pop;
19              
20             # if all population has zero score, then none
21             # deserves to be selected.
22 0 0         $tot = 1 unless $tot; # to avoid div by zero
23              
24             # normalize
25 0           my @norms = map {$_->score / $tot} @$pop;
  0            
26              
27 0           @wheel = ();
28              
29 0           my $cur = 0;
30 0           for my $i (@norms) {
31 0           push @wheel => [$cur, $cur + $i];
32 0           $cur += $i;
33             }
34              
35 0           $wheelPop = $pop;
36             }
37              
38             # sub roulette():
39             # Roulette Wheel selection.
40             # argument is number of individuals to select (def = 2).
41             # returns selected individuals.
42              
43             sub roulette {
44 0   0 0 1   my $num = shift || 2;
45              
46 0           my @selected;
47              
48 0           for my $j (1 .. $num) {
49 0           my $rand = rand;
50 0           for my $i (0 .. $#wheel) {
51 0 0 0       if ($wheel[$i][0] <= $rand && $rand < $wheel[$i][1]) {
52 0           push @selected => $wheelPop->[$i];
53 0           last;
54             }
55             }
56             }
57              
58 0           return @selected;
59             }
60              
61             # same as roulette(), but returns unique individuals.
62             sub rouletteUnique {
63 0   0 0 1   my $num = shift || 2;
64              
65             # make sure we select unique individuals.
66 0           my %selected;
67              
68 0           while ($num > keys %selected) {
69 0           my $rand = rand;
70              
71 0           for my $i (0 .. $#wheel) {
72 0 0 0       if ($wheel[$i][0] <= $rand && $rand < $wheel[$i][1]) {
73 0           $selected{$i} = 1;
74 0           last;
75             }
76             }
77             }
78              
79 0           return map $wheelPop->[$_], keys %selected;
80             }
81              
82             # sub tournament():
83             # arguments are anon list of population, and number
84             # of individuals in tournament (def = 2).
85             # return 1 individual.
86              
87             sub tournament {
88 0     0 1   my ($pop, $num) = @_;
89              
90 0   0       $num ||= 2;
91              
92 0           my %s;
93 0           while ($num > keys %s) {
94 0           my $i = int rand @$pop;
95 0           $s{$i} = 1;
96             }
97              
98 0           return (sort {$b->score <=> $a->score}
  0            
99 0           map {$_->score; $_} # This avoids a bug in Perl. See Genetic.pm.
  0            
100             map $pop->[$_], keys %s)[0];
101             }
102              
103             # sub random():
104             # pure random choice of individuals.
105             # arguments are anon list of population, and number
106             # of individuals to select (def = 1).
107             # returns selected individual(s).
108              
109             sub random {
110 0     0 1   my ($pop, $num) = @_;
111              
112 0   0       $num ||= 1;
113              
114 0           my %s;
115 0           while ($num > keys %s) {
116 0           my $i = int rand @$pop;
117 0           $s{$i} = 1;
118             }
119              
120 0           return map $pop->[$_], keys %s;
121             }
122              
123             # sub topN():
124             # fittest N individuals.
125             # arguments are anon list of pop, and N (def = 1).
126             # return anon list of top N individuals.
127              
128             sub topN {
129 0     0 1   my ($pop, $N) = @_;
130              
131 0   0       $N ||= 1;
132              
133             # hmm .. are inputs already sorted?
134 0           return [(sort {$b->score <=> $a->score}
  0            
135 0           map {$_->score; $_} # This avoids a bug in Perl. See Genetic.pm.
  0            
136             @$pop)[0 .. $N-1]];
137             }
138              
139             1;
140              
141             __END__