martes, 13 de mayo de 2008

Ejercicio 5: Algoritmo genético

En este ejercicio hemos programado un algoritmo genético con números reales que utiliza la función Griewank como función de fitness. El código es el siguiente:

#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 fitnes, que es la función Griewank: f(x) = 1/4000*sum(xi-100)^2 - prod((xi-100)/sqrt(i)) + 1

my $funcionGriewank = sub {

my $indice = shift;
my @x = @{$indice->{_array}};
my $nComp = $#x; #número de componentes del array x

my $suma = 0;
my $producto = 1;
for (my $j = 1; $j<=$nComp; $j++){
$suma = $suma + $x[$j-1]^2;
$producto = $producto * cos($x[$j-1]/sqrt($j));
}

my $f = $suma/4000 - $producto + 1;
return -1*$f; #pasamos el resultado a negativo para que el objetivo sea maximizar la función de fitness

};


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

#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 $m = Algorithm::Evolutionary::Op::GaussianMutation->new(0, 0.1); #mutación
my $c = Algorithm::Evolutionary::Op::VectorCrossover->new(2); #cruce


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

# 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( $funcionGriewank , 0.2 , [$m, $c] ) ;


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

#Evaluamos la población inicial
for ( @pop ) {
if ( !defined $_->Fitness() ) {
my $fitness = $funcionGriewank->($_);
$_->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() ;

Y el resultado de la ejecución del programa se muestra en la siguiente imagen:

No hay comentarios: