unit uTestSimplex;

interface

uses
	Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
	StdCtrls, uExcelFile, xMatDefs,
	uSimplex,	uMIPSImplex, uconstantesSimSEE, ulistaViolacionesPermitidasSimplex;

type
	TformTestSimplex = class(TForm)
    btAbrir: TButton;
    BTCerrar: TButton;
		OpenDialog1: TOpenDialog;
    BTActualizar: TButton;
		memo: TMemo;
		btContinuar: TButton;
    eCntLlamadas: TEdit;
    eCntHasta: TEdit;
		procedure btAbrirClick(Sender: TObject);
		procedure BTCerrarClick(Sender: TObject);
		procedure BTActualizarClick(Sender: TObject);
		procedure btContinuarClick(Sender: TObject);
		procedure FormCreate(Sender: TObject);
		procedure FormClose(Sender: TObject; var Action: TCloseAction);
	private
		procedure Procesar_DBGMONSPX(var Message: TMessage); message WM_DBGMONSPX;
		procedure ResolverReferenciasYCargarSimplex;
	public
		xf: TExcelFile;
		h: Variant;
		kfilx: integer; // fila de las x: en la planilla
		spx: TSimplex;
	end;

var
	formTestSimplex: TformTestSimplex;

implementation

{$R *.DFM}

procedure TformTestSimplex.Procesar_DBGMONSPX(var Message: TMessage);
var
	ts: String;
	cntLLamadas, cntHasta: integer;
begin
	cntLlamadas:= StrToInt( ecntLlamadas.text );
	inc( cntLlamadas );
	ecntLlamadas.text:= IntToStr( cntLlamadas );
	cntHasta:= StrToInt( ecntHasta.text );

	ts:= ecntLlamadas.text+'::>'+dbgmonspx_LeerMensaje;
	memo.Lines.Append( ts );
	if cntLlamadas <= cntHasta then
		btContinuarClick( self )
	else
		btContinuar.Enabled:= true;
end;

procedure TformTestSimplex.btAbrirClick(Sender: TObject);
var
	res: integer;
begin
	if OpenDialog1.Execute then
	begin
		btAbrir.Enabled:= false;
		xf:= TExcelFile.Create('', true);
		xf.Abrir( OpenDialog1.FileName );
		ResolverReferenciasYCargarSimplex;
		res:=	spx.Resolver;
	end;
end;

procedure TformTestSimplex.BTCerrarClick(Sender: TObject);
begin
	if assigned( xf ) then
	begin
		xf.Free;
		xf:= nil;
		dbgmonspx_Abortar;		
	end;
	btAbrir.Enabled:= true;
end;

procedure TformTestSimplex.ResolverReferenciasYCargarSimplex;
var
	jcol: integer;
	buscando: boolean;
	r: string;
	cnt_Variables, cnt_Restricciones: integer;

	k, j: integer;
  ivae1, ivae2: String;

	lstve: TDAOfNInt;
  xlstAcoplesVEnts: TDAOfAcoplesVEnts;
	NEnteras, nViolacionesPermitidas, nViolacionesUsadas: integer;
  ficha: TFichaViolacionPermitida;
  listaViolacionesPermitidas: TListaViolacionesPermitidasSimplex;
