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.c, xbcoco2.c, xbcoco3.c, xbcoco.c
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.c
/********************************************************
  BCL Example Problems
  ====================

  file xbcoco1.c
  ``````````````
  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 <stdio.h>
#include "xprb.h"

int main(int argc, char **argv)
{
 XPRBvar make11,make21,make12,make22;
 XPRBctr ctr;
 XPRBprob prob;

 prob=XPRBnewprob("Coco1");       /* Initialize a new problem in BCL */

/****VARIABLES****/
 make11=XPRBnewvar(prob,XPRB_PL,"make11",0,XPRB_INFINITY);  
                                  /* Amount of prod. 1 to make at factory 1 */
 make21=XPRBnewvar(prob,XPRB_PL,"make21",0,XPRB_INFINITY);
                                  /* Amount of prod. 2 to make at factory 1 */
 make12=XPRBnewvar(prob,XPRB_PL,"make12",0,XPRB_INFINITY);
                                  /* Amount of prod. 1 to make at factory 2 */
 make22=XPRBnewvar(prob,XPRB_PL,"make22",0,XPRB_INFINITY);
                                  /* Amount of prod. 2 to make at factory 2 */
/****OBJECTIVE****/
 ctr = XPRBnewctr(prob,"OBJ",XPRB_N); 
 XPRBaddterm(ctr, make11,  50);   /* Objective: maximize total profit */
 XPRBaddterm(ctr, make21, 125); 
 XPRBaddterm(ctr, make12,  47); 
 XPRBaddterm(ctr, make22, 132); 
 XPRBsetobj(prob,ctr);            /* Select objective function */ 

/****CONSTRAINTS****/
 ctr=XPRBnewctr(prob,"MxMake1",XPRB_L);  /* Capacity limit at factory 1 */
 XPRBaddterm(ctr, make11, 1);
 XPRBaddterm(ctr, make21, 1); 
 XPRBaddterm(ctr, NULL, 400);

 ctr=XPRBnewctr(prob,"MxMake2",XPRB_L);  /* Capacity limit at factory 2 */
 XPRBaddterm(ctr, make12, 1);
 XPRBaddterm(ctr, make22, 1); 
 XPRBaddterm(ctr, NULL, 500);

 ctr=XPRBnewctr(prob,"MxSell1",XPRB_L);  /* Limit on amount of prod. 1 to be sold */
 XPRBaddterm(ctr, make11, 1);
 XPRBaddterm(ctr, make12, 1); 
 XPRBaddterm(ctr, NULL, 650);

 ctr=XPRBnewctr(prob,"MxSell2",XPRB_L);  /* Limit on amount of prod. 2 to be sold */
 XPRBaddterm(ctr, make21, 1);
 XPRBaddterm(ctr, make22, 1); 
 XPRBaddterm(ctr, NULL, 600);

/****SOLVING + OUTPUT****/
 XPRBsetsense(prob, XPRB_MAXIM);      /* Choose the sense of optimization */
 XPRBlpoptimize(prob, "");            /* Solve the LP-problem */
 printf("Objective: %g\n", XPRBgetobjval(prob));   /* Get objective value */

    /* Print out the solution values for all variables */
 printf("%s: %g\n",XPRBgetvarname(make11),XPRBgetsol(make11));
 printf("%s: %g\n",XPRBgetvarname(make21),XPRBgetsol(make21));
 printf("%s: %g\n",XPRBgetvarname(make12),XPRBgetsol(make12));
 printf("%s: %g\n",XPRBgetvarname(make22),XPRBgetsol(make22));
 
 return 0;
} 

xbcoco2.c
/********************************************************
  BCL Example Problems
  ====================

  file xbcoco2.c
  ``````````````
  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 <stdio.h>
#include "xprb.h"

#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 */
 
/***********************************************************************/

void modcoco2(XPRBprob prob)
{
 XPRBvar make[NP][NF];
 XPRBctr ctr;
 int p,f;
 
/****VARIABLES****/
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)   
   make[p][f]=                   /* Amount of prod. p to make at factory f */
    XPRBnewvar(prob,XPRB_PL,XPRBnewname("make_p%df%d",p+1,f+1),0,XPRB_INFINITY);                                     
/****OBJECTIVE****/
 ctr = XPRBnewctr(prob,"OBJ",XPRB_N);  /* Objective: maximize total profit */
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++) XPRBaddterm(ctr,make[p][f],PROFIT[p][f]); 
 XPRBsetobj(prob,ctr);                 /* Select objective function */ 

