/********************************************************
  Xpress-BCL Java Example Problems
  ================================

  file xbdelvr.java
  `````````````````
  Transportation problem.

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2000, rev. Mar. 2011
********************************************************/

import java.io.*;
import com.dashoptimization.*;

public class xbdelvr
{
 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, 600.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[] = {123.3,  56.4,  17.1, 192.8, 310.0,  47.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() throws IOException
 {
  XPRBexpr lobj, lc;
  int s,c;
  XPRBvar[][] x;
 
  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<NCust; c++)          /* Satisfy demand of each customer */
  {
   lc = new XPRBexpr();
   for(s=0;s<NSupp;s++)  lc.add(x[s][c]);
   p.newCtr("Demand", lc.gEql(DEMAND[c]));
  }
        
  for(s=0;s<NSupp;s++)            /* Keep within supply at each supplier*/
  {
   lc = new XPRBexpr();
   for(c=0; 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.exportProb(XPRB.MPS,"delivery");  /* Write out an MPS file */

  p.setSense(XPRB.MINIM);          /* Set objective sense to minimization */
  p.lpOptimize("");                /* Solve the LP-problem */
  System.out.println("Objective: " + p.getObjVal());  /* Get objective value */
    
  for(s=0;s<NSupp;s++)             /* Print out the solution values */
   for(c=0; c<NCust; c++)
    System.out.print(x[s][c].getName() +":"+ x[s][c].getSol() +" ");
  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 */
   modDelivery();        /* Problem formulation and solution */
  }
  catch(IOException e)
  {
   System.err.println(e.getMessage());
   System.exit(1);
  }
 }
} 
