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.cs, xbcoco2.cs, xbcoco3.cs, xbcoco.cs
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.cs
/********************************************************
  Xpress-BCL C# Example Problems
  ==============================

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

  (c) 2008 Fair Isaac Corporation
      authors: S.Heipcke, D.Brett.
********************************************************/

using System;
using System.Text;
using System.IO;
using BCL;


namespace Examples
{
    public class TestCoco1
    {
        public static void Main()
        {
            XPRB.init();
            XPRBvar make11,make21,make12,make22;
            XPRBprob p = new XPRBprob("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(BCLconstant.XPRB_MAXIM);      /* Choose the sense of the optimization */
            p.lpOptimize();                 /* Solve the LP-problem */
            System.Console.WriteLine("Objective: " + p.getObjVal());   /* Get objective value */

            /* Print out the solution values for all variables */
            System.Console.WriteLine(make11.getName() + ": " + make11.getSol());
            System.Console.WriteLine(make21.getName() + ": " + make21.getSol());
            System.Console.WriteLine(make12.getName() + ": " + make12.getSol());
            System.Console.WriteLine(make22.getName() + ": " + make22.getSol());

            return;
        }

    }

}

xbcoco2.cs
/********************************************************
  Xpress-BCL C# Example Problems
  ==============================

  file xbcoco2.cs
  ````````````````
  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
      authors: S.Heipcke, D.Brett.
********************************************************/

using System;
using System.Text;
using System.IO;
using BCL;


namespace Examples
{
    public class TestCoco1
    {
        const int NP = 2;            /* Number of products (p) */
        const int NF = 2;            /*           factories (f) */
        const int NR = 2;            /*           raw materials (r) */

        //Define XPRBDATAPATH to point where you wish:
        const string XPRBDATAPATH = "../../data";
        const string REVFILE    = XPRBDATAPATH + "/coco/rev.dat";
        const string CMAKEFILE  = XPRBDATAPATH + "/coco/cmake.dat";
        const string CBUYFILE   = XPRBDATAPATH + "/coco/cbuy.dat";
        const string REQFILE    = XPRBDATAPATH + "/coco/req.dat";
        const string MXSELLFILE = XPRBDATAPATH + "/coco/maxsell.dat";
        const string MXMAKEFILE = XPRBDATAPATH + "/coco/mxmake.dat";

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

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

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

