unit uhiperplanos;

{$mode delphi}

interface

uses
  Classes, SysUtils, xmatdefs, matreal, uauxiliares;

type
{ THiperplano }
// C = AT X + C0
THiperplano = class
  A: TDAofNReal;
  C0: NReal;
  constructor Create( DimX: integer);
  constructor CreateUnserializeXLT( s: string );
  function SerializeXLT: String;
  constructor CreateFromBinStream( f: TStream );
  procedure WriteToBinStream( f: TStream );
  function val( X: TDAofNReal ): NReal; overload;
  function val( Xr: TDAOfNReal; Xd: TDAofNInt ): NReal; overload;
  destructor destroy;override;
  function Clonar: THiperplano;
  procedure combinar( learningRate: NReal; NuevoHiperplano: THiperplano );
end;

TDAOfHiperplanos = array of THiperplano;

{ TConjuntoDeHiperplanos }

TConjuntoDeHiperplanos = class
  hiperPlanos:TDAOfHiperplanos;
  constructor Create(DimX: integer; NHiperplanos: integer);
  constructor CreateFromXLT( var fxlt: TextFile );
  procedure WriteToXLT( var fxlt: TStream );

  constructor CreateReadFromXLT( var fxlt: TStream );
  procedure WriteToArchi(archi: String);

  constructor CreateFromBinStream( f: TStream );
  procedure WriteToBinStream( f: TStream );
  destructor destroy; override;

// retorna el Hiperplano de mayor costo en el punto (xr, xd)
// en MC retorna el valor que toma el hiperplano devuelto en el punto (xr, xd)
  function HiperPlanoMayorCostoAt( Xr: TDAOfNreal; Xd: TDAOfNInt; out MC: NReal; out kHiperplano: integer ): THiperplano;

// retorna el valor del hiperplano de mayor costo en eel punto (xr, xd)
  function ValMax( xr: TDAOfNReal; xd: TDAOfNInt ): NReal;
end;

TDAOfConjuntosDeHiperplanos = array of TConjuntoDeHiperplanos;



function DistEuclidea2( hp1, hp2: THiperplano): NReal;
function DistanciaMaxAbs(  hp1, hp2: THiperplano): NReal;
function DistanciaMaxRel(  hp1, hp2: THiperplano): NReal;

implementation

function DistEuclidea2(hp1, hp2: THiperplano): NReal;
var
  res: NReal;
  k: integer;
begin
  res:= sqr( hp1.C0  - hp2.C0 );
  for k:= 0 to high( hp1.a ) do
    res:= res + sqr( hp1.a[k] - hp2.a[k] );
  result:= res;
end;

function DistanciaMaxAbs(hp1, hp2: THiperplano): NReal;
var
  res: NReal;
  a: NReal;
  k: integer;
begin
  res:= abs( hp1.C0  - hp2.C0 );
  for k:= 0 to high( hp1.a ) do
  begin
    a:= abs( hp1.a[k] - hp2.a[k] );
    if a > res then res:= a;
  end;
  result:= res;
end;

function DistanciaMaxRel(hp1, hp2: THiperplano): NReal;
var
  res: NReal;
  a: NReal;
  k: integer;
begin

  if ((hp1=nil) or (hp2=nil)) then
  begin
    Result:=0;
    Exit;
  end;

  if hp1.C0 <> 0 then
    res:= abs( hp1.C0  - hp2.C0 ) / abs( hp1.C0 )
  else
    if hp2.C0 <> 0 then
      res:= abs( hp1.C0  - hp2.C0 ) / abs( hp2.C0 )
    else
      res:= 0;

  for k:= 0 to high( hp1.a ) do
  begin
    if hp1.a[k] <> 0 then
      a:= abs( hp1.a[k] - hp2.a[k] ) / hp1.a[k]
    else
      if hp2.a[k] <> 0 then
        a:= abs( hp1.a[k] - hp2.a[k] ) / hp2.a[k]
      else
        a:= 0;
    if a > res then res:= a;
  end;

  result:= res;
end;



{ TConjuntoDeHiperplanos }

constructor TConjuntoDeHiperplanos.Create(DimX: integer; NHiperplanos: integer);
var
  k: integer;
begin
  setlength( hiperPlanos, NHiperplanos );
  for k:= 0 to high( hiperPlanos ) do
    hiperPlanos[k]:= THiperplano.Create( DimX );
end;

constructor TConjuntoDeHiperplanos.CreateFromXLT(var fxlt: TextFile);
var
  r: string;
  k: integer;
  NHiperplanos: integer;
begin
  readln( fxlt, NHiperplanos );
  setlength( hiperplanos, NHiperplanos );
  for k:= 0 to high( hiperPlanos ) do
  begin
    readln( fxlt, r );
    hiperPlanos[k]:= THiperplano.CreateUnserializeXLT( r );
  end;
end;


procedure TConjuntoDeHiperplanos.WriteToXLT(var fxlt: TStream);
var
  r: string;
  k, an: integer;
