File Coverage

blib/lib/AI/Genetic/Defaults.pm
Criterion Covered Total %
statement 15 68 22.0
branch 0 8 0.0
condition n/a
subroutine 5 15 33.3
pod 0 10 0.0
total 20 101 19.8


line stmt bran cond sub pod time code
1              
2             package AI::Genetic::Defaults;
3              
4 1     1   5 use strict;
  1         2  
  1         34  
5 1     1   498 use AI::Genetic::OpSelection;
  1         3  
  1         26  
6 1     1   488 use AI::Genetic::OpCrossover;
  1         3  
  1         28  
7 1     1   470 use AI::Genetic::OpMutation;
  1         2  
  1         625  
8              
9             1;
10              
11             # this implements the default strategies.
12              
13             sub rouletteSinglePoint {
14             # initialize the roulette wheel
15 0     0 0   AI::Genetic::OpSelection::initWheel($_[0]->people);
16              
17 0           push @_ => 'vectorSinglePoint', 'rouletteUnique';
18 0           goto &genericStrategy;
19             }
20              
21             sub rouletteTwoPoint {
22             # initialize the roulette wheel
23 0     0 0   AI::Genetic::OpSelection::initWheel($_[0]->people);
24              
25 0           push @_ => 'vectorTwoPoint', 'rouletteUnique';
26 0           goto &genericStrategy;
27             }
28              
29             sub rouletteUniform {
30             # initialize the roulette wheel
31 0     0 0   AI::Genetic::OpSelection::initWheel($_[0]->people);
32              
33 0           push @_ => 'vectorUniform', 'rouletteUnique';
34 0           goto &genericStrategy;
35             }
36              
37             sub tournamentSinglePoint {
38 0     0 0   push @_ => 'vectorSinglePoint', 'tournament', [$_[0]->people];
39 0           goto &genericStrategy;
40             }
41              
42             sub tournamentTwoPoint {
43 0     0 0   push @_ => 'vectorTwoPoint', 'tournament', [$_[0]->people];
44 0           goto &genericStrategy;
45             }
46              
47             sub tournamentUniform {
48 0     0 0   push @_ => 'vectorUniform', 'tournament', [$_[0]->people];
49 0           goto &genericStrategy;
50             }
51              
52             sub randomSinglePoint {
53 0     0 0   push @_ => 'vectorSinglePoint', 'random', [$_[0]->people];
54 0           goto &genericStrategy;
55             }
56              
57             sub randomTwoPoint {
58 0     0 0   push @_ => 'vectorTwoPoint', 'random', [$_[0]->people];
59 0           goto &genericStrategy;
60             }
61              
62             sub randomUniform {
63 0     0 0   push @_ => 'vectorUniform', 'random', [$_[0]->people];
64 0           goto &genericStrategy;
65             }
66              
67             # generic sub that implements everything.
68             sub genericStrategy {
69 0     0 0   my ($ga, $Xop, $selOp, $selArgs) = @_;
70              
71             #perhaps args should be:
72             # ($ga, [xop, xargs], [selop, selargs]) ?
73              
74 0           my $pop = $ga->people;
75              
76             # now double up the individuals, and get top half.
77 0           my $size = $ga->size;
78 0           my $ind = $ga->indType;
79              
80 0           my @newPop;
81              
82             # optimize
83 0           my $crossProb = $ga->crossProb;
84              
85             # figure out mutation routine to use, and its arguments.
86 0           my @mutArgs = ($ga->mutProb);
87 0           my $mutOp = 'bitVector';
88 0 0         if ($ind =~ /IndRangeVector/) {
    0          
89 0           $mutOp = 'rangeVector';
90 0           push @mutArgs => $pop->[0]->ranges;
91             } elsif ($ind =~ /IndListVector/) {
92 0           $mutOp = 'listVector';
93 0           push @mutArgs => $pop->[0]->lists;
94             }
95              
96 0           my ($ssub, $xsub, $msub);
97             {
98 1     1   6 no strict 'refs';
  1         2  
  1         311  
  0            
99 0           $ssub = \&{"AI::Genetic::OpSelection::$selOp"};
  0            
100 0           $xsub = \&{"AI::Genetic::OpCrossover::$Xop"};
  0            
101 0           $msub = \&{"AI::Genetic::OpMutation::$mutOp"};
  0            
102             }
103              
104 0           for my $i (1 .. $size/2) {
105 0           my @parents = $ssub->(@$selArgs);
106 0 0         @parents < 2 and push @parents => $ssub->(@$selArgs);
107              
108 0           my @cgenes = $xsub->($crossProb, map scalar $_->genes, @parents);
109              
110             # check if two didn't mate.
111 0 0         unless (ref $cgenes[0]) {
112 0           @cgenes = map scalar $_->genes, @parents;
113             }
114              
115             # mutate them.
116 0           $_ = $msub->(@mutArgs, $_) for @cgenes;
117              
118             # push them into pop.
119 0           push @newPop => map $pop->[0]->new($_), @cgenes;
120             }
121              
122             # assign the fitness function. This is UGLY.
123 0           my $fit = $pop->[0]->fitness;
124 0           $_->fitness($fit) for @newPop;
125              
126             # now chop in half and reassign the population.
127 0           $ga->people(AI::Genetic::OpSelection::topN([@$pop, @newPop], $size));
128             }