Initializing help system before first use

Coco - A full production planning example


Type: Production planning
Rating: 2 (easy-medium)
Description: The Coco productional planning problem: multi-item, multi-period, multi-site production planning. A sequence of model versions show how the model was developed, to (a) use more sophisticated modeling features and (b) to extend the model, taking it from a simple linear model to one with fixed prices and logical decisions.
  1. xbcoco1: initial formulation, data, variables and constraints fixed
  2. xbcoco2: use parameters, data tables and subscripted variables.
    read data tables in from text data files (short-term planning).
  3. xbcoco3: like xbcoco2.c, but several time periods (mid-term planning).
  4. xbcoco : complete problem, data defined in the model definition (long-term planning).
File(s): xbcoco1.cxx, xbcoco2.cxx, xbcoco3.cxx, xbcoco.cxx
Data file(s): rev.dat, cmake.dat, cbuy.dat, req.dat, maxsell.dat, mxmake.dat, revt.dat, cbuyt.dat, maxsellt.dat, pstock0.dat, rstock0.dat


xbcoco1.cxx
/********************************************************
  Xpress-BCL C++ Example Problems
  ===============================

  file xbcoco1.cxx
  ````````````````
  Coco Problem Phase 1. 
  Initial formulation: data, variables and 
  constraints fixed.

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2000, rev. Mar. 2011
********************************************************/

#include <iostream>
#include "xprb_cpp.h"

using namespace std;
using namespace ::dashoptimization;

int main(int argc, char **argv)
{
 XPRBvar make11,make21,make12,make22;
 XPRBprob p("Coco1");         /* Initialize a new problem in BCL */

/****VARIABLES****/
 make11 = p.newVar("make11"); /* Amount of prod. 1 to make at factory 1 */
 make21 = p.newVar("make21"); /* Amount of prod. 2 to make at factory 1 */
 make12 = p.newVar("make12"); /* Amount of prod. 1 to make at factory 2 */
 make22 = p.newVar("make22"); /* Amount of prod. 2 to make at factory 2 */

/****OBJECTIVE****/
              /* Define & set objective function: maximize total profit */ 
 p.setObj(p.newCtr("OBJ", 50*make11 + 125*make21 + 47*make12 + 132*make22));

/****CONSTRAINTS****/
 p.newCtr("MxMake1", make11+make21 <= 400);  /* Capacity limit at factory 1 */

 p.newCtr("MxMake2", make12+make22 <= 500);  /* Capacity limit at factory 2 */

 p.newCtr("MxSell1", make11+make12 <= 650);  /* Limit on the amount of 
                                                prod. 1 to be sold */

 p.newCtr("MxSell2", make21+make22 <= 600);  /* Limit on the amount of 
                                                prod. 2 to be sold */

/****SOLVING + OUTPUT****/
 p.setSense(XPRB_MAXIM);      /* Choose the sense of the optimization */
 p.lpOptimize("");            /* Solve the LP-problem */
 cout << "Objective: " << p.getObjVal() << endl;   /* Get objective value */

               /* Print out the solution values for all variables */
 cout << make11.getName() << ": " << make11.getSol() << endl;
 cout << make21.getName() << ": " << make21.getSol() << endl;
 cout << make12.getName() << ": " << make12.getSol() << endl;
 cout << make22.getName() << ": " << make22.getSol() << endl;
 
 return 0;
} 

xbcoco2.cxx
/********************************************************
  Xpress-BCL C++ Example Problems
  ===============================

  file xbcoco2.cxx
  `````````````````
  Coco Problem Phase 2. 
  Use parameters, data tables and subscripted variables
  to separate the model structure from the data. 
  Read data tables in from text data files.

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2000, rev. Mar. 2011
********************************************************/

#include <iostream>
#include <cstdio>
#include "xprb_cpp.h"

using namespace std;
using namespace ::dashoptimization;

#define NP 2            /* Number of products (p) */
#define NF 2            /*           factories (f) */
#define NR 2            /*           raw materials (r) */

#define REVFILE     XPRBDATAPATH "/coco/rev.dat"
#define CMAKEFILE   XPRBDATAPATH "/coco/cmake.dat"
#define CBUYFILE    XPRBDATAPATH "/coco/cbuy.dat"
#define REQFILE     XPRBDATAPATH "/coco/req.dat"
#define MXSELLFILE  XPRBDATAPATH "/coco/maxsell.dat"
#define MXMAKEFILE  XPRBDATAPATH "/coco/mxmake.dat"

