
function Generation ( pop_size, elite, operadores ) {
  if (elite > pop_size) {
    return;
  }
  this.pop_size = pop_size;
  this.elite = elite;
  this.operadores = operadores;

  // funciones
  this.reproduce = reproduce;
  this.apply = gen_apply;

}


function compare_fitness(x, y)
{
  if (x.fitness > y.fitness)
    return -1;
  else if (x.fitness == y.fitness)
    return 0;
  else
    return 1; 
}      
   
function gen_apply( pop, fitness ) {
  // primero, calcular el fitness
  for ( var i = 0; i < pop.length; i++ ) {
    if ( pop[i].fitness == null ) {
      pop[i].fitness = fitness( pop[i] );
    }
  }
  // Poner por orden
  //  print( "Mejor pre " + pop[0].fitness + " " + pop[0].chromosome );
  pop.sort( compare_fitness );
  //   print( "Mejor pos " + pop[0].fitness + " " + pop[0].chromosome );
  var elite_pop= pop.slice( 0, this.pop_size - this.elite );
  var new_pop = reproduce( elite_pop, this.pop_size-elite_pop.length, this.operadores );
  for ( i = 0; i < new_pop.length; i ++ ) {
    elite_pop.push( new_pop[i] );
  }
  return elite_pop;
}


function reproduce ( elite_pop, pop_size, operadores ) {
  var pool = new Array();
  var total_rate=0;
  for ( var i = 0; i < operadores.length; i ++ ) {
    total_rate += operadores[i].rate;
  }
  var elite_size = elite_pop.length;
  for ( i = 0; i < operadores.length; i ++ ) {
    var generados = (pop_size * operadores[i].rate )/total_rate;
    for ( var j = 0; (j < generados) && (pool.length < pop_size); j ++ ) {
      var new_guy;
      var this_guy = elite_pop[ Math.floor( Math.random()*elite_size) ];
      var other_guy;
      if ( operadores[i].arity == 2 ) {
	other_guy = elite_pop[  Math.floor(Math.random()*elite_size) ];
	new_guy = operadores[i].apply(this_guy, other_guy);
      } else {
	new_guy = operadores[i].apply(this_guy);
      }
      pool.push( new_guy );
    }
  }
  // Por si falta alguno
  for ( i = pool.length; i < pop_size; i ++ ) {
    pool.push( elite_pop[Math.floor( Math.random()*elite_size)].clone() );
  }
  return pool;
  
}

