unit umodelos;
{
En esta unidad se define la clase TModelo. El proposito es dar un marco para
poder cargar y evaluar una relacion de entre dos conjuntos de series temporales
compatible con el formato de la clase TSeriesDeDatos

}
{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, useriestemporales,xmatdefs,matreal,MatEnt,urosx,
  uConstantesSimSEE,uoddface_nn1,uoddface,upgsql,ucentral_data;


type

  { TModelo }

  TModelo = class
    cntParams,cntParamsR,cntParamsN:integer; // cantidad de parametros, reales y enteros
    cntEntradas,cntEntradasR,cntEntradasN,cntSalidas,cntSalidasR,cntSalidasN:integer; // cantidad de entradas
    series:TSeriesDeDatos; // series que definen la relacion
    entradasR,salidasR:TDAOfVectR; // entradas y salidas reales
    entradasN,salidasN:TDAOfVectE; // entradas y salidas enteras
    entradasRCalculadas,salidasRCalculadas:TDAOfVectR; // entradas y salidas reales calculadas
    entradasNCalculadas,salidasNCalculadas:TDAOfVectE; // entradas y salidas enteras calculadas
    datosNoValidos:TStringList; // datos para los cuales no se evalua

    constructor Create(xSeries:TSeriesDeDatos;xDatosNoValidos:TStringList);


    // salidasCalculadas <--- f(entradas) donde f es el modelo
    procedure evaluarModelo();
    procedure evaluarMuestra(kMuestra:integer);
    procedure cambiarSeries(xSeries:TSeriesDeDatos);virtual;
    function calcularErrorMedio:NReal;
    function calcularErrorCuadraticoMedio:NReal;
    procedure writeResultadosToArchi(archiString:string);

  end;

  { TModeloRedesNeuronales }

  TModeloRedesNeuronales = class(TModelo)

    problema:TEntrenarRedNeuronal_Problema;
    constructor CreateFromProblemaOddface(nidProblema, idEjecutor: integer;
      dbpq: TDBrosxCon;xDatosNoValidos:TStringList);

    function getModeloViejo(nidCentral: integer; dbpq: TPgSqlConn;
      xSeries: TSeriesDeDatos; out seriesModeloViejo: TSeriesDeDatos): NReal;
    procedure cambiarSeries(xSeries:TSeriesDeDatos);override;
  end;




implementation

{ TModeloRedesNeuronales }

constructor TModeloRedesNeuronales.CreateFromProblemaOddface(nidProblema,
  idEjecutor: integer; dbpq: TDBrosxCon; xDatosNoValidos: TStringList);
var
  sql,ADN,tmp_rundir:string;
  ds:TResultadoQuery;
  nidIndividuo:integer;
  individuo:TIndividuo;
begin
  datosNoValidos:=xDatosNoValidos;
  // Elijo el mejor individuo del problema

  sql:='SELECT ADN, nid FROM ofe_individuos_' + IntToStr(nidProblema) + ' ORDER BY ' +
    'f_objetivo LIMIT 1';
  ds:=dbpq.Query(sql);

  ADN:=ds.FieldByName('ADN').AsString;
  nidIndividuo:=ds.FieldByName('nid').AsInteger();

  // Creo el problema

  tmp_rundir := CrearDirectorioTemporal(getDefault_tmp_base,IntToStr(idEjecutor));
  if tmp_rundir <> '' then
    limpiarCarpeta(tmp_rundir, '*.*');
  writeln('Cambiando el directorio a : ', tmp_rundir);
  chdir(tmp_rundir);

  problema:=TEntrenarRedNeuronal_Problema.CreateFromDB(dbpq,nidProblema,
    idEjecutor,tmp_rundir);

  problema.nidIndividuo:=nidIndividuo;

  individuo:=TIndividuo.CreateFromADN_HexStr(dbpq,problema,ADN);

  problema.decodificar_adn(individuo);

  problema.cerebro.SetParametros(Individuo.XR);

end;

function TModeloRedesNeuronales.getModeloViejo(nidCentral: integer;
  dbpq: TPgSqlConn; xSeries: TSeriesDeDatos; out seriesModeloViejo:TSeriesDeDatos
  ): NReal;
var
  sql:string;
  ds:TSQLQuery;
  tipo,nMuestrasValidas, kMuestra,NMuestras:integer;
  a, alfa, vm:NReal; // solo tiene sentido si es eolica
  potenciaAutorizada:NReal;
  centralBoba :TCentralGeneradora;
  potUnDispSinRes, vel, ro, rad, temp:TVectR;
  modeloViejo, error, error2:TVectR;

begin

  series:=xSeries;
  potUnDispSinRes:=series.GetSerie(6);
  vel:=series.GetSerie(0);
  ro:=series.GetSerie(4);
  rad:=series.GetSerie(3);
  temp:=series.GetSerie(5);

  NMuestras:=series.NPuntos;

  modeloViejo:=TVectR.Create_Init(NMuestras);
  error:=TVectR.Create_Init(NMuestras);
  error2:=TVectR.Create_Init(NMuestras);

  sql:='SELECT tipo, potencia_autorizada_mw FROM centrales WHERE nid = ' + IntToStr(nidCentral);
  ds:=dbpq.Query(sql);
  tipo:=ds.FieldByName('tipo').AsInteger();
  potenciaAutorizada := ds.FieldByName('potencia_autorizada_mw').AsFloat();

  case tipo of
    0: // Eolica
    begin
      // a, alfa, vm, coso
      sql:= 'SELECT * FROM parametros_curvas_pronos WHERE nidcentral = ' +
        IntToStr(nidCentral) + ' ORDER BY dt desc LIMIT 1';

      ds:=dbpq.query(sql);

      if ds.nrows = 1 then
      begin
        a := ds.FieldByName('a').AsFloat();
        alfa := ds.FieldByName('alfa').AsFloat();
        vm := ds.FieldByName('vm').AsFloat();
      end
      else
      begin
        a := potenciaAutorizada;
        alfa := alfa_POR_DEFECTO;
        vm := vm_POR_DEFECTO;
      end;
    end;
    1: // Solar
    // parabola chota
    begin

    end;
  end;

  centralBoba := TCentralGeneradora.Create(0, tipo, 0, '', '', '', '',
    '', '', '', potenciaAutorizada, 0, 0, 0, '', '', 0, 0);

  nMuestrasValidas := 0;

  NMuestras:=series.NPuntos;

  for kMuestra := 0 to NMuestras - 1 do
  begin
    if (datosNoValidos.IndexOf(FloatToStr(potUnDispSinRes.e(kMuestra + 1))) > -1) or
      (datosNoValidos.IndexOf(FloatToStr(vel.e(kMuestra + 1))) > -1) or
      (datosNoValidos.IndexOf(FloatToStr(ro.e(kMuestra + 1))) > -1) then
    begin
      modeloViejo.pon_e(kMuestra + 1, StrToFloat(datosNoValidos[0]));
      error.pon_e(kMuestra + 1, StrToFloat(datosNoValidos[0]));
      error2.pon_e(kMuestra + 1, StrToFloat(datosNoValidos[0]));
    end
    else
    begin
      case tipo of
      0: modeloViejo.pon_e(kMuestra + 1, centralBoba.VelToPot_SIMPLE_(
           0, vel.e(kMuestra + 1), ro.e(kMuestra + 1), a, alfa, vm) / potenciaAutorizada);
      1: modeloViejo.pon_e(kMuestra + 1, centralBoba.RadToPot_SIMPLE_(
           rad.e(kMuestra + 1), temp.e(kMuestra + 1), vel.e(kMuestra + 1), ro.e(kMuestra + 1)) / potenciaAutorizada);
      end;

      error.pon_e(kMuestra + 1, modeloViejo.e(kMuestra + 1) -
        potUnDispSinRes.e(kMuestra + 1));

      error2.pon_e(kMuestra + 1, sqr(error.e(kMuestra + 1)) *
        //(sqr(potUnDispSinRes.e(kMuestra + 1) - 0.75) + 0.4375));
        1);

      Inc(nMuestrasValidas);
    end;
  end;

  seriesModeloViejo := TSeriesDeDatos.CreateVacia(0, 1, vel.n);

  seriesModeloViejo.AddSerie('real', TVectR.Create_Clone(potUnDispSinRes));
  seriesModeloViejo.AddSerie('pronos', modeloViejo);
  seriesModeloViejo.AddSerie('error', error);
  seriesModeloViejo.AddSerie('e2', error2);

  //seriesModeloViejo.WriteToArchi(dirBaseResultadosDbg + 'modelo_viejo_dbg.xlt');

  Result:=promedioSinNoValidos(error2);

  ds.Free;
  centralBoba.Free;
end;

procedure TModeloRedesNeuronales.cambiarSeries(xSeries: TSeriesDeDatos);
begin
  inherited cambiarSeries(xSeries);
  problema.cambiarSeries(xSeries);
end;


{ TModelo }

constructor TModelo.Create(xSeries: TSeriesDeDatos; xDatosNoValidos: TStringList
  );
begin
  series:=xSeries;
  datosNoValidos:=xDatosNoValidos;
end;



procedure TModelo.evaluarModelo();
var
  kMuestra,NMuestras:integer;
begin
  for kMuestra:=0 to NMuestras - 1 do
    evaluarMuestra(kMuestra);
end;

procedure TModelo.evaluarMuestra(kMuestra: integer);
begin

end;

procedure TModelo.cambiarSeries(xSeries: TSeriesDeDatos);
begin
  series:=xSeries;
end;

function TModelo.calcularErrorMedio: NReal;
begin

end;

function TModelo.calcularErrorCuadraticoMedio: NReal;
begin

end;

procedure TModelo.writeResultadosToArchi(archiString: string);
var
  seriesArchi:TSeriesDeDatos;
begin
  // escribo el modelo y la realidad
  seriesArchi:=TSeriesDeDatos.CreateVacia(0,1,128);




end;

end.

