unit opt_genetico;

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

interface

uses
  Classes, SysUtils,
  uplan,
  dbPlanesPrueba,
  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_selPadre(NIndividuos: integer; criterio: integer ): 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;

begin

//obs: lo que viene a continuacion se puede resumir poniendo NIndividuos:=Poblacion_Count();
NIndividuos:= dbPlanesPrueba.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_selPadre(NIndividuos, criterio);
  if ( random > 0.001 ) then // factor de innovación
  begin
    papa := Poblacion_selPadre(NIndividuos, criterio);
    a    := mezclar(mama, papa);
    while random > 0.3 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_selPadre(NIndividuos: integer; criterio: integer ): TPlan;
var
  k:      integer;
  ds:     TDAOfTPlanPrueba;
  rp:     TPlan;
begin

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

  //ordena según criterio = 0
  ds := dbPlanesPrueba.returnOrdList(NIndividuos, criterio);
  rp := ds[k];

  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.