/****TABLES****/
double REV[NP];         /* Unit selling price of product p */
double CMAK[NP][NF];    /* Unit cost to make product p at factory f */
double CBUY[NR];        /* Unit cost to buy raw material r */
double REQ[NP][NR];     /* Requirement by unit of prod. p for raw material r */
double MXSELL[NP];      /* Max. amount of p that can be sold */
double MXMAKE[NF];      /* Max. amount factory f can make over all products */
double PROFIT[NP][NF];  /* Profit contribution of product p at factory f */

XPRBprob pb("Coco2");   /* Initialize a new problem in BCL */
 
/***********************************************************************/

void modCoco2()
{
 XPRBvar make[NP][NF];
 XPRBexpr lobj, lc;
 int p,f;
 
/****VARIABLES****/
 for(p=0;p<NP;p++)         /* Amount of prod. p to make at factory f */
  for(f=0;f<NF;f++)   
   make[p][f] = pb.newVar(XPRBnewname("make_p%df%d",p+1,f+1));    

/****OBJECTIVE****/
 for(p=0;p<NP;p++)         /* Objective: maximize total profit */
  for(f=0;f<NF;f++)  lobj += PROFIT[p][f]* make[p][f]; 
 pb.setObj(pb.newCtr("OBJ",lobj)); 

/****CONSTRAINTS****/
   
 for(p=0;p<NP;p++)         /* Limit on the amount of product p to be sold */
 {
  lc=0;
  for(f=0;f<NF;f++)  lc += make[p][f];
  pb.newCtr("MxSell", lc <= MXSELL[p]);
 }   

 for(f=0;f<NF;f++)         /* Capacity limit at factory f */
 {
  lc=0;
  for(p=0;p<NP;p++) lc += make[p][f];
  pb.newCtr("MxMake", lc <= MXMAKE[f]);      
 }

/****SOLVING + OUTPUT****/
 pb.setSense(XPRB_MAXIM);  /* Choose the sense of the optimization */
 pb.lpOptimize("");        /* Solve the LP-problem */
 cout << "Objective: " << pb.getObjVal() << endl;  /* Get objective value */
    
 for(p=0;p<NP;p++)         /* Print the solution values */      
  for(f=0;f<NF;f++)   
   cout << make[p][f].getName() << ":" << make[p][f].getSol() << " ";
 cout << endl;
}

/***********************************************************************/

    /**** Read data from files ****/