/****CONSTRAINTS****/
            /* Limit on the amount of product p to be sold */   
 for(p=0;p<NP;p++)
 {
  ctr = XPRBnewctr(prob,"MxSell",XPRB_L);        
  for(f=0;f<NF;f++) XPRBaddterm(ctr,make[p][f],1);
  XPRBaddterm(ctr,NULL,MXSELL[p]);
 }   
            /* Capacity limit at factory f */
 for(f=0;f<NF;f++)
 {
  ctr=XPRBnewctr(prob,"MxMake",XPRB_L);      
  for(p=0;p<NP;p++)
   XPRBaddterm(ctr, make[p][f], 1);
  XPRBaddterm(ctr, NULL, MXMAKE[f]);
 }

/****SOLVING + OUTPUT****/
 XPRBsetsense(prob,XPRB_MAXIM);        /* Choose the sense of optimization */
 XPRBlpoptimize(prob, "");             /* Solve the LP-problem */
 printf("Objective: %g\n", XPRBgetobjval(prob));    /* Get objective value */
    
 for(p=0;p<NP;p++)      
  for(f=0;f<NF;f++)   
  { XPRBprintvar(make[p][f]); printf(" "); }  /* Print the solution values */
 printf("\n");
}

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

    /**** Read data from files ****/
void readdata(void)
{
 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)
{
 XPRBprob prob;

 prob=XPRBnewprob("Coco2");     /* Initialize a new problem in BCL */
 readdata();                    /* Data input from file */
 modcoco2(prob);                /* Model and solve the problem */
  
 return 0;
} 

xbcoco3.c
/********************************************************
  BCL Example Problems
  ====================

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

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

#include <stdio.h>
#include "xprb.h"

#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 */
 
/***********************************************************************/

void modcoco3(XPRBprob prob)
{
 XPRBvar make[NP][NF][NT], sell[NP][NF][NT], pstock[NP][NF][NT+1],
         buy[NR][NF][NT], rstock[NR][NF][NT+1];
 XPRBctr ctr;
 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]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("make_p%d_f%d",p+1,f+1), 
        0, XPRB_INFINITY);
        /* Amount of prod. p to make at factory f in period t */
    sell[p][f][t]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("sell_p%d_f%d",p+1,f+1), 
        0, XPRB_INFINITY);
        /* Amount of prod. p sold from factory f in period t */
   }        
   for(t=0;t<NT+1;t++)
    pstock[p][f][t]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("pstock_p%d_f%d",p+1,f+1), 
        0, XPRB_INFINITY);
        /* 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]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("buy_r%d_f%d",r+1,f+1), 
        0, XPRB_INFINITY);
        /* Amount of raw material r bought for factory f in period t */
   for(t=0;t<NT+1;t++)
    rstock[r][f][t]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("rstock_r%d_f%d",r+1,f+1), 
        0, XPRB_INFINITY);
        /* Stock level of raw mat. r at factory f at start of per. t */
  }
        
/****OBJECTIVE****/
 ctr = XPRBnewctr(prob,"OBJ",XPRB_N); 
 for(f=0;f<NF;f++)                     /* Objective: maximize total profit */
 {
  for(p=0;p<NP;p++)
  {
   for(t=0;t<NT;t++)
   {
    XPRBaddterm(ctr, sell[p][f][t], REV[p][t]);
    XPRBaddterm(ctr, make[p][f][t], -1*CMAK[p][f]);
   } 
   for(t=1;t<NT+1;t++)
    XPRBaddterm(ctr, pstock[p][f][t], -1*CPSTOCK);    
  }
  for(r=0;r<NR;r++)
  {
   for(t=0;t<NT;t++)
    XPRBaddterm(ctr, buy[r][f][t], -1*CBUY[r][t]);
   for(t=1;t<NT+1;t++)
    XPRBaddterm(ctr, rstock[r][f][t], -1*CRSTOCK);    
  }
 } 
 XPRBsetobj(prob,ctr);                       /* Select objective function */  
 
/****CONSTRAINTS****/
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
   {                 
    ctr=XPRBnewctr(prob,"PBal",XPRB_E);      /* Product stock balance */  
    XPRBaddterm(ctr, pstock[p][f][t], 1);
    XPRBaddterm(ctr, make[p][f][t], 1);
    XPRBaddterm(ctr, sell[p][f][t], -1);
    XPRBaddterm(ctr, pstock[p][f][t+1], -1);
   }

 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
   {                 
    ctr=XPRBnewctr(prob,"RBal",XPRB_E);      /* Raw material stock balance */     
    XPRBaddterm(ctr, rstock[r][f][t], 1);
    XPRBaddterm(ctr, buy[r][f][t], 1);
    XPRBaddterm(ctr, rstock[r][f][t+1], -1);
    for(p=0;p<NP;p++) 
     XPRBaddterm(ctr, make[p][f][t], -1*REQ[p][r]);   
   }

 for(p=0;p<NP;p++)
  for(t=0;t<NT;t++)
  {         /* Limit on the amount of product p to be sold */ 
   ctr=XPRBnewctr(prob,"MxSell",XPRB_L);      
   for(f=0;f<NF;f++)
    XPRBaddterm(ctr, sell[p][f][t], 1);
   XPRBaddterm(ctr, NULL, MXSELL[p][t]);
  }
    
 for(f=0;f<NF;f++)
  for(t=0;t<NT;t++)
  {
   ctr=XPRBnewctr(prob,"MxMake",XPRB_L);     /* Capacity limit at factory f */
   for(p=0;p<NP;p++)
    XPRBaddterm(ctr, make[p][f][t], 1);
   XPRBaddterm(ctr, NULL, MXMAKE[f]);
  }

 for(f=0;f<NF;f++)
  for(t=1;t<NT+1;t++)
  {              
   ctr=XPRBnewctr(prob,"MxRStock",XPRB_L);   /* Raw material stock limit */   
   for(r=0;r<NR;r++) 
    XPRBaddterm(ctr, rstock[r][f][t], 1);
   XPRBaddterm(ctr, NULL, MXRSTOCK);
  }

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

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

