unit opt_geneticoreductor;

{$MACRO ON}
//define el plan particular
{$define uplan := uplanreductor}
{$define TPlan := TPlanReductor}
{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils,
  uplan,
  dbPlanesPruebareductor,
  uauxiliares,
  xMatDefs, Math;

//genera un nuevo individuo a través de una mezcla o de una mutación
function Aparear: TPlan;
//devuelve un plan padre
function Poblacion_selPadres(NIndividuos: integer; criterio: integer; Madre: TPlan ): TPlan;
//devuelve un plan bebé mezclando papá y mamá
function mezclar(mama, papa: TPlan): TPlan;
implementation

function Aparear: TPlan;
var
  k: integer;
  papa, mama: TPlan;
  a: TPlan;
  NIndividuos: integer;
  criterio: integer;
  factorDeInnovacion : NReal;
  factorMutacion : NReal;
begin

//obs: lo que viene a continuacion se puede resumir poniendo NIndividuos:=Poblacion_Count();
NIndividuos:= dbPlanesPruebaReductor.Poblacion_count;

(**
// implementamos cuatro criterios de búsqueda simultáneos
  if random < 0.5 then
    if random < 0.5 then
      criterio:= 0
    else
      criterio:= 1
  else
    if random < 0.5 then
      criterio:= 2
    else
      criterio:= 3;
*)
  criterio := 0; // optimizamos en valor esperado.

  mama := Poblacion_selPadres(NIndividuos, criterio, nil );
  factorDeInnovacion := 1 - 0.001;
  if ( random < factorDeInnovacion ) then // factor de innovación
  begin
    papa := Poblacion_selPadres(NIndividuos, criterio, mama );
    a    := mezclar(mama, papa);

    factorMutacion := 1 - 0.3;
    while (random < factorMutacion) do  // factor de mutación
      a.mutar;
    //papa.Free;
    //mama.Free;

    Result:= a;

  end
  else
  begin  // (1- factorDeInovacion ) = "repeticion asegurada"
    mama.raza := 43366;           //indica que proviene del algoritmo genetico
    Result := mama;
  end;
end;

function Poblacion_selPadres(NIndividuos: integer; criterio: integer; Madre: TPlan ): TPlan;
var
  k, j:      integer;
  ds:     TDAOfTPlanPrueba;
  rp:     TPlan;
  dif: TDAOfNreal;
  idxs: TDAOfNInt;
begin

  k := 0;
  while (random > 0.93) and (k < (NIndividuos - 1)) do Inc(k);

  //ordena según criterio = 0
  ds := dbPlanesPruebaReductor.returnOrdList( NIndividuos, criterio);

  if ( Madre = nil ) then
  begin
    k := 0;
    while (random > 0.93) and (k < (NIndividuos - 1)) do Inc(k);
    rp := ds[k];
  end
  else
  begin
    setlength( dif, NIndividuos );
    setlength( idxs, NIndividuos );
    for j:= 0 to High( dif ) do
    begin
       dif[j]:= Madre.diferencia( ds[j] );
       idxs[j]:= j;
    end;

    QuickSort_Creciente(dif, idxs );
    k := 0;
    while (random > 0.93) and (k < (NIndividuos - 1)) do Inc(k);
    rp := ds[idxs[k]];
    setlength( dif, 0 );
    setlength( idxs, 0 );

  end;


  Result := rp;
end;

function mezclar(mama, papa: TPlan): TPlan;
begin
  Result := uplanreductor.mezclar(mama, papa);
end;

 (* //uplanprueba !!!
function mezclar(mama, papa: TPlan): TPlan;
var
  k:      integer;
  bebe:   TPlan;
  fp, fm: TDAOfNInt;
begin

  Result := uplanreductor.mezclar(mama, papa);

  bebe := TPlan.Create;


  for k:= 0 to length(bebe.adn)-1 do
      if random < 0.5 then
         bebe.adn[k] := papa.adn[k]
      else
          bebe.adn[k] := mama.adn[k];
  bebe.raza:=43366; //indica que este plan provino de la raza genetica
  Result := bebe;
end;
*)

end.