begin
	buscando:= true;
	kfilx:= 1;
	jcol:= 1;
	h:= xf.Hoja(1);
	while buscando and (kfilx < 100) do
	begin
		r:=	h.cells[kfilx, 1];
		if pos('NEnteras:', r ) = 1 then
			buscando:= false
		else
			inc( kfilx );
	end;

	NEnteras:= h.cells[kfilx, 2];
	setlength( lstve, NEnteras );
	for k:= 0 to high( lstve ) do
		lstve[k]:= h.cells[kfilx, 3+k];
  //paso la lista de variables enteras y el ivae VarAcoplada ResAcoplada
  kfilx:= kfilx + 2;
  setLength( xlstAcoplesVEnts, NEnteras);
  for k:= 0 to high(xlstAcoplesVEnts) do
  begin
    j:= 1;
    ivae1:= h.cells[kfilx, 1];
    ivae2:= h.cells[kfilx + j, 1];
    while (ivae1 = ivae2) do
    begin
      inc(j);
      ivae2:= h.cells[kfilx + j, 1]
    end;
    setLength(xlstAcoplesVEnts[k], j);
    for j:= 0 to high(xlstAcoplesVEnts[k]) do
    begin
      xlstAcoplesVEnts[k][j].ivar:= h.cells[kfilx + j, 2];
      xlstAcoplesVEnts[k][j].ires:= h.cells[kfilx + j, 3];
    end;
    kfilx:= kfilx + length(xlstAcoplesVEnts[k]);
  end;

  kfilx:= kfilx + 2;//cnt_Varfijas, cnt_RestriccionesRedundantes
  listaViolacionesPermitidas:= TListaViolacionesPermitidasSimplex.Create;
  nViolacionesUsadas:= h.cells[kfilx, 2];
  kfilx:= kfilx + 2;//cnt_ViolacionesUsadas, violacionesPermitidas
  nViolacionesPermitidas:= h.cells[kfilx, 2];
  listaViolacionesPermitidas.Capacity:= nViolacionesPermitidas;
  inc(kfilx);//ivar	ires	usada
  for k:= 1 to nViolacionesPermitidas do
  begin
    ficha:= TFichaViolacionPermitida.Create(h.cells[kfilx + k, 1], h.cells[kfilx + k, 2]);
    ficha.usada:= h.cells[kfilx + k, 3];
    listaViolacionesPermitidas.Add(ficha);
  end;

	buscando:= true;
	kfilx:= 1;
	jcol:= 1;
	h:= xf.Hoja(1);
	while buscando and (kfilx < 100) do
	begin
		r:=	h.cells[kfilx,1];
		if pos('x:', r ) = 1 then
			buscando:= false
		else
			inc( kfilx );
	end;

	if buscando then
		raise Exception.Create('No encontré la fila del asl x: ' );

	// contamos las variables
	cnt_Variables:= 0;
	jcol:= 2;
	r:= h.cells[kfilx, jcol];
	while r <> '' do
	begin
		inc( cnt_Variables );
		inc( jcol );
		r:= h.cells[kfilx, jcol];
	end;

	// contamos las restricciones
	cnt_Restricciones:= 0;
	jcol:= 2;
	r:= h.cells[kfilx+4, jcol];
	while r <> '' do
	begin
		inc( cnt_Restricciones);
		inc( jcol );
		r:= h.cells[kfilx+4, jcol];
	end;

  //creamos el simplex
  spx:= TMIPSimplex.Create_init( cnt_Restricciones+1, cnt_Variables+1, NEnteras, NIL, NIL);
  spx.violacionesPermitidas.Free;
  spx.violacionesPermitidas:= listaViolacionesPermitidas;
  spx.cnt_ViolacionesUsadas:= nViolacionesUsadas;


  for j:= 1 to cnt_Variables do
    spx.top[j]:= h.cells[kfilx+5, j + 1];

  for j:= 1 to cnt_Restricciones do
	  spx.left[j]:= h.cells[kfilx+6, j + 1];

  spx.rearmarIndicesiiXiiY;

  // ahora leemos las variables y sus cotas
  spx.cnt_varfijas:= 0;
  for j:= 1 to cnt_Variables do
  begin
	  spx.x_inf.pv[j]:= h.cells[kfilx+1, j + 1];
  	spx.x_sup.pv[j]:= h.cells[kfilx+2, j + 1];
	  spx.flg_x[j]:= h.cells[kfilx+3, j + 1];
  	if abs( spx.flg_x[j] ) = 2 then inc (spx.cnt_varfijas );
    spx.nombreVars[j]:= h.cells[kfilx, j + 1 ];
  end;

//  TMIPSimplex(spx).lstAcoplesVEnts:= xlstAcoplesVEnts;
  for j:= 1 to NEnteras do
  begin
    if xlstAcoplesVEnts[j - 1][0].ivar <> -1 then
      TMIPSimplex(spx).set_EnteraConAcoples(j, lstve[j-1], trunc( spx.x_sup.pv[lstve[j-1]] + 0.1),
                                            xlstAcoplesVEnts[j - 1])
    else
      spx.set_entera( j, lstve[j-1], trunc( spx.x_sup.pv[lstve[j-1]] + 0.1) );
  end;

  // cargamos las flg_y
  spx.cnt_igualdades:= 0;
  for j:= 1 to cnt_Restricciones do
  begin
    spx.flg_y[j]:= h.cells[kfilx+4, j + 1 ];
    if abs(spx.flg_y[j]) = 2  then
      inc( spx.cnt_igualdades );
    if spx.iiy[j] > 0 then
      spx.nombreRest[j]:= h.cells[kfilx + 10 + spx.iiy[j], 1]
    else
      spx.nombreRest[j]:= h.cells[kfilx + 10, 1 - spx.iiy[j] ]
  end;

  // cargamos la matriz
  for k:= 1 to cnt_Restricciones + 1 do
    for j:= 1 to cnt_Variables + 1 do
    begin
      spx.pon_e(k, j , h.cells[kfilx + 10 + k, j + 1]);
    end;
end;

procedure TformTestSimplex.BTActualizarClick(Sender: TObject);
var
	k, j: integer;
	spx: TSimplex;
