/* $Id: ekk.cpp 1561 2010-06-13 13:08:03Z stefan $ */
// Copyright (C) 2002, International Business Machines
// Corporation and others.  All Rights Reserved.

/*  This can be used to compare OSL and Clp.  The interface functions
    below (in ekk_interface.cpp) were written so that calls to osl
    in the middle of complex algorithms could easily be swapped
    for Clp code.  This was to stress test Clp (and Osl :-)).

    With the addition of ekk_crash it may be used to see if we need
    a crash in Clp.  With "both" set it can also be used to see which
    gives better behavior after postSolve.

    However they may be useful as sample code.  Virtuous people would
    add return code checking.

    This main could just as easily be C code.

*/

#include "ekk_c_api.h"
// These interface functions are needed
// Note - This example wastes memory as it has several copies of matrix
/* As ekk_primalSimplex + postsolve instructions:
   presolve - 0 , no presolve, 1 presolve but no primal after postsolve,
                  2 do primal if any infeasibilities,
		  3 always do primal.
*/
extern "C" int ekk_primalClp(EKKModel * model, int  startup, int presolve);

/* As ekk_dualSimplex + postsolve instructions:
   presolve - 0 , no presolve, 1 presolve but no primal after postsolve,
                  2 do primal if any infeasibilities,
		  3 always do primal.
*/
extern "C" int ekk_dualClp(EKKModel * model, int presolve);

/* rather like ekk_preSolve (3) plus:
   keepIntegers - false to treat as if continuous
   pass   - do this many passes (0==default(5))

   returns 1 if infeasible
*/
extern "C" int ekk_preSolveClp(EKKModel * model, bool keepIntegers,
                               int pass);

#include "ClpSimplex.hpp"
#include <stdio.h>
#include <stdarg.h>

int main(int argc, const char *argv[])
{
     const char * name;
     // problem is actually scaled for osl, dynamically for clp (slows clp)
     // default is primal, no presolve, minimise and use clp
     bool    primal = true, presolve = false;
     int useosl = 0;
     bool freeFormat = false;
     bool exportIt = false;

     EKKModel * model;
     EKKContext * context;

     if (argc > 1) {
          name = argv[1];
     } else {
#if defined(SAMPLEDIR)
          name = (SAMPLEDIR "/p0033.mps";
#else
          fprintf(stderr, "Do not know where to find sample MPS files.\n");
          exit(1);
#endif
             }

             /* initialize OSL environment */
             context = ekk_initializeContext();
     model = ekk_newModel(context, "");

     int i;
     printf("*** Options ");
     for (i = 2; i < argc; i++) {
          printf("%s ", argv[i]);
     }
     printf("\n");

     // see if free format needed

     for (i = 2; i < argc; i++) {
          if (!strncmp(argv[i], "free", 4)) {
               freeFormat = true;
          }
     }

     // create model from MPS file

     if (!freeFormat) {
          ekk_importModel(model, name);
     } else {
          ekk_importModelFree(model, name);
     }

     // other options
     for (i = 2; i < argc; i++) {
          if (!strncmp(argv[i], "max", 3)) {
               if (!strncmp(argv[i], "max2", 4)) {
                    // This is for testing - it just reverses signs and maximizes
                    int i, n = ekk_getInumcols(model);
                    double * objective = ekk_getObjective(model);
                    for (i = 0; i < n; i++) {
                         objective[i] = -objective[i];
                    }
                    ekk_setObjective(model, objective);
                    ekk_setMaximize(model);
               } else {
                    // maximize
                    ekk_setMaximize(model);
               }
          }
          if (!strncmp(argv[i], "dual", 4)) {
               primal = false;
          }
          if (!strncmp(argv[i], "presol", 6)) {
               presolve = true;
          }
          if (!strncmp(argv[i], "osl", 3)) {
               useosl = 1;
          }
          if (!strncmp(argv[i], "both", 4)) {
               useosl = 2;
          }
          if (!strncmp(argv[i], "export", 6)) {
               exportIt = true;
          }
     }
     if (useosl) {
          // OSL
          if (presolve)
               ekk_preSolve(model, 3, NULL);
          ekk_scale(model);

          if (primal)
               ekk_primalSimplex(model, 1);
          else
               ekk_dualSimplex(model);
          if (presolve) {
               ekk_postSolve(model, NULL);
               ekk_primalSimplex(model, 3);
          }
          if (useosl == 2)
               ekk_allSlackBasis(model);    // otherwise it would be easy
     }
     if ((useosl & 2) == 0) {
          // CLP
          if (presolve)
               ekk_preSolveClp(model, true, 5);
          /* 3 is because it is ignored if no presolve, and we
             are forcing Clp to re-optimize */
          if (primal)
               ekk_primalClp(model, 1, 3);
          else
               ekk_dualClp(model, 3);
     }
     if (exportIt) {
          ClpSimplex * clp = new ClpSimplex();;
          int numberRows = ekk_getInumrows(model);
          int numberColumns = ekk_getInumcols(model);
          clp->loadProblem(numberColumns, numberRows, ekk_blockColumn(model, 0),
                           ekk_blockRow(model, 0), ekk_blockElement(model, 0),
                           ekk_collower(model), ekk_colupper(model),
                           ekk_objective(model),
                           ekk_rowlower(model), ekk_rowupper(model));
          // Do integer stuff
          int * which =  ekk_listOfIntegers(model);
          int numberIntegers =  ekk_getInumints(model);
          for (int i = 0; i < numberIntegers; i++)
               clp->setInteger(which[i]);
          ekk_free(which);
          clp->writeMps("try1.mps");
          delete clp;
     }
     ekk_deleteModel(model);
     ekk_endContext(context);
     return 0;
}
