/* $Id: rowColumn.cpp 1559 2010-06-05 19:42:36Z stefan $ */
/* Copyright (C) 2004, International Business Machines Corporation
   and others.  All Rights Reserved.

   This sample program is designed to illustrate programming
   techniques using CoinLP, has not been thoroughly tested
   and comes without any warranty whatsoever.

   You may copy, modify and distribute this sample program without
   any restrictions whatsoever and without any payment to anyone.
*/

#include "ClpSimplex.hpp"
#include <cstdio>
#include <cassert>

int main(int argc, const char *argv[])
{
     ClpSimplex  modelByRow, modelByColumn;

     // This very simple example shows how to create a model by row and by column
     int numberRows = 3;
     int numberColumns = 5;
     // Rim of problem is same in both cases
     double objective [] = {1000.0, 400.0, 500.0, 10000.0, 10000.0};
     double columnLower[] = {0.0, 0.0, 0.0, 0.0, 0.0};
     double columnUpper[] = {COIN_DBL_MAX, COIN_DBL_MAX, COIN_DBL_MAX, 20.0, 20.0};
     double rowLower[] = {20.0, -COIN_DBL_MAX, 8.0};
     double rowUpper[] = {COIN_DBL_MAX, 30.0, 8.0};
     // Matrix by row
     int rowStart[] = {0, 5, 10, 13};
     int column[] = {0, 1, 2, 3, 4,
                     0, 1, 2, 3, 4,
                     0, 1, 2
                    };
     double elementByRow[] = {8.0, 5.0, 4.0, 4.0, -4.0,
                              8.0, 4.0, 5.0, 5.0, -5.0,
                              1.0, -1.0, -1.0
                             };
     // Matrix by column
     int columnStart[] = {0, 3, 6, 9, 11, 13};
     int row[] = {0, 1, 2,
                  0, 1, 2,
                  0, 1, 2,
                  0, 1,
                  0, 1
                 };
     double elementByColumn[] = {8.0, 8.0, 1.0,
                                 5.0, 4.0, -1.0,
                                 4.0, 5.0, -1.0,
                                 4.0, 5.0,
                                 -4.0, -5.0
                                };
     int numberElements;
     // Do column version first as it can be done two ways
     // a) As one step using matrix as stored
     modelByColumn.loadProblem(numberColumns, numberRows, columnStart, row, elementByColumn,
                               columnLower, columnUpper, objective,
                               rowLower, rowUpper);
     // Solve
     modelByColumn.dual();
     // check value of objective
     assert(fabs(modelByColumn.objectiveValue() - 76000.0) < 1.0e-7);
     // b) As two steps - first creating a CoinPackedMatrix
     // NULL for column lengths indicate they are stored without gaps
     // Look at CoinPackedMatrix.hpp for other ways to create a matrix
     numberElements = columnStart[numberColumns];
     CoinPackedMatrix byColumn(true, numberRows, numberColumns, numberElements,
                               elementByColumn, row, columnStart, NULL);
     // now load matrix and rim
     modelByColumn.loadProblem(byColumn,
                               columnLower, columnUpper, objective,
                               rowLower, rowUpper);
     // Solve
     modelByColumn.dual();
     // check value of objective
     assert(fabs(modelByColumn.objectiveValue() - 76000.0) < 1.0e-7);
     // Now do by row
     // The false says row ordered so numberRows and numberColumns swapped - see CoinPackedMatrix.hpp
     assert(numberElements == rowStart[numberRows]);    // check same number of elements in each copy
     CoinPackedMatrix byRow(false, numberColumns, numberRows, numberElements,
                            elementByRow, column, rowStart, NULL);
     // now load matrix and rim
     modelByRow.loadProblem(byRow,
                            columnLower, columnUpper, objective,
                            rowLower, rowUpper);
     // Solve
     modelByRow.dual();
     // check value of objective
     assert(fabs(modelByRow.objectiveValue() - 76000.0) < 1.0e-7);
     // write solution
     const double * solution = modelByRow.primalColumnSolution();
     for (int i = 0; i < numberColumns; i++) {
          if (solution[i])
               printf("Column %d has value %g\n",
                      i, solution[i]);
     }
     modelByRow.writeMps("Tiny.mps");
     return 0;
}
