File Coverage

lib/Algorithm/Evolutionary/Op/GaussianMutation.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1 1     1   15497 use strict;
  1         1  
  1         33  
2 1     1   3 use warnings;
  1         1  
  1         24  
3              
4 1     1   4 use lib qw(../../..);
  1         1  
  1         5  
5              
6             =encoding utf8
7              
8             =head1 NAME
9              
10             Algorithm::Evolutionary::Op::GaussianMutation - Changes numeric chromosome components following the gaussian distribution.
11              
12             =cut
13              
14             =head1 SYNOPSIS
15              
16             my $op = new Algorithm::Evolutionary::Op::GaussianMutation( 0, 0.05) # With average 0, and 0.05 standard deviation
17              
18             =cut
19              
20             =head1 Base Class
21              
22             L
23              
24             =cut
25              
26             =head1 DESCRIPTION
27              
28             Mutation operator for a GA: applies gaussian mutation to a number
29              
30             =cut
31              
32             package Algorithm::Evolutionary::Op::GaussianMutation;
33              
34             our $VERSION = '3.4';
35              
36 1     1   126 use Carp;
  1         1  
  1         103  
37 1     1   548 use Math::Random;
  1         4709  
  1         84  
38 1     1   363 use Clone qw(clone);
  1         394  
  1         53  
39              
40 1     1   6 use base 'Algorithm::Evolutionary::Op::Base';
  1         1  
  1         347  
41              
42             #Class-wide constants
43             our $APPLIESTO = 'Algorithm::Evolutionary::Individual::Vector';
44             our $ARITY = 1;
45              
46             =head2 new( [$average = 0] [, $standard deviation = 1] [, $rate = 1 ]
47              
48             Creates a new mutation operator with an application rate. Rate defaults to 1.
49              
50             =cut
51              
52             sub new {
53             my $class = shift;
54             my $avg = shift || 0;
55             my $stddev = shift || 1;
56             my $rate = shift || 1;
57              
58             my $hash = {avg => $avg,
59             stddev => $stddev };
60             my $self = Algorithm::Evolutionary::Op::Base::new( 'Algorithm::Evolutionary::Op::GaussianMutation', $rate, $hash );
61             return $self;
62             }
63              
64             =head2 create
65              
66             Creates a new mutation operator with an application rate. Rate defaults to 0.1.
67              
68             Called create to distinguish from the classwide ctor, new. It just
69             makes simpler to create a Mutation Operator
70              
71             =cut
72              
73             sub create {
74             my $class = shift;
75             my $avg = shift || 0;
76             my $stddev = shift || 1;
77            
78             my $self = {_avg => $avg,
79             _stddev => $stddev };
80              
81             bless $self, $class;
82             return $self;
83             }
84              
85             =head2 apply( $chromosome )
86              
87             Applies mutation operator to a "Chromosome", a vector of stuff,
88             really. Can be applied only to I with the C<_array> instance
89             variable; but it checks before application (roughly) that both operands are of
90             type L.
91              
92             =cut
93              
94             sub apply ($$) {
95             my $self = shift;
96             my $arg = shift || croak "No victim here!";
97             croak "Incorrect type".(ref $arg) if !$arg->{_array};
98             my $victim = clone($arg);
99             my @deltas = random_normal( @{$victim->{_array}} + 1, #+1 is needed, returns empty if not
100             $self->{_avg}, $self->{_stddev} );
101             for ( @{$victim->{_array}} ) {
102             my $adjust = pop @deltas;
103             $_ += $adjust;
104             # makes sure that the new value stays within its confines
105             if($_ < $victim->{_rangestart}) {
106             $_ = $victim->{_rangestart};
107             } elsif($_ > $victim->{_rangeend}) {
108             $_ = $victim->{_rangeend};
109             }
110             }
111             $victim->{_fitness} = undef;
112             return $victim;
113             }
114              
115             =head1 THANKS
116              
117             This file has been improved with input from Christoph Meißner.
118              
119             =head1 Copyright
120            
121             This file is released under the GPL. See the LICENSE file included in this distribution,
122             or go to http://www.fsf.org/licenses/gpl.txt
123              
124             =cut