lunes, 26 de mayo de 2008

Séptimo ejercicio

En este ejercicio utilizaremos el paquete de perl Algorithm::Evolutionary para implementar un algoritmo genético para minimizar la función de Griewank. En este caso usaremos codificación real para los cromosomas.

use Algorithm::Evolutionary::Individual::Vector;
use Algorithm::Evolutionary::Op::Easy;
use Algorithm::Evolutionary::Op::GaussianMutation;
use Algorithm::Evolutionary::Op::VectorCrossover;

# Definición de la función de Griewank:
# -------------------------------------
# f(x) = 1/4000*sum(xi^2) - prod(cos(xi)/sqrt(i)) + 1
#
# -600 <= x(i) <= 600
# i = 1..n (n = número de dimensiones del problema)
#
# Mínimo global: f(x) = 0 se alcanza con x = (0, ..., 0)
#

# Función de Griewank
my $funcionGriewank = sub {
# Cogemos el individuo a evaluar
my $chrom = shift;
# Extraemos el vector
my @x = @{$chrom->{_array}};

# Calculamos la función
my $suma = 0;
my $prod = 1;
for (my $i=0;$i<=$#x;$i++){
$suma += $x[$i]**2;
$prod *= cos($x[$i]/sqrt($i+1));
}
$suma = $suma/4000;
my $fitness = $suma-$prod+1;

return $fitness;
};

# Parámetros del algoritmo
my $popSize = 100; # Tamaño de la población
my $numGens = 100; # Número de generaciones
my $dimensiones = 2; # Número de dimensiones del problema
# y, por lo tanto, número de cromosomas

# Creación de la población inicial
my @pop;
for ( 0..$popSize ) {
# Los genes tomarán valores entre -600 y 600
my $indi = Algorithm::Evolutionary::Individual::Vector->
new( $dimensiones, -600, 600 );
push( @pop, $indi );
}

# Inicializamos el fitnes de la población inicial
for ( @pop ) {
if ( !defined $_->Fitness() ) {
my $fitness = $funcionGriewank->($_);
$_->Fitness( $fitness );
}
}

# Definición de los operadores genéticos
my $mutacion = Algorithm::Evolutionary::Op::GaussianMutation->
new( 0, 0.1 );
my $cruce = Algorithm::Evolutionary::Op::VectorCrossover->
new(2);

# Elección del algoritmo
my $generation = Algorithm::Evolutionary::Op::Easy->
new( $funcionGriewank , 0.2 , [$mutacion, $cruce] ) ;

# Bucle general del algoritmo
do {
$generation->apply( \@pop );
print "$numGens : ", $pop[0]->asString(), "\n" ;
$numGens--;
} while( $numGens > 0 );

# Mejor individuo encontrado
print "\nLa mejor solución encontrada es:\n\t ";
print $pop[0]->asString(),"\n";

No hay comentarios: