/********************************************************
  Xpress-BCL Java Example Problems
  ================================

  file xbdlvriis.java
  ```````````````````
  Transportation problem (infeasible data).
  Retrieving and printing IIS.

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, 2005, rev. Mar. 2011
********************************************************/

import java.io.*;
import java.util.*;
import com.dashoptimization.*;

public class xbdlvriis
{
 static final int NSupp = 10;     /* Number of suppliers */
 static final int NCust = 7;      /* Number of customers */
 static final int MaxArcs = 100;  /* Max. num. of non-zero cost values */

 static final String VANFILE = System.getProperty("XPRBDATA") + 
   "/delivery/ifvan.dat";
 static final String COSTFILE = System.getProperty("XPRBDATA") + 
   "/delivery/cost.dat";

/****DATA****/
/* Supplier:                    London  Luton  B'ham Bristl  Derby Stckpt */
 static final double SUPPLY[] = {140.0, 200.0,  50.0,  10.0, 400.0, 200.0,  
/* Supplier:                     York  Derby Soton Scnthp */
                                 20.0, 90.0,  30.0,  12.0};
/* Customer:                     London Livpol Doncst   York   Hull  Manchr */
 static final double DEMAND[] = {1230.3, 560.4, 117.1, 592.8, 310.0, 1247.0, 
/* Customer:                     Shffld */    
                                 86.0};

 static double[][] COST;          /* Cost per supplier-customer pair */
 static double[][] IFVAN;         /* Non-zero if route uses vans instead 
                                     of lorries */
 static final double VANCAP=40.0; /* Capacity on routes that use vans */

 static XPRB bcl;
 static XPRBprob p;

/***********************************************************************/

 static void modDelivery()
 {
  XPRBexpr lobj, lc;
  int s,c,i;
  XPRBvar[][] x;
  ArrayList iisctr,iisvar;
  int numv, numc, numiis, ct;
 
  bcl = new XPRB();               /* Initialize BCL */
  p = bcl.newProb("Delivery");    /* Create a new problem in BCL */

/****VARIABLES****/
  x = new XPRBvar[NSupp][NCust];
  for(s=0;s<NSupp;s++)
   for(c=0; c<NCust; c++)
    x[s][c] = p.newVar("x_s" + s);
     
/****OBJECTIVE****/
  lobj = new XPRBexpr();
  for(s=0;s<NSupp;s++)            /* Objective: Minimize total cost */
   for(c=0; c<NCust; c++)
    lobj.add(x[s][c].mul(COST[s][c]));
  p.setObj(lobj); /* Set objective function */ 

/****CONSTRAINTS****/  
  for(c=0; c<4; c++)              /* Satisfy demand of each customer */
  {
   lc = new XPRBexpr();
   for(s=0;s<5;s++)  lc.add(x[s][c]);
   p.newCtr("Demand", lc.gEql(DEMAND[c]));
  }
  for(c=4; c<NCust; c++)          /* Satisfy demand of each customer */
  {
   lc = new XPRBexpr();
   for(s=5;s<NSupp;s++)  lc.add(x[s][c]);
   p.newCtr("Demand", lc.gEql(DEMAND[c]));
  }
        
  for(s=0;s<5;s++)                /* Keep within supply at each supplier*/
  {
   lc = new XPRBexpr();
   for(c=0; c<4; c++)  lc.add(x[s][c]);
   p.newCtr("Supply", lc.lEql(SUPPLY[s]) );
  }          
  for(s=5;s<NSupp;s++)            /* Keep within supply at each supplier*/
  {
   lc = new XPRBexpr();
   for(c=4; c<NCust; c++)  lc.add(x[s][c]);
   p.newCtr("Supply", lc.lEql(SUPPLY[s]) );
  }  
 
/****BOUNDS****/
  for(s=0;s<NSupp;s++)
   for(c=0; c<NCust; c++)
    if(IFVAN[s][c]!=0) x[s][c].setUB(VANCAP);

/****SOLVING + OUTPUT****/
  p.setSense(XPRB.MINIM);          /* Set objective sense to minimization */
  p.lpOptimize("");                /* Solve the LP-problem */

  System.out.println("LP status: " + p.getLPStat());
  if (p.getLPStat()==XPRB.LP_OPTIMAL)
   System.out.println("Objective: " + p.getObjVal()); /* Get objective value */
  else if (p.getLPStat()==XPRB.LP_INFEAS)
  {
   numiis = p.getNumIIS();         /* Get the number of independent IIS */
   System.out.println("Number of IIS: " + numiis); 

   iisvar = new ArrayList();
   iisctr = new ArrayList();

   for(s=1;s<=numiis;s++)
   { 
    p.getIIS(iisvar, iisctr, s);
    numv = iisvar.size(); numc = iisctr.size();
    System.out.println("IIS " + s + ":  " + numv + " variables, " +
                       numc + " constraints");
    if (numv>0)
    {                              /* Print all variables in the IIS */
     System.out.print("        Variables: ");
     for(i=0;i<numv;i++) 
      System.out.print(((XPRBvar)iisvar.get(i)).getName() + " ");
     System.out.println();
    } 
    if (numc>0)
    {                              /* Print all constraints in the IIS */
     System.out.print("        Constraints: ");
     for(i=0;i<numc;i++) 
      System.out.print(((XPRBctr)iisctr.get(i)).getName() + " ");
     System.out.println();
    } 
   }

/* Alternative way of enumerating IIS: */
  p.getIIS(iisvar, iisctr, 0);
  numv = iisvar.size(); numc = iisctr.size();
  System.out.println("IIS approximation:  " + numv + " variables, " + numc + " constraints with non-zero reduced cost/dual values");
  ct=0;
  while(numv+numc>0)
  {
   if(ct>0)
    System.out.println("IIS " + ct + ":  " + numv + " variables, " + numc + " constraints");
   ct++;  
   p.getIIS(iisvar, iisctr, ct);
   numv = iisvar.size(); numc = iisctr.size();
  }
   
/* Retrieve variables only */
   System.out.println("Variables");
   for(s=1;s<=numiis;s++)
   { 
    p.getIIS(iisvar, null, s);
    numv = iisvar.size(); 
    System.out.print("  IIS " + s + ":  " + numv + " variables  ( " );
    for(i=0;i<numv;i++) 
     System.out.print(((XPRBvar)iisvar.get(i)).getName() + " ");
     System.out.println(")");
   }

/* Retrieve constraints only */    
   System.out.println("Constraints");
   for(s=1;s<=numiis;s++)
   { 
    p.getIIS(null, iisctr, s);
    numc = iisctr.size();
    System.out.print("  IIS " + s + ":  " + numc + " constraints  ( ");
    for(i=0;i<numc;i++) 
     System.out.print(((XPRBctr)iisctr.get(i)).getName() + " ");
    System.out.println(")");
   } 
     
  }
 }

/***********************************************************************/

    /**** Initialize the stream tokenizer ****/
 static StreamTokenizer initST(FileReader file)
 {
  StreamTokenizer st=null;

  st= new StreamTokenizer(file);   /* Initialize the stream tokenizer */
  st.commentChar('!');             /* Use the character '!' for comments */
  st.eolIsSignificant(true);       /* Return end-of-line character */
  st.ordinaryChar(',');            /* Use ',' as separator */
  st.parseNumbers();               /* Read numbers as numbers (not strings)*/ 
  return st;
 }

    /**** Read multi line data file ****/
 static void readMultiLineFile(String filename, double[][] data) throws IOException
 {
  FileReader datafile=null;
  StreamTokenizer st;
  int i=0, j=0;

  datafile = new FileReader(filename);
  st = initST(datafile);
  do
  {
   do
   { 
    st.nextToken();
   } while(st.ttype==st.TT_EOL);    /* Skip empty lines */
   while(st.ttype == st.TT_NUMBER)
   {
    data[j][i++] = st.nval;
    if(st.nextToken() != ',') { j++; i=0; break;}
    st.nextToken();
   }
  } while( st.ttype == st.TT_EOL );
  datafile.close(); 
 }

    /**** Read data from files ****/
 static void readData() throws IOException
 {
  int s,c;  

  COST = new double[NSupp][NCust];
  IFVAN = new double[NSupp][NCust];
 
/* Initialize data tables to 0: in the van data file some entries that are 
 * zero are simply left out (that is, the lines are incomplete) */
  for(s=0;s<NSupp;s++)
   for(c=0; c<NCust; c++)
   {
    COST[s][c] = 0;
    IFVAN[s][c] = 0;
   }  
        /* Read the demand data file */
 readMultiLineFile(COSTFILE,COST);

        /* Read the van data file */
 readMultiLineFile(VANFILE,IFVAN);
}

/***********************************************************************/

 public static void main(String[] args)
 {
  try
  {
   readData();           /* Data input from file */
  }
  catch(IOException e)
  {
   System.err.println(e.getMessage());
   System.exit(1);
  }
  modDelivery();         /* Problem formulation and solution */
 }
} 
