viernes, 23 de mayo de 2008

Ejercicio 6

En el siguiente código se muestra el algoritmo genético en que los cromosomas son representados con número reales en lugar de binarios, usando para el fitness la función de Griewank


#!/usr/bin/perl

use warnings;
use strict;

#Incluimos los elementos de la librería necesarios
use Algorithm::Evolutionary::Individual::Vector;
use Algorithm::Evolutionary::Op::Easy;
use Algorithm::Evolutionary::Op::GaussianMutation;
use Algorithm::Evolutionary::Op::VectorCrossover;

#----------------------------------------------------------#
#leemos los parámetros de la línea de comandos
my $popSize = shift || 100;
my $numGens = shift || 100 ;

#----------------------------------------------------------#
#Definimos la función de fitness,
que es la función Griewank


my $funcion_griewank = sub {

my $indi = shift;

my @cr = @{$indi->{_array}};
my $fr=4000;

my $sum;

my $prod=1;
for(my $i=1; $i<=$#cr; $i++){

$sum+=$cr[$i-1]^2;
$prod*=cos($cr[$i-1]/sqrt($i));

}

return -$sum/$fr + $prod-1;

#Using n==2
#my ($x, $y) = @{$indi->{_array}};
#return ($x*$x+$y*$y)/$fr
#-(cos($x)+ cos($y)/sqrt(2));


};

#----------------------------------------------------------#

#Creamos la población inicial con $popSize
individuos

my @pop;
for ( 0..$popSize ) {

my $indi = Algorithm::Evolutionary
::Individual::Vector->new( 2 );

push( @pop, $indi );
}

#----------------------------------------------------------#
#Definimos los operadores de variación

my $mut_operator = Algorithm::Evolutionary::Op::
GaussianMutation->new( 0, 0.1 );

my $cross_operator = Algorithm::Evolutionary::Op::
VectorCrossover->new(2);

#----------------------------------------------------------#

# Usamos estos operadores para definir una
# generación del algoritmo. Lo cual
# no es realmente necesario ya que este algoritmo
# define ambos operadores por
# defecto. Los parámetros son la función de
# fitness, la tasa de selección y
# los operadores de variación.

my $generation = Algorithm::Evolutionary::Op
::Easy->new( $funcion_griewank,
0.2 , [$mut_operator, $cross_operator] ) ;

#----------------------------------------------------------#
#Evaluamos la población inicial
for( @pop ){
if ( !defined $_->Fitness() ) {

my $fitness = $funcion_griewank->($_);
$_->Fitness( $fitness );

}
}

#Bucle del algoritmo evolutivo
my $contador=0;
do {

$generation->apply( \@pop );
print "$contador : ", $pop[0]->asString(),
"\n" ;

$contador++;
} while( $contador < $numGens );

#----------------------------------------------------------#
#Tomamos la mejor solución encontrada y la mostramos
my ( $x, $y ) = @{$pop[0]->{_array}};

print "El mejor es:\n\t ";
print $pop[0]->asString() ;
print "\n\t x=$x \n\t y=$y \n\t Fitness: ";

print $pop[0]->Fitness() ;


Lo único a destacar es que yo la había hecho para sólo dos elementos, pero al ver que todo el mundo la ha generalizado, pues no iba yo a ser menos ...

En fin, en el siguiente enlace está la captura de pantalla que demuestra que el algoritmo funciona

No hay comentarios: