/************************************************************************
* retroLP solves linear programs using the simplex method.             *
* Copyright (C) 2001, 2003, 2005 Gavriel Yarmish & Richard Van Slyke.  *
* For further information, and gpl licensing, see the end of this file.*
************************************************************************/


//======================= FILE TO_STATE.CPP ===================
// Reads from a binary problem representation into LP_state 
// structure. If alloc is positive it allocates dynamic
// memory for the LP_state.
// 3/26/05 Changed so that readmps could be integrated 
//         into retroLP
// 8/8/01 Revised lpb format to include variable names (lpbV1)
//        also modified report to give dual variables,
//        variable names
// 8/10/01 Reversed sign of Phase II objective reported in output
#include "simplex.h"
#include "params.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>


LP_state *allocate_LP_state();
double **allocate_a(long , long);
short *allocate_svector(long);
void *allocate_evector(long,size_t);
int *allocate_ivector(long);
long *allocate_lvector(long);
double *allocate_dvector(long);
char *allocate_cvector(long nn);
char *allocate_strvector(int ,long );
void report(long, LP_state **,double *);
void tableau_out(LP_state *);
char *out_type(var_type);
char *out_range(var_range);
int to_state(FILE *, short, LP_state **);

//=====================TO_STATE=========================
int to_state(FILE *file, short alloc, LP_state **lp)
{
   int j, k;
#if RFLAG
   int i;
#endif
   size_t size;
   LP_state *s;
// If we need to allocate space do so
   if(alloc > 0)
   {
      s=allocate_LP_state();
      s->name = allocate_cvector(101);
   }
   else
   {
      s=*lp;
   }
//Make sure we are at beginning for file
   rewind(file);
// FIND OUT SIZES
   k=0; //============= NAME ============
   fread(&size,sizeof(size_t),1,file);
   if(feof(file)+ferror(file)>0)goto error;   
   fread(s->name,sizeof(char),size+1,file);
   if(feof(file)+ferror(file)>0)goto error;
   k=1; //============== M ==============
   fread(&(s->m),sizeof(long), 1, file);
   if(feof(file)+ferror(file)>0)goto error;
   k=2; //============== N ===============
   fread(&(s->n),sizeof(long), 1, file);
   if(feof(file)+ferror(file)>0)goto error;
   k=3; //============== MM ==============
   fread(&(s->mm),sizeof(long), 1, file);
   if(feof(file)+ferror(file)>0)goto error;
// ALLOCATE SPACE DATA STRUCTURE FOR THE FIRST TIME ONLY ( alloc > 0 )
   if(alloc > 0)
   {
      s->a = allocate_a(s->m, s->n);
      s->jnonbasic = allocate_lvector(s->n);
      s->ntype = (var_type *)allocate_evector(s->n, sizeof(var_type));
      s->nrange = (var_range *)allocate_evector(s->n, sizeof(var_range));
      s->x = allocate_dvector(s->n);
      s->nl = allocate_dvector(s->n);
      s->nu = allocate_dvector(s->n);
      s->ibasic = allocate_lvector(s->m +1);
      s->btype = (var_type *)allocate_evector(s->m, sizeof(var_type));
      s->brange = (var_range *)allocate_evector(s->m, sizeof(var_range));
      s->b = allocate_dvector(s->m+1);
      s->bl = allocate_dvector(s->m);
      s->bu = allocate_dvector(s->m);
   }


   k=4; //============== A MATRIX ==============
#if RFLAG
   printf(" Constraint Matrix \n");
#endif
   // Write out each column separately since allocated separately.
   for (j=0;j<=s->n; j++)
   {
      fread(s->a[j],sizeof(double),s->m+2,file);
      if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
      for(i=0;i<=s->m+1;i++)
         {
            printf(" %10.2e ", s->a[j][i]);
         }
         printf("\n");
#endif

   }
   k=5; //============== JNONBASIC ==============
#if RFLAG
   printf(" Indices of non-basic variables \n");
#endif
   fread(s->jnonbasic ,sizeof(long),s->n+1,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
for(j=1;j<=s->n;j++)
   {
      printf(" %ld ", (s->jnonbasic)[j]);
   }
   printf("\n");
#endif
   k=6; //============== NTYPE ==============
#if RFLAG
   printf(" Non-basic types \n");
#endif
   fread(s->ntype,sizeof(var_type),s->n + 1 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(j=1;j<=s->n;j++)
   {
      printf(" %d ", (s->ntype)[j]);
   }
   printf("\n");
#endif
   k=7; //============== NRANGE ==============
#if RFLAG
   printf(" Variable range vector \n");
#endif    
   fread(s->nrange,sizeof(var_range),s->n + 1 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(j=1;j<=s->n;j++)
   {
      printf(" %d ", (s->nrange)[j]);
   }
   printf("\n");
#endif
   k=8; //============== X ==============
#if RFLAG
   printf(" Current value of non-basics \n");
#endif
   fread(s->x,sizeof(double),s->n + 1 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(j=1;j<=s->n;j++)
   {
      printf(" %10.2e ", (s->x)[j]);
   }
   printf("\n");
#endif
// FILL IN LOWER AND UPPER BOUNDS
   k=9; //============== NL ==============
#if RFLAG
   printf(" Lower and upper bounds \n");
#endif
   fread(s->nl,sizeof(double),s->n +1 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
     for(j=1;j<=s->n;j++)
     {
        printf(" %10.2le ", (s->nl)[j]);
     }
     printf("\n");
#endif
   k=10; //============== NU ==============
   fread(s->nu, sizeof(double),s->n +1 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
     for(j=1;j<=s->n;j++)
     {
        printf(" %10.2le ", (s->nu)[j]);
     }
     printf("\n");
#endif
// LOAD INDICES OF BASIC VARIABLES
#if RFLAG
   printf(" Indices of basic variables \n");
#endif
   k=11; //============== IBASIC ==============
   fread(s->ibasic ,sizeof(long),s->m+1,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(i=1;i<=s->m;i++)
   {
      printf(" %ld ", (s->ibasic)[i]);
   }
   printf("\n");
#endif
// LOAD INDICES OF NON-BASIC VARIABLES
#if RFLAG
   printf(" Types of basic variables \n");
#endif
   k=12; //============== BTYPE ==============
   fread(s->btype ,sizeof(var_type),s->m + 1 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(i=1;i<=s->m;i++)
   {
      printf(" %d ", (s->btype)[i]);
   }
   printf("\n");
#endif
// LOAD INDICES OF NON-BASIC VARIABLES
#if RFLAG
   printf(" Ranges of basic variables \n");
#endif
   k=13; //============== BRANGE ==============
   fread(s->brange ,sizeof(var_range),s->m + 1 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(i=1;i<=s->m;i++)
   {
      printf(" %d ", (s->brange)[i]);
   }
   printf("\n");
#endif
// CURRENT VALUE OF BASIC VARIABLES
   k=14; //============== B ==============
#if RFLAG
   printf(" Current value of basics \n");
#endif
   fread(s->b, sizeof(double), s->m + 2 ,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(i=0;i<=s->m+1;i++)
   {
      printf(" %12.4e ", (s->b)[i]);
   }
   printf("\n");
#endif
   k=15; //============== BL ==============
#if RFLAG
   printf(" Lower bounds for basics \n");
#endif
   fread(s->bl,sizeof(double),s->m + 1,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(j=1;j<=s->m;j++)
   {
      printf(" %12.4e ", (s->bl)[j]);
   }
   printf("\n");
#endif
   k=16; //============== BU ==============
#if RFLAG
   printf(" Upper bounds for basics \n");
#endif
   fread(s->bu,sizeof(double),s->m + 1,file);
   if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
   for(j=1;j<=s->m;j++)
   {
      printf(" %12.4e ", (s->bu)[j]);
   }
   printf("\n");
#endif
   k=17; //======== Check for Verions lpbV1 ==============
#if RFLAG
   printf(" Check for version lpbV1 extension \n");
#endif
// You need only read in the row and column names once!
   if(alloc)
   {
   s->lpb_version = allocate_cvector(10);
   fread(s->lpb_version,sizeof(char),10,file);
// If end of file reached assume old format lpbV0
   if(feof(file))
   {
      strcpy(s->lpb_version,"lpbV0");
      printf("Version lpbV0 file\n");
   }
   else
   {
      if(strcmp(s->lpb_version,"lpbV1"))
      {
// Corrupted file !?
         k=171;
         goto error;
      }
      if(ferror(file)>0)
      {
         k=172;
         goto error;
      }
// If we get here we have version lpbV1
      printf("\n\n<><><><><><><><><><><><><><><><><><><><><><><><><><><>\n");
      printf("PROBLEM: %s\n", s->name);
      printf("Version lpbV1 file\n");
// Only attempt to read for new files (lpbV1)

      k=18; //============== NAMES ==============
#if RFLAG
      printf(" Row and Column Names \n");
#endif
      s->names = allocate_strvector(8,s->m+s->n);
      fread(s->names,sizeof(char),9*(s->m +s->n + 1),file);
      if(feof(file)+ferror(file)>0)goto error;
#if RFLAG
      printf("ROWS:\n");
      for(j=s->n + 1;j<=s->m+ s->n;j++)
      {
          printf(" %s\n",&(s->names[9*j]));
      }
      printf("\n");
      printf("COLUMNS:\n");
      for(j=1;j<=s->n;j++)
      {
          printf(" %s\n",&(s->names[9*j]));
      }
      printf("\n");
#endif
   }
   }
   *lp=s;
   return 0;
   error:
      printf("Error in reading file (%d) -- feof, ferror: %d %d \n" , k, feof(file), ferror(file));
      clearerr(file);
      return(200+k);
}
//=============================REPORT=============================
// Print out landscape; assumes 100 characters per line available
// Level gives the amount of output:
//   Level = 0 => No output
//   Level = 1 => A few lines of output including phase, iteration
//                number,
//   Level = 2 => 1 plus the incoming and outcoming variables from
//                the last iteration and related values
//   Level = 3 => 2 plus row and column values
//   Level = 4 => 3 plus matrix of coefficients

//Global variable for statistics
extern long iter,        // iterations in simplex (excluding refresh, et al.)
     miter,       // major iterations: iterations which result in an
                  // actual pivot
     riter,   // Cumulative pivots in refresh, et al.
     cntnfx,      // number of times CCR3 doesn't encounter fixed, non-basic variable
     cntcc;       // number of times CCR3 actually used (inner product taken)


void report(long level, LP_state *s )
{
   FILE * output;
   long i, j, k, v = 0;
   double * pi;
   if(!strcmp(s->lpb_version,"lpbV1"))v = 1;
   else printf("Old version of .lpb file; can't print variable names\n");

//------------------ NAME ---------------------
   
    int hossz;
	char outfile[30];
	for (hossz=0;s->name[hossz]!='\0';hossz++){
		outfile[hossz]=s->name[hossz];
	}
    outfile[hossz++]='.';
	outfile[hossz++]='s';
	outfile[hossz++]='o';
	outfile[hossz++]='l';
	outfile[hossz++]='\0';
   
   output = fopen(outfile,"w");
   if(level >= 1)
   {
      printf("======================================\n");
      printf("PROBLEM: %s \n",s->name);


	  fprintf(output,"\n\n****************************\n");
      fprintf(output,"  PROBLEM NAME: %s ",s->name);
	  fprintf(output,"\n****************************\n\n");
	  
	  // Sign of Phase II objective gets reversed in retroLP
      printf("Objective value: Phase 2: %20.12e\n",-(maxfactor)*s->b[0]);
      fprintf(output,"     Objective value: Phase 2  : %19.12e\n",-(maxfactor)*s->b[0]);
	  
	  printf("Objective value: Phase 1: %20.12e\n", s->b[s->m + 1]);
	  fprintf(output,"     Objective value: Phase 1  : %19.12e\n", s->b[s->m + 1]);

      printf("AT ITERATION %ld, MAJOR %ld, RE %ld", iter, miter, riter);
	  fprintf(output,"     NUMBER OF ITERATION       : %ld\n", iter);
	  //fprintf(output,"     NUMBER OF MAJOR           : %ld\n", miter);
	  fprintf(output,"     NUMBER OF ROWS            : %ld\n", s->m);
	  fprintf(output,"     NUMBER OF COLUMNS         : %ld\n", s->n);
	  
	  

      if(ccr==2) printf("\nFor CCR2 not fixed %ld, not evaluated %ld",cntnfx, cntcc);
      if(ccr==3) printf("\nFor CCR3 not fixed %ld, not evaluated %ld",cntnfx, cntcc);

      printf("\n");
      if(s->mm == 0)
         printf("(IN PHASE 2)\n");
      else
         printf("(IN PHASE 1)\n");
//==================== SIZES =================
   printf(" m, n, mm: %ld, %ld, %ld \n",  \
               s->m, s->n, s->mm);
   }
//----------------- ROW RESULTS -----------------
   if(level >= 3)
   {
// Allocate space for dual vector
      pi = allocate_dvector(s->m);

   // Load pi vector
      for(i=1; i<=s->m; i++)
         if((k=s->ibasic[i])>s->n)pi[k-s->n]=0.0;
      for(j=1; j<=s->n; j++)
         if((k=s->jnonbasic[j])>s->n)pi[k-s->n]=s->a[j][s->mm];

      printf("\nROW RESULTS (Currently Basic Variables)\n");
	  fprintf(output,"\n***************************************");
      fprintf(output,"\nROW RESULTS (Currently Basic Variables)");
	  fprintf(output,"\n***************************************\n\n");
	  
	  if(v)printf("  Name   ");
	  if(v)fprintf(output,"  Name   ");
      printf(" Index     Type        Range         Value      Lower Bound\Upper Bound Dual Variable\n");
      fprintf(output," Index     Type        Range         Value        Dual Variable\n");
      fprintf(output,"----------------------------------------------------------------------\n");

      char *tp, *rng;
      for(i=1;i<=s->m;i++)
      {
         tp = out_type(s->btype[i]);
         rng = out_range(s->brange[i]);
         if(v)printf("%8s ",&(s->names[9*(s->ibasic[i])]));
		 if(v)fprintf(output,"%8s ",&(s->names[9*(s->ibasic[i])]));
         printf(" %6ld  %8s  %8s  %12.4e  %12.4e  %12.4e",s->ibasic[i], tp, rng, s->b[i], s->bl[i], s->bu[i]);
         
         fprintf(output," %6ld  %8s  %8s  %12.4e ",s->ibasic[i], tp, rng, s->b[i]);
         
         
         if(v)printf("%12.4e",pi[i]);
		 if(v)fprintf(output,"%15.4e",pi[i]);
         printf("\n");
		 fprintf(output,"\n");
      }
//----------------- COLUMN RESULTS -----------------
      printf("\nCOLUMN RESULTS (Currently non-basic variables)\n");
	  
	  fprintf(output,"\n\n**********************************************");
	  fprintf(output,"\nCOLUMN RESULTS (Currently non-basic variables)");
	  fprintf(output,"\n**********************************************\n\n");

      if(v)printf("  Name   ");
	  if(v)fprintf(output,"  Name   ");
      printf(" Index     Type        Range        Value     Reduced Cost\n");
      
      
      fputs(" Index     Type        Range        Value        Reduced Cost\n",output);
      fputs("-------------------------------------------------------------------------\n",output);
      
      for(j=1;j<=s->n;j++)
      {
         tp = out_type(s->ntype[j]);
         rng = out_range(s->nrange[j]);
         if(v)printf("%8s ",&(s->names[9*(s->jnonbasic[j])]));
		 if(v)fprintf(output,"%8s ",&(s->names[9*(s->jnonbasic[j])]));
         printf(" %6ld  %8s  %8s %12.4e  %12.4e  %12.4e  %12.4e\n",s->jnonbasic[j], tp, rng, s->x[j], s->nl[j], s->nu[j], s->a[j][s->mm]);

         fprintf (output," %6ld  %8s  %8s %12.4e %15.4e\n",s->jnonbasic[j], tp, rng, s->x[j], s->a[j][s->mm]);
      }
      free(pi);
   }
//============== A MATRIX ==============
   if(level >= 4)
   {
       printf(" Constraint Matrix \n");
       tableau_out(s);
       printf("======================================\n");
   }
   fclose (output);
   return;
}

/************************************************************************
* retroLP solves linear programs using the simplex method.             *
* Copyright (C) 2001, 2003, 2005 Gavriel Yarmish & Richard Van Slyke.  *
*                                                                      *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or    *
* (at your option) any later version.                                  *
*                                                                      *
* This program is distributed in the hope that it will be useful,      *
* but WITHOUT ANY WARRANTY; without even the implied warranty of       *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
* GNU General Public License for more details.                         *
*                                                                      *
* You should have received a copy of the GNU General Public License    *  
* along with this program; if not, write to the Free Software          *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,           *
*                                                                      *
************************************************************************/