void readData()
{
 FILE *datafile;
 int p,f,r;
        /* Read the revenu data file */
 datafile=fopen(REVFILE,"r");
 XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", REV, NP);
 fclose(datafile);

        /* Read the production cost data file */
 datafile=fopen(CMAKEFILE,"r");
 for(p=0;p<NP;p++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", CMAK[p], NF);
 fclose(datafile);

        /* Read the raw material cost data file */
 datafile=fopen(CBUYFILE,"r");
 XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", CBUY, NR);
 fclose(datafile);

        /* Read the resource requirement data file */
 datafile=fopen(REQFILE,"r");
 for(p=0;p<NP;p++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", REQ[p], NR);
 fclose(datafile);
  
        /* Read the max. sales quantities data file */
 datafile=fopen(MXSELLFILE,"r");
 XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", MXSELL, NP);
 fclose(datafile);
  
        /* Read the production capacities data file */
 datafile=fopen(MXMAKEFILE,"r");
 XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", MXMAKE, NF);
 fclose(datafile);
 
        /* Calculate the table PROFIT */
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)
  {
   PROFIT[p][f] = REV[p] - CMAK[p][f];
   for(r=0;r<NR;r++) PROFIT[p][f] -= (REQ[p][r]*CBUY[r]);
  }
}

/***********************************************************************/

int main(int argc, char **argv)
{
 readData();            /* Data input from file */
 modCoco2();            /* Model and solve the problem */
  
 return 0;
} 

xbcoco3.cxx
/********************************************************
  Xpress-BCL C++ Example Problems
  ===============================

  file xbcoco3.cxx
  `````````````````
  Coco Problem Phase 3. 
  Introduce time periods and inventory.

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2000, rev. Mar. 2011
********************************************************/

#include <iostream>
#include <cstdio>
#include "xprb_cpp.h"

using namespace std;
using namespace ::dashoptimization;

#define NP 2           /* Number of products (p) */
#define NF 2           /* Factories (f) */
#define NR 2           /* Raw materials (r) */
#define NT 4           /* Time periods (t) */

#define REVFILE     XPRBDATAPATH "/coco/revt.dat"
#define CMAKEFILE   XPRBDATAPATH "/coco/cmake.dat"
#define CBUYFILE    XPRBDATAPATH "/coco/cbuyt.dat"
#define REQFILE     XPRBDATAPATH "/coco/req.dat"
#define MXSELLFILE  XPRBDATAPATH "/coco/maxsellt.dat"
#define MXMAKEFILE  XPRBDATAPATH "/coco/mxmake.dat"
#define PSTOCK0FILE XPRBDATAPATH "/coco/pstock0.dat"
#define RSTOCK0FILE XPRBDATAPATH "/coco/rstock0.dat"

/****TABLES****/
double REV[NP][NT];     /* Unit selling price of product p in period t */
double CMAK[NP][NF];    /* Unit cost to make product p at factory f */
double CBUY[NR][NT];    /* Unit cost to buy raw material r in period t */
double REQ[NP][NR];     /* Requirement by unit of prod. p for raw material r */
double MXSELL[NP][NT];  /* Max. amount of p that can be sold in period t */
double MXMAKE[NF];      /* Max. amount factory f can make over all products */
double PSTOCK0[NP][NF]; /* Initial product p stock level at factory f */
double RSTOCK0[NR][NF]; /* Initial raw material r stock level at factory f*/

/****DATA****/
double CPSTOCK = 2.0;   /* Unit cost to store any product p */
double CRSTOCK = 1.0;   /* Unit cost to store any raw material r */
double MXRSTOCK = 300;  /* Max. amount of r that can be stored each f and t */

XPRBprob pb("Coco3");   /* Initialize a new problem in BCL */
 
/***********************************************************************/

void modCoco3()
{
 XPRBvar make[NP][NF][NT], sell[NP][NF][NT], pstock[NP][NF][NT+1],
       buy[NR][NF][NT], rstock[NR][NF][NT+1];
 XPRBexpr lobj, lc;
 int p,f,r,t;
 
/****VARIABLES****/
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
   {
    make[p][f][t] = pb.newVar(XPRBnewname("make_p%d_f%d",p+1,f+1));
        /* Amount of prod. p to make at factory f in period t */
    sell[p][f][t] = pb.newVar(XPRBnewname("sell_p%d_f%d",p+1,f+1));
        /* Amount of prod. p sold from factory f in period t */
   }        
   for(t=0;t<NT+1;t++)
    pstock[p][f][t] = pb.newVar(XPRBnewname("pstock_p%d_f%d",p+1,f+1));
        /* Stock level of prod. p at factory f at start of period t */
  }     
 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
    buy[r][f][t] = pb.newVar(XPRBnewname("buy_r%d_f%d",r+1,f+1));
        /* Amount of raw material r bought for factory f in period t */
   for(t=0;t<NT+1;t++)
    rstock[r][f][t] = pb.newVar(XPRBnewname("rstock_r%d_f%d",r+1,f+1));
        /* Stock level of raw mat. r at factory f at start of per. t */
  }
        
/****OBJECTIVE****/
 for(f=0;f<NF;f++)        /* Objective: maximize total profit */
 {
  for(p=0;p<NP;p++)
  {
   for(t=0;t<NT;t++)
    lobj += REV[p][t]*sell[p][f][t] - CMAK[p][f]*make[p][f][t];
   for(t=1;t<NT+1;t++)  lobj -= CPSTOCK*pstock[p][f][t];    
  }
  for(r=0;r<NR;r++)
  {
   for(t=0;t<NT;t++)  lobj -= CBUY[r][t]*buy[r][f][t];
   for(t=1;t<NT+1;t++)  lobj -= CRSTOCK*rstock[r][f][t];    
  }
 } 
 pb.setObj(pb.newCtr("OBJ",lobj));   /* Set objective function */  
 