begin
  BTContinuar.enabled:= false;
	spx:= umipsimplex.spxActivo;
	if spx = nil then exit;
  h.cells[kfilx - 3, 2]:= spx.cnt_varfijas;
  h.cells[kfilx - 2, 2]:= spx.cnt_RestriccionesRedundantes;
  //Cotas y flgs_x
  for j:= 1 to spx.nc-1 do
  begin
	  h.cells[kfilx+1, j + 1]:= spx.x_inf.pv[j];
  	h.cells[kfilx+2, j + 1]:= spx.x_sup.pv[j];
	  h.cells[kfilx+3, j + 1]:= spx.flg_x[j];
  end;

  //flgs_y
  for j:= 1 to spx.nf-1 do
  begin
    h.cells[kfilx+4, j + 1 ]:=spx.flg_y[j];
  end;

  //Top y left
  for j:= 1 to spx.nc-1 do
    h.cells[kfilx+5, j + 1 ]:=spx.top[j];
  for j:= 1 to spx.nf-1 do
    h.cells[kfilx+6, j + 1 ]:=spx.left[j];

  //Encabezados de las variables
  for j:= 1 to spx.nc do
	  if spx.top[j] < 0 then
		  h.cells[kfilx+10+0, j+1]:= spx.nombreVars[-spx.top[j]]
  	else
	    h.cells[kfilx+10+0, j+1]:= spx.nombreRest[spx.top[j]];

  //Nombres de las restricciones y valores que tienen que cumplir
  for k:= 1 to spx.nf-1 do
	  if spx.left[k] > 0 then
    begin
      //Es una y
			h.cells[kfilx+10+k, 1]:= spx.nombreRest[spx.left[k]];
			case spx.flg_y[spx.left[k]] of
				0: begin
           h.cells[kfilx+10+k, 1+spx.nc+1]:='>= 0';
           h.cells[kfilx+10+k, 1+spx.nc+2]:='';
           end;
				2: begin
        	 h.cells[kfilx+10+k, 1+spx.nc+1]:='= 0';
           h.cells[kfilx+10+k, 1+spx.nc+1]:='';
           end;
        -2:begin
           h.cells[kfilx+10+k, 1+spx.nc+1]:='= 0';
           h.cells[kfilx+10+k, 1+spx.nc+1]:='';
           end;
			else
        //Cota superior de una restriccion??
				h.cells[kfilx+10+k, 1+spx.nc+1]:='??, flg_y='+IntToStr( spx.flg_y[spx.left[k]] );
			end; // case
	  end
	  else
		begin
      //Es una x
			h.cells[kfilx+10+k, 1]:= spx.nombreVars[-spx.left[k]];
			case spx.flg_x[-spx.left[k]] of
				-1, 1:  begin
                h.cells[kfilx+10+k, 1+spx.nc+1]:= '>= 0';
                h.cells[kfilx+10+k, 1+spx.nc+2]:= '<= ' + FloatToStr(spx.x_sup.e(-spx.left[k]));
                end;
        -2, 2:  begin
//                if pos('=', h.cells[kfilx+10+k, 1+spx.nc+2]) <> 0 then
                h.cells[kfilx+10+k, 1+spx.nc+2]:= ' ';
                h.cells[kfilx+10+k, 1+spx.nc+1]:= '= 0';// + FloatToStr(spx.x_inf.e(-spx.left[k]));
                end;
				0:  begin
//            if pos('=', h.cells[kfilx+10+k, 1+spx.nc+2]) <> 0 then
            h.cells[kfilx+10+k, 1+spx.nc+2]:= ' ';
            h.cells[kfilx+10+k, 1+spx.nc+1]:='>= 0';
            end
			end; //  case
		end;
  h.cells[kfilx + 10 + spx.nf, 1]:= 'z';

  for k:= 1 to spx.nf do
	  for j:= 1 to spx.nc do
    begin
//	  	h.cells[kfilx+10+k, j+1]:= spx.e(k, j);
	  	h.cells[kfilx+10+k, j+1]:= spx.pm[k].pv[j];
      if abs(spx.pm[k].pv[j]) > 1E15 then
        memo.Lines.Add('OJO: abs(spx[' + IntToStr(k) +', ' + IntToStr(j) + ']) > 1E15');
    end;
  BTContinuar.enabled:= true;
end;

procedure TformTestSimplex.btContinuarClick(Sender: TObject);
begin
	btContinuar.Enabled:= false;
	dbgmonspx_Continuar;
end;

procedure TformTestSimplex.FormCreate(Sender: TObject);
begin
	usimplex.dbgmonspx_RegistrarMonitor( Handle );
	xf:= nil;
  OpenDialog1.InitialDir:= getDir_Dbg;
end;

procedure TformTestSimplex.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  BTCerrarClick(BTCerrar);
	if xf <> nil then
	begin
		xf.free;
		xf:= nil;
		dbgmonspx_RegistrarMonitor(0);
		dbgmonspx_Continuar;		
	end;
end;

end.