begin
  writeS( fxlt, IntToStr( length( hiperplanos ) ) );
  for k:= 0 to high( hiperPlanos ) do
  begin
     if hiperPlanos[k]=nil then
       Writeln('hola')
     else
       an:=Length(hiperPlanos[k].A);
     r:= hiperPlanos[k].SerializeXLT;
     writeS( fxlt, #9 + r );
  end;
   writelnS(fxlt);
end;

constructor TConjuntoDeHiperplanos.CreateReadFromXLT(var fxlt: TStream);
var
  r: string;
  k: integer;
  NHiperplanos: integer;
begin
  ReadLnS( fxlt, r) ;
  NHiperplanos:=NextInt(r);

  setlength( hiperPlanos, NHiperplanos );
  for k:= 0 to high( hiperPlanos ) do
    hiperPlanos[k]:= THiperplano.CreateUnserializeXLT(r);//( getNextPalSep( r, #9 ) );
end;

procedure TConjuntoDeHiperplanos.WriteToArchi(archi: String);
var
  f: TStream;
begin
  f:= TFileStream.Create( archi, fmCreate+ fmShareExclusive );
  WriteToXLT(f);
  f.free;
end;

constructor TConjuntoDeHiperplanos.CreateFromBinStream(f: TStream);
var
  k: integer;
  NHiperplanos: integer;
begin
   f.Read( NHiperplanos, sizeOf(NHiperplanos ) );
   setlength( hiperPlanos, NHiperplanos );
   for k:= 0 to high( hiperPlanos ) do
      hiperPlanos[k]:= THiperplano.CreateFromBinStream( f );

end;

procedure TConjuntoDeHiperplanos.WriteToBinStream(f: TStream);
var
  k: integer;
  NHiperPLanos: integer;
begin
   NHiperplanos:= length( Hiperplanos );
   f.Write( NHiperplanos, SizeOf( NHiperplanos ) );
   for k:= 0 to high( hiperPlanos ) do
     hiperPlanos[k].WriteToBinStream( f );
end;

destructor TConjuntoDeHiperplanos.destroy;
var
  k: integer;
begin
  for k:= 0 to high( hiperPlanos ) do
    hiperPlanos[k].Free;
  setlength( hiperPlanos, 0 );
  inherited destroy;
end;

function TConjuntoDeHiperplanos.HiperPlanoMayorCostoAt(Xr: TDAOfNreal;
  Xd: TDAOfNInt; out MC: NReal; out kHiperplano: integer): THiperplano;
var
  hpMC, hp: THiperplano;
  C: NReal;
  k: integer;
begin
  hpMC:= hiperPlanos[0];
  MC:= hpMC.val( xr, xd );
  kHiperplano:= 0;
  for k:= 1 to high( hiperPlanos ) do
  begin
    hp:= hiperPLanos[k];
    C:= hp.val( xr, xd );
    if C > MC then
    begin
      MC:= C;
      hpMC:= hp;
      kHiperplano:= k;
    end;
  end;
  result:= hpMC;
end;

function TConjuntoDeHiperplanos.ValMax(xr: TDAOfNReal; xd: TDAOfNInt): NReal;
var
  mc: NReal;
  kh: integer;
  ah: THiperplano;
begin
  ah:= self.HiperPlanoMayorCostoAt( xr, xd, mc, kh );
  result:= mc;
end;

{ THiperplano }

constructor THiperplano.Create(DimX: integer);
begin
  inherited Create;
  setlength( a, DimX );
  C0:= 0;
end;

constructor THiperplano.CreateUnserializeXLT(s: string);
var
  k: integer;
  DimX: integer;
begin
  DimX:= NextInt( s, #9 );
  Create( DimX );
  for k:= 0 to high( a ) do
    a[k]:= NextFloat( s, #9 );
  C0:= NextFloat( s, #9 );
end;

function THiperplano.SerializeXLT: String;
var
  s: string;
  k,an: integer;
begin
 an:= length(A);
 s:= IntToStr( length( A ) );
  for k:= 0 to high( A ) do
    s:= s + #9 + FloatToStr( A[k] );

  s:= s+ #9+ FloatToStr( C0 );
  result:= s;
end;

constructor THiperplano.CreateFromBinStream(f: TStream);
var
  DimX: integer;
begin
  f.Read( DimX, sizeOf( DimX ) );
  Create( DimX );
  f.Read( a[0], length( a ) * SizeOf( NReal ) );
  f.Read( C0, SizeOf( C0 ) );
end;

procedure THiperplano.WriteToBinStream(f: TStream);
var
  DimX: integer;

begin
  DimX:= length( a );
  f.Write( DimX, sizeOf( DimX ) );
  f.Write( a[0], length( a ) * SizeOf( NReal ) );
  f.Write( C0, SizeOf( C0 ) );
end;

function THiperplano.val(X: TDAofNReal): NReal;
var
  res: NReal;
  k: integer;
begin
  res:= C0;
  for k:= 0 to high( X ) do
    res:= res + a[k]* X[k];
  result:= res;
end;

function THiperplano.val(Xr: TDAOfNReal; Xd: TDAofNInt): NReal;
var
  res: NReal;
  k: integer;
  base: integer;
begin
 // res:= C0;
  res:=0;
  for k:= 0 to high( Xr ) do
    res:= res + a[k]* Xr[k];
  base:= length( Xr );
  for k:= 0 to  high( xd ) do
    res:= res + a[base + k] * Xd[k];
  result:= res;
end;

destructor THiperplano.destroy;
begin
  setlength( a, 0 );
  inherited destroy;
end;

function THiperplano.Clonar: THiperplano;
var
  res: THiperplano;
  k: integer;
begin
  res:= THiperplano.Create( length( a  ));
  for k:= 0 to high( a ) do
    res.a[ k ] := a[ k ];
  res.C0:= C0;
  result:= res;
end;

procedure THiperplano.combinar(learningRate: NReal; NuevoHiperplano: THiperplano
  );
var
  k: integer;
  r: NReal;

begin

  r:= 1 - learningRate;
  for k:= 0 to high( a ) do
     a[ k ]:= a[ k] * r + NuevoHiperplano.a[ k ] * learningRate;
  c0 := c0 * r + NuevoHiperplano.c0* learningrate;
end;



end.