/****CONSTRAINTS****/
 for(p=0;p<NP;p++)        /* Product stock balance */
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
    pb.newCtr("PBal", 
     pstock[p][f][t]+make[p][f][t] == sell[p][f][t]+pstock[p][f][t+1] ); 

 for(r=0;r<NR;r++)        /* Raw material stock balance */
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
   {                 
    lc=0;
    for(p=0;p<NP;p++)  lc += REQ[p][r]*make[p][f][t];
    pb.newCtr("RBal", rstock[r][f][t]+buy[r][f][t] == lc+rstock[r][f][t+1]);
   }

 for(p=0;p<NP;p++)
  for(t=0;t<NT;t++)
  {                       /* Limit on the amount of product p to be sold */ 
   lc=0;
   for(f=0;f<NF;f++)  lc += sell[p][f][t];
   pb.newCtr("MxSell", lc <= MXSELL[p][t]);  
  }
    
 for(f=0;f<NF;f++)
  for(t=0;t<NT;t++)
  {                       /* Capacity limit at factory f */
   lc=0;
   for(p=0;p<NP;p++)  lc += make[p][f][t];
   pb.newCtr("MxMake", lc <= MXMAKE[f]);
  }

 for(f=0;f<NF;f++)
  for(t=1;t<NT+1;t++)
  {                       /* Raw material stock limit */        
   lc=0;
   for(r=0;r<NR;r++) lc += rstock[r][f][t];
   pb.newCtr("MxRStock", lc <= MXRSTOCK);    
  }

/****BOUNDS****/
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)
   pstock[p][f][0].fix(PSTOCK0[p][f]);    /* Initial product levels */

 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
   rstock[r][f][0].fix(RSTOCK0[r][f]);    /* Initial raw mat. levels */

/****SOLVING + OUTPUT****/
 pb.setSense(XPRB_MAXIM); /* Choose the sense of the optimization */
 pb.lpOptimize("");       /* Solve the LP-problem */
 cout << "Objective: " << pb.getObjVal() << endl;   /* Get objective value */
    
                          /* Uncomment to print out the solution values */
/* for(p=0;p<NP;p++)        
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
     cout << make[p][f][t].getName() << ":" << make[p][f][t].getSol() << " " <<
     sell[p][f][t].getName() << ":" << sell[p][f][t].getSol()) << "  ";
   for(t=0;t<NT+1;t++) 
    cout << pstock[p][f][t].getName() << ":" << pstock[p][f][t].getSol() << " ";
  }
 cout << endl; 

 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
    cout << buy[r][f][t].getName() << ":" << buy[r][f][t].getSol() << " ";
   for(t=0;t<NT+1;t++)
    cout << rstock[r][f][t].getName() << ":" << rstock[r][f][t].getSol() << " ";
  }  
 cout << endl;
*/ 
}

/***********************************************************************/

    /**** Read data from files ****/