/****SOLVING + OUTPUT****/
 XPRBsetsense(prob,XPRB_MAXIM);              /* Choose sense of optimization */
 XPRBlpoptimize(prob, "");                   /* Solve the LP-problem */
 printf("Objective: %g\n", XPRBgetobjval(prob));      /* 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++)
    printf("%s:%g %s:%g  ", XPRBgetvarname(make[p][f][t]), 
      XPRBgetsol(make[p][f][t]), XPRBgetvarname(sell[p][f][t]), 
      XPRBgetsol(sell[p][f][t]));
   for(t=0;t<NT+1;t++) 
    printf("%s:%g ", XPRBgetvarname(pstock[p][f][t]), XPRBgetsol(pstock[p][f][t]));
  }
 printf("\n");

 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
    printf("%s:%g ", XPRBgetvarname(buy[r][f][t]), XPRBgetsol(buy[r][f][t]));
   for(t=0;t<NT+1;t++) 
    printf("%s:%g ", XPRBgetvarname(rstock[r][f][t]), XPRBgetsol(rstock[r][f][t]));
  }  
 printf("\n");
*/ 
}

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

    /**** Read data from files ****/
void readdata(void)
{
 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)
{
 XPRBprob prob;

 prob=XPRBnewprob("Coco3");   /* Initialize a new problem in BCL */
 readdata();                  /* Data input from file */
 modcoco3(prob);              /* Model and solve the problem */
  
 return 0;
} 

xbcoco.c
/********************************************************
  BCL Example Problems
  ====================

  file xbcoco.c
  `````````````
  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 <stdio.h>
#include "xprb.h"

#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];
 XPRBctr ctr;
 int p,f,r,t;
 XPRBprob prob;

 prob=XPRBnewprob("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]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("make_p%d_f%d",p+1,f+1), 
        0, XPRB_INFINITY);
        /* Amount of prod. p to make at factory f in period t */
    sell[p][f][t]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("sell_p%d_f%d",p+1,f+1), 
        0, XPRB_INFINITY);
        /* Amount of prod. p sold from factory f in period t */
   }        
   for(t=0;t<NT+1;t++)
    pstock[p][f][t]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("pstock_p%d_f%d",p+1,f+1), 
        0, XPRB_INFINITY);
        /* 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]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("buy_r%d_f%d",r+1,f+1), 
        0, XPRB_INFINITY);
        /* Amount of raw material r bought for factory f in period t */
   for(t=0;t<NT+1;t++)
    rstock[r][f][t]=XPRBnewvar(prob,XPRB_PL, XPRBnewname("rstock_r%d_f%d",r+1,f+1), 
        0, XPRB_INFINITY);
        /* 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]=XPRBnewvar(prob,XPRB_BV, XPRBnewname("open_f%d",f+1), 0, 1);
        /* 1 if factory f is open in period t, else 0 */
            
/****OBJECTIVE****/
 ctr = XPRBnewctr(prob,"OBJ",XPRB_N); 
 for(f=0;f<NF;f++)                  /* Objective: maximize total profit */
 {
  for(p=0;p<NP;p++)
  {
   for(t=0;t<NT;t++)
   {
    XPRBaddterm(ctr, sell[p][f][t], REV[p][t]);
    XPRBaddterm(ctr, make[p][f][t], -1*CMAK[p][f]);
   } 
   for(t=1;t<NT+1;t++)
    XPRBaddterm(ctr, pstock[p][f][t], -1*CPSTOCK);    
  } 
  if(PHASE==4)
   for(t=0;t<NT;t++)
    XPRBaddterm(ctr, openm[f][t], 20000-COPEN[f]);
  else if(PHASE==5)
   for(t=0;t<NT;t++)
    XPRBaddterm(ctr, openm[f][t], -1*COPEN[f]);
  for(r=0;r<NR;r++)
  {
   for(t=0;t<NT;t++)
    XPRBaddterm(ctr, buy[r][f][t], -1*CBUY[r][t]);
   for(t=1;t<NT+1;t++)
    XPRBaddterm(ctr, rstock[r][f][t], -1*CRSTOCK);    
  }
 } 
 XPRBsetobj(prob,ctr);                       /* Select objective function */  
 