        void modCoco2()
        {
            XPRBvar[,] make = new XPRBvar[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("make_p" + (p+1) + "f" + (f+1));    

            /****OBJECTIVE****/
            lobj = new XPRBexpr();
            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 = new XPRBexpr(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 = new XPRBexpr(0);
                for(p=0;p<NP;p++) lc += make[p,f];
                pb.newCtr("MxMake", lc <= MXMAKE[f]);      
            }

            /****SOLVING + OUTPUT****/
            pb.setSense(BCLconstant.XPRB_MAXIM);  /* Choose the sense of the optimization */
            pb.lpOptimize();             /* Solve the LP-problem */
            System.Console.WriteLine("Objective: " + pb.getObjVal());  /* Get objective value */

            for(p=0;p<NP;p++)         /* Print the solution values */      
                for(f=0;f<NF;f++)   
                    System.Console.Write(make[p,f].getName() + ":" + make[p,f].getSol() + " ");
            System.Console.WriteLine();
        }

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

        /**** Read data from files ****/
        void readData()
        {
            FileStream file;
            StreamReader fileStreamIn;
            int p,f,r;

            /* Read the revenue data file */
            /* Read the demand data file */
            file = new FileStream(REVFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out REV, NP);
            fileStreamIn.Close();
            file.Close();

            /* Read the production cost data file */
            file = new FileStream(CMAKEFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (p = 0; p < NP; p++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NF);
                for(int q=0; q<NF; q++)
                    CMAK[p,q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();

            /* Read the raw material cost data file */
            file = new FileStream(CBUYFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out CBUY, NR);
            fileStreamIn.Close();
            file.Close();

            /* Read the resource requirement data file */
            file = new FileStream(REQFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (p = 0; p < NP; p++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NF);
                for (int q = 0; q < NF; q++)
                    REQ[p, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();

            /* Read the max. sales quantities data file */
            file = new FileStream(MXSELLFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out MXSELL, NP);
            fileStreamIn.Close();
            file.Close();

            /* Read the production capacities data file */
            file = new FileStream(MXMAKEFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out MXMAKE, NF);
            fileStreamIn.Close();
            file.Close();

            /* 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]);
                }
        }

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

        public static void Main()
        {
            XPRB.init();
            TestCoco1 TestInstance = new TestCoco1();
            TestInstance.readData();            /* Data input from file */
            TestInstance.modCoco2();            /* Model and solve the problem */

            return;
        } 

    }

}

xbcoco3.cs
/********************************************************
  Xpress-BCL C# Example Problems
  ==============================

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

  (c) 2008 Fair Isaac Corporation
      authors: S.Heipcke, D.Brett.
********************************************************/

using System;
using System.Text;
using System.IO;
using BCL;


namespace Examples
{
    public class TestCoco3
    {
        const int NP = 2;           /* Number of products (p) */
        const int NF = 2;           /* Factories (f) */
        const int NR = 2;           /* Raw materials (r) */
        const int NT = 4;           /* Time periods (t) */

        //Define XPRBDATAPATH to point where you wish.
        const string XPRBDATAPATH = "../../data";
        const string PSTOCK0FILE= XPRBDATAPATH + "/coco/pstock0.dat";
        const string RSTOCK0FILE= XPRBDATAPATH + "/coco/rstock0.dat";
        const string REVFILE    = XPRBDATAPATH + "/coco/revt.dat";
        const string CMAKEFILE  = XPRBDATAPATH + "/coco/cmake.dat";
        const string CBUYFILE   = XPRBDATAPATH + "/coco/cbuyt.dat";
        const string REQFILE    = XPRBDATAPATH + "/coco/req.dat";
        const string MXSELLFILE = XPRBDATAPATH + "/coco/maxsellt.dat";
        const string MXMAKEFILE = XPRBDATAPATH + "/coco/mxmake.dat";

        /****TABLES****/
        double[,] REV = new double[NP,NT];     /* Unit selling price of product p in period t */
        double[,] CMAK = new double[NP,NF];    /* Unit cost to make product p at factory f */
        double[,] CBUY = new double[NR,NT];    /* Unit cost to buy raw material r in period t */
        double[,] REQ = new double[NP,NR];     /* Requirement by unit of prod. p for raw material r */
        double[,] MXSELL = new double[NP,NT];  /* Max. amount of p that can be sold in period t */
        double[] MXMAKE = new double[NF];      /* Max. amount factory f can make over all products */
        double[,] PSTOCK0 = new double[NP,NF]; /* Initial product p stock level at factory f */
        double[,] RSTOCK0 = new double[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 = new XPRBprob("Coco3");   /* Initialize a new problem in BCL */

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

        void modCoco3()
        {
            XPRBvar[,,] make = new XPRBvar[NP,NF,NT];
            XPRBvar[,,] sell = new XPRBvar[NP,NF,NT];
            XPRBvar[,,] pstock = new XPRBvar[NP,NF,NT+1];
            XPRBvar[,,] buy = new XPRBvar[NR,NF,NT];
            XPRBvar[,,] rstock = new XPRBvar[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("make_p" + (p+1) + "_f" + (f+1));
                        /* Amount of prod. p to make at factory f in period t */
                        sell[p,f,t] = pb.newVar("sell_p" + (p+1) + "_f" + (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("pstock_p" + (p+1) + "_f" + (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("buy_r" + (r+1) + "_f" + (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("rstock_r" + (r+1) + "_f" + (f+1));
                    /* Stock level of raw mat. r at factory f at start of per. t */
                }

            /****OBJECTIVE****/
            lobj = new XPRBexpr();
            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 = new XPRBexpr(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 = new XPRBexpr(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 = new XPRBexpr(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 = new XPRBexpr(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(BCLconstant.XPRB_MAXIM); /* Choose the sense of the optimization */
            pb.lpOptimize();            /* Solve the LP-problem */
            System.Console.WriteLine("Objective: " + pb.getObjVal());   /* 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++)
                    System.Console.Write(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++) 
                    System.Console.Write(pstock[p,f,t].getName() + ":" + pstock[p,f,t].getSol() + " ");
            }
            System.Console.WriteLine(); 

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

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

        /**** Read data from files ****/
        void readData()
        {
            FileStream file;
            StreamReader fileStreamIn;
            int p, r;
    
            /* Read the revenu data file */
            file = new FileStream(REVFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (p = 0; p < NP; p++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NT);
                for (int q = 0; q < NT; q++)
                    REV[p, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();

            /* Read the production cost data file */
            file = new FileStream(CMAKEFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (p = 0; p < NP; p++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NF);
                for (int q = 0; q < NF; q++)
                    CMAK[p, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();


            /* Read the raw material cost data file */
            file = new FileStream(CBUYFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (r = 0; r < NR; r++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NT);
                for (int q = 0; q < NT; q++)
                    CBUY[r, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();


            /* Read the resource requirement data file */
            file = new FileStream(REQFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (p = 0; p < NP; p++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NR);
                for (int q = 0; q < NR; q++)
                    REQ[p, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();

            /* Read the max. sales quantities data file */
            file = new FileStream(MXSELLFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (p = 0; p < NP; p++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NT);
                for (int q = 0; q < NT; q++)
                    MXSELL[p, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();

            /* Read the production capacities data file */
            file = new FileStream(MXMAKEFILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out MXMAKE, NF);
            fileStreamIn.Close();
            file.Close();

            /* Read the product stock data file */
            /* Read the max. sales quantities data file */
            file = new FileStream(PSTOCK0FILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (p = 0; p < NP; p++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NF);
                for (int q = 0; q < NF; q++)
                    PSTOCK0[p, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();

            /* Read the raw material stock data file */
            file = new FileStream(RSTOCK0FILE, FileMode.Open, FileAccess.Read);
            fileStreamIn = new StreamReader(file);
            for (r = 0; r < NR; r++)
            {
                double[] temp = new double[NF];
                pb.XPRBreadarrline(fileStreamIn, 200, "{g} , ", out temp, NF);
                for (int q = 0; q < NF; q++)
                    RSTOCK0[r, q] = temp[q];

            }
            fileStreamIn.Close();
            file.Close();
        }

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

        public static void Main()
        {
           XPRB.init();
           TestCoco3 TestInstance = new TestCoco3();

            TestInstance.readData();            /* Data input from file */
            TestInstance.modCoco3();            /* Model and solve the problem */

            return;
        } 

    }

}

xbcoco.cs
/********************************************************
  Xpress-BCL C# Example Problems
  ==============================

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

  (c) 2008 Fair Isaac Corporation
      authors: S.Heipcke, D.Brett.
********************************************************/

using System;
using System.Text;
using System.IO;
using BCL;


namespace Examples
{
    public class TestIntCocoComplete
    {
        const int 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 */

        const int NP = 2;            /* Number of products (p) */
        const int NF = 2;            /*           factories (f) */
        const int NR = 2;            /*           raw materials (r) */
        const int NT = 4;            /*           time periods (t) */

        /****DATA****/
        double[,] REV =       /* Unit selling price of product p in period t */
        {{400, 380, 405, 350},
        {410, 397, 412, 397}};
        double[,] CMAK =     /* Unit cost to make product p at factory f */
        {{150, 153},
        { 75,  68}};
        double[,] CBUY =     /* 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 =      /* Requirement by unit of prod. p for raw material r */
        {{1.0, 0.5},
        {1.3, 0.4}};
        double[,] MXSELL =   /* 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 =  /* Initial product p stock level at factory f */
        {{50, 100},
        {50,  50}};
        double[,] RSTOCK0 =  /* Initial raw material r stock level at factory f*/
        {{100, 150},
        { 50, 100}};

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

        public static void Main()
        {
            XPRB.init();

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

            /****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("make_p" + (p+1) + "_f" + (f+1));
                        /* Amount of prod. p to make at factory f in period t */
                        sell[p, f, t] = pb.newVar("sell_p" + (p + 1) + "_f" + (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("pstock_p" + (p+1) + "_f" + (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("buy_r" + (r+1) + "_f" + (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("rstock_r" + (r+1) + "_f" + (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("open_f" + (f+1), BCLconstant.XPRB_BV);
            /* 1 if factory f is open in period t, else 0 */

            /****OBJECTIVE****/
            lobj = new XPRBexpr();
            for (f = 0; f < NF; f++)        /* Objective: maximize total profit */
            {
                for (p = 0; p < NP; p++)
                {
                    for (t = 0; t < NT; t++)
                        lobj += TestInstance.REV[p,t] * sell[p,f,t] - TestInstance.CMAK[p,f] * make[p,f,t];
                    for (t = 1; t < NT + 1; t++) lobj -= TestInstance.CPSTOCK * pstock[p,f,t];
                }
                if (PHASE == 4)
                    for (t = 0; t < NT; t++) lobj += (20000 - TestInstance.COPEN[f]) * openm[f,t];
                else if (PHASE == 5)
                    for (t = 0; t < NT; t++) lobj -= TestInstance.COPEN[f] * openm[f,t];
                for (r = 0; r < NR; r++)
                {
                    for (t = 0; t < NT; t++) lobj -= TestInstance.CBUY[r,t] * buy[r,f,t];
                    for (t = 1; t < NT + 1; t++) lobj -= TestInstance.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 = new XPRBexpr(0.0);
                        for (p = 0; p < NP; p++) lc += TestInstance.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 = new XPRBexpr(0.0);
                    for (f = 0; f < NF; f++) lc += sell[p,f,t];
                    pb.newCtr("MxSell", lc <= TestInstance.MXSELL[p,t]);
                }

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

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

            if (PHASE == 5)
                for (f = 0; f < NF; f++)
                    for (t = 0; t < NT - 1; t++)    /* Once closed, always closed */
                        pb.newCtr("Closed", new XPRBexpr(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(TestInstance.PSTOCK0[p, f]);    /* Initial product levels */

            for (r = 0; r < NR; r++)
                for (f = 0; f < NF; f++)
                    rstock[r, f, 0].fix(TestInstance.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(BCLconstant.XPRB_MAXIM);  /* Choose the sense of the optimization */
            pb.mipOptimize();            /* Solve the MIP-problem */
            System.Console.WriteLine("Objective: " + pb.getObjVal());   /* 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;
        }
    }
}