void readData()
{
 FILE *datafile;
 int p,r;
        /* Read the revenu data file */
 datafile=fopen(REVFILE,"r");
 for(p=0;p<NP;p++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", REV[p], NT);
 fclose(datafile);

        /* Read the production cost data file */
 datafile=fopen(CMAKEFILE,"r");
 for(p=0;p<NP;p++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", CMAK[p], NF);
 fclose(datafile);

        /* Read the raw material cost data file */
 datafile=fopen(CBUYFILE,"r");
 for(r=0;r<NR;r++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", CBUY[r], NT);
 fclose(datafile);

        /* Read the resource requirement data file */
 datafile=fopen(REQFILE,"r");
 for(p=0;p<NP;p++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", REQ[p], NR);
 fclose(datafile);
  
        /* Read the max. sales quantities data file */
 datafile=fopen(MXSELLFILE,"r");
 for(p=0;p<NP;p++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", MXSELL[p], NT);
 fclose(datafile);
  
        /* Read the production capacities data file */
 datafile=fopen(MXMAKEFILE,"r");
 XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", MXMAKE, NF);
 fclose(datafile);
 
        /* Read the product stock data file */
 datafile=fopen(PSTOCK0FILE,"r");
 for(p=0;p<NP;p++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", PSTOCK0[p], NF);
 fclose(datafile);

        /* Read the raw material stock data file */
 datafile=fopen(RSTOCK0FILE,"r");
 for(r=0;r<NR;r++)
  XPRBreadarrlinecb(XPRB_FGETS, datafile, 200, "g,", RSTOCK0[r], NF);
 fclose(datafile);
}

/***********************************************************************/

int main(int argc, char **argv)
{
 readData();            /* Data input from file */
 modCoco3();            /* Model and solve the problem */
  
 return 0;
} 

xbcoco.cxx
/********************************************************
  Xpress-BCL C++ Example Problems
  ===============================

  file xbcoco.cxx
  ```````````````
  Complete Coco Problem. 
  Specify phase by PHASE parameter.
  Data input in the model, not via data files.

  (c) 2008 Fair Isaac Corporation
      author: S.Heipcke, Jan. 2000, rev. Mar. 2011
********************************************************/

#include <iostream>
#include "xprb_cpp.h"

using namespace std;
using namespace ::dashoptimization;

#define PHASE 5
/* Phase = 3: Multi-period parameterised model; mines always open
 * Phase = 4: Mines may open/closed freely; when closed save 20000 per month
 * Phase = 5: Once closed always closed; larger saving */
 
#define NP 2            /* Number of products (p) */
#define NF 2            /*           factories (f) */
#define NR 2            /*           raw materials (r) */
#define NT 4            /*           time periods (t) */

/****DATA****/
double REV[][NT] =      /* Unit selling price of product p in period t */
        {{400, 380, 405, 350},
         {410, 397, 412, 397}};
double CMAK[][NF] =     /* Unit cost to make product p at factory f */
        {{150, 153},
         { 75,  68}};
double CBUY[][NT] =     /* Unit cost to buy raw material r in period t */
        {{100,  98,  97, 100},
         {200, 195, 198, 200}};
double COPEN[] =        /* Fixed cost of factory f being open for one period */
        {50000, 63000};
double CPSTOCK = 2.0;   /* Unit cost to store any product p */
double CRSTOCK = 1.0;   /* Unit cost to store any raw material r */
double REQ[][NR] =      /* Requirement by unit of prod. p for raw material r */
        {{1.0, 0.5},
         {1.3, 0.4}};
double MXSELL[][NT] =   /* Max. amount of p that can be sold in period t */
        {{650, 600, 500, 400},
         {600, 500, 300, 250}};
double MXMAKE[] =       /* Max. amount factory f can make over all products */
        {400, 500};
double MXRSTOCK = 300;  /* Max. amount of r that can be stored each f and t */
double PSTOCK0[][NF] =  /* Initial product p stock level at factory f */
        {{50, 100},
         {50,  50}};
double RSTOCK0[][NF] =  /* Initial raw material r stock level at factory f*/
        {{100, 150},
         { 50, 100}};
 
/***********************************************************************/

int main(int argc, char **argv)
{
 XPRBvar make[NP][NF][NT], sell[NP][NF][NT], pstock[NP][NF][NT+1],
       buy[NR][NF][NT], rstock[NR][NF][NT+1], openm[NF][NT];
 XPRBexpr lobj, lc;
 int p,f,r,t; 
 XPRBprob pb("Coco");   /* Initialize a new problem in BCL */

/****VARIABLES****/
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
   {
    make[p][f][t] = pb.newVar(XPRBnewname("make_p%d_f%d",p+1,f+1));
        /* Amount of prod. p to make at factory f in period t */
    sell[p][f][t] = pb.newVar(XPRBnewname("sell_p%d_f%d",p+1,f+1));
        /* Amount of prod. p sold from factory f in period t */
   }        
   for(t=0;t<NT+1;t++)
    pstock[p][f][t] = pb.newVar(XPRBnewname("pstock_p%d_f%d",p+1,f+1));
        /* Stock level of prod. p at factory f at start of period t */
  }     
 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
    buy[r][f][t] = pb.newVar(XPRBnewname("buy_r%d_f%d",r+1,f+1));
        /* Amount of raw material r bought for factory f in period t */
   for(t=0;t<NT+1;t++)
    rstock[r][f][t] = pb.newVar(XPRBnewname("rstock_r%d_f%d",r+1,f+1));
        /* Stock level of raw mat. r at factory f at start of per. t */
  }
  
 for(f=0;f<NF;f++)
  for(t=0;t<NT;t++)
   openm[f][t] = pb.newVar(XPRBnewname("open_f%d",f+1), XPRB_BV);
        /* 1 if factory f is open in period t, else 0 */
            
/****OBJECTIVE****/
 for(f=0;f<NF;f++)        /* Objective: maximize total profit */
 {
  for(p=0;p<NP;p++)
  {
   for(t=0;t<NT;t++)
    lobj += REV[p][t]*sell[p][f][t] - CMAK[p][f]*make[p][f][t];
   for(t=1;t<NT+1;t++)  lobj -= CPSTOCK*pstock[p][f][t];    
  } 
  if(PHASE==4)
   for(t=0;t<NT;t++)  lobj += (20000-COPEN[f])*openm[f][t];
  else if(PHASE==5)
   for(t=0;t<NT;t++)  lobj -= COPEN[f]*openm[f][t];
  for(r=0;r<NR;r++)
  {
   for(t=0;t<NT;t++)  lobj -= CBUY[r][t]*buy[r][f][t];
   for(t=1;t<NT+1;t++)  lobj -= CRSTOCK*rstock[r][f][t];    
  }
 } 
 pb.setObj(pb.newCtr("OBJ",lobj));   /* Set objective function */  
 
/****CONSTRAINTS****/
 for(p=0;p<NP;p++)        /* Product stock balance */  
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
    pb.newCtr("PBal", 
     pstock[p][f][t]+make[p][f][t] == sell[p][f][t]+pstock[p][f][t+1] ); 
     
 for(r=0;r<NR;r++)        /* Raw material stock balance */
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
   {                 
    lc=0;
    for(p=0;p<NP;p++)  lc += REQ[p][r]*make[p][f][t];
    pb.newCtr("RBal", rstock[r][f][t]+buy[r][f][t] == lc+rstock[r][f][t+1]);
   }

 for(p=0;p<NP;p++)
  for(t=0;t<NT;t++)
  {                       /* Limit on the amount of product p to be sold */     
   lc=0;
   for(f=0;f<NF;f++)  lc += sell[p][f][t];
   pb.newCtr("MxSell", lc <= MXSELL[p][t]);  
  }
    
 for(f=0;f<NF;f++)
  for(t=0;t<NT;t++)
  {                       /* Capacity limit at factory f */
   lc=0;
   for(p=0;p<NP;p++)  lc += make[p][f][t];
   pb.newCtr("MxMake", lc <= MXMAKE[f]*openm[f][t]);
  }

 for(f=0;f<NF;f++)
  for(t=1;t<NT+1;t++)
  {                       /* Raw material stock limit */        
   lc=0;
   for(r=0;r<NR;r++) lc += rstock[r][f][t];
   pb.newCtr("MxRStock", lc <= MXRSTOCK);    
  }

 if(PHASE==5)
  for(f=0;f<NF;f++)
   for(t=0;t<NT-1;t++)    /* Once closed, always closed */
    pb.newCtr("Closed", openm[f][t+1] <= openm[f][t]); 

/****BOUNDS****/
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)
   pstock[p][f][0].fix(PSTOCK0[p][f]);    /* Initial product levels */

 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
   rstock[r][f][0].fix(RSTOCK0[r][f]);    /* Initial raw mat. levels */

 if(PHASE<=3)
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
    openm[f][t].fix(1);
   
/****SOLVING + OUTPUT****/
 pb.setSense(XPRB_MAXIM);  /* Choose the sense of the optimization */
 pb.mipOptimize("");       /* Solve the MIP-problem */
 cout << "Objective: " << pb.getObjVal() << endl;   /* Get objective value */
    
                           /* Uncomment to print out the solution values */
/* for(p=0;p<NP;p++)        
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
    cout << make[p][f][t].getName() << ":" << make[p][f][t].getSol() << " " <<
     sell[p][f][t].getName() << ":" << sell[p][f][t].getSol()) << "  ";
 cout << endl; 

 for(p=0;p<NP;p++)      
  for(f=0;f<NF;f++)
   for(t=0;t<NT+1;t++)
    cout << pstock[p][f][t].getName() << ":" << pstock[p][f][t].getSol() << " ";
 cout << endl; 
 
 for(r=0;r<NR;r++)      
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
    cout << buy[r][f][t].getName() << ":" << buy[r][f][t].getSol() << " ";
   for(t=0;t<NT+1;t++)
    cout << rstock[r][f][t].getName() << ":" << rstock[r][f][t].getSol() << " ";
  }
 for(f=0;f<NF;f++)
  for(t=0;t<NT;t++)
   cout << openm[f][t].getName() << ":" << openm[f][t].getSol() << " ";
 cout << endl; 
*/

 return 0;
}