/****CONSTRAINTS****/
 for(p=0;p<NP;p++)
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
   {                 
    ctr=XPRBnewctr(prob,"PBal",XPRB_E);      /* Product stock balance */  
    XPRBaddterm(ctr, pstock[p][f][t], 1);
    XPRBaddterm(ctr, make[p][f][t], 1);
    XPRBaddterm(ctr, sell[p][f][t], -1);
    XPRBaddterm(ctr, pstock[p][f][t+1], -1);
   }

 for(r=0;r<NR;r++)
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
   {                 
    ctr=XPRBnewctr(prob,"RBal",XPRB_E);      /* Raw material stock balance */     
    XPRBaddterm(ctr, rstock[r][f][t], 1);
    XPRBaddterm(ctr, buy[r][f][t], 1);
    XPRBaddterm(ctr, rstock[r][f][t+1], -1);
    for(p=0;p<NP;p++) 
     XPRBaddterm(ctr, make[p][f][t], -1*REQ[p][r]);   
   }

 for(p=0;p<NP;p++)
  for(t=0;t<NT;t++)
  {         /* Limit on the amount of product p to be sold */ 
   ctr=XPRBnewctr(prob,"MxSell",XPRB_L);      
   for(f=0;f<NF;f++)
    XPRBaddterm(ctr, sell[p][f][t], 1);
   XPRBaddterm(ctr, NULL, MXSELL[p][t]);
  }
    
 for(f=0;f<NF;f++)
  for(t=0;t<NT;t++)
  {
   ctr=XPRBnewctr(prob,"MxMake",XPRB_L);     /* Capacity limit at factory f */
   for(p=0;p<NP;p++)
    XPRBaddterm(ctr, make[p][f][t], 1);
   XPRBaddterm(ctr, openm[f][t], -1*MXMAKE[f]);
  }

 for(f=0;f<NF;f++)
  for(t=1;t<NT+1;t++)
  {              
   ctr=XPRBnewctr(prob,"MxRStock",XPRB_L);   /* Raw material stock limit */   
   for(r=0;r<NR;r++) 
    XPRBaddterm(ctr, rstock[r][f][t], 1);
   XPRBaddterm(ctr, NULL, MXRSTOCK);
  }

 if(PHASE==5)
  for(f=0;f<NF;f++)
   for(t=0;t<NT-1;t++)
   {                 
    ctr=XPRBnewctr(prob,"Closed",XPRB_L);    /* Once closed, always closed */
    XPRBaddterm(ctr, openm[f][t+1], 1);
    XPRBaddterm(ctr, openm[f][t], -1);
   }

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

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

 if(PHASE<=3)
  for(f=0;f<NF;f++)
   for(t=0;t<NT;t++)
    XPRBfixvar(openm[f][t],1);
   
/****SOLVING + OUTPUT****/
 XPRBsetsense(prob, XPRB_MAXIM);     /* Choose the sense of the optimization */
 XPRBmipoptimize(prob, "");          /* Solve the MIP-problem */
 printf("Objective: %g\n", XPRBgetobjval(prob));     /* 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++)
    printf("%s:%g %s:%g  ", XPRBgetvarname(make[p][f][t]), 
      XPRBgetsol(make[p][f][t]), XPRBgetvarname(sell[p][f][t]), 
      XPRBgetsol(sell[p][f][t]));
 printf("\n"); 
  
 for(p=0;p<NP;p++)      
  for(f=0;f<NF;f++)
   for(t=0;t<NT+1;t++)
    printf("%s:%g ", XPRBgetvarname(pstock[p][f][t]), XPRBgetsol(pstock[p][f][t]));
 printf("\n"); 
  
 for(r=0;r<NR;r++)      
  for(f=0;f<NF;f++)
  {
   for(t=0;t<NT;t++)
    printf("%s:%g ", XPRBgetvarname(buy[r][f][t]), XPRBgetsol(buy[r][f][t]));
   for(t=0;t<NT+1;t++)
    printf("%s:%g ", XPRBgetvarname(rstock[r][f][t]), XPRBgetsol(rstock[r][f][t]));
  }
 for(f=0;f<NF;f++)
  for(t=0;t<NT;t++)
   printf("%s:%g ", XPRBgetvarname(openm[f][t]), XPRBgetsol(openm[f][t]));  
 printf("\n"); 
*/

 return 0;
}