source: branches/ClpForOsi2/Clp/src/ClpMain.cpp @ 1816

Last change on this file since 1816 was 1816, checked in by mjs, 8 years ago

Eclipse code analyzer recommendations: (a) catch exceptions by reference; (b) parenthesize multi-term Boolean expressions; (c) virtual methods need virtual dtors (and Eclipse likes to see the keyword); (d) operator=() should return *this (and check for self-assignment).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 183.0 KB
Line 
1/* $Id: ClpMain.cpp 1816 2011-11-02 15:25:47Z mjs $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include "CoinPragma.hpp"
7
8#include <cassert>
9#include <cstdio>
10#include <cstdlib>
11#include <cmath>
12#include <cfloat>
13#include <string>
14#include <iostream>
15
16int boundary_sort = 1000;
17int boundary_sort2 = 1000;
18int boundary_sort3 = 10000;
19
20#include "CoinPragma.hpp"
21#include "CoinHelperFunctions.hpp"
22#include "CoinSort.hpp"
23// History since 1.0 at end
24#include "ClpConfig.h"
25#include "CoinMpsIO.hpp"
26#include "CoinFileIO.hpp"
27#ifdef COIN_HAS_GLPK
28#include "glpk.h"
29extern glp_tran* cbc_glp_tran;
30extern glp_prob* cbc_glp_prob;
31#else
32#define GLP_UNDEF 1
33#define GLP_FEAS 2
34#define GLP_INFEAS 3
35#define GLP_NOFEAS 4
36#define GLP_OPT 5
37#endif
38
39#include "ClpFactorization.hpp"
40#include "CoinTime.hpp"
41#include "ClpSimplex.hpp"
42#include "ClpSimplexOther.hpp"
43#include "ClpSolve.hpp"
44#include "ClpPackedMatrix.hpp"
45#include "ClpPlusMinusOneMatrix.hpp"
46#include "ClpNetworkMatrix.hpp"
47#include "ClpDualRowSteepest.hpp"
48#include "ClpDualRowDantzig.hpp"
49#include "ClpLinearObjective.hpp"
50#include "ClpPrimalColumnSteepest.hpp"
51#include "ClpPrimalColumnDantzig.hpp"
52#include "ClpPresolve.hpp"
53#include "CbcOrClpParam.hpp"
54#include "CoinSignal.hpp"
55#ifdef DMALLOC
56#include "dmalloc.h"
57#endif
58#if defined(COIN_HAS_WSMP) || defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(TAUCS_BARRIER) || defined(COIN_HAS_MUMPS)
59#define FOREIGN_BARRIER
60#endif
61
62static double totalTime = 0.0;
63static bool maskMatches(const int * starts, char ** masks,
64                        std::string & check);
65static ClpSimplex * currentModel = NULL;
66
67extern "C" {
68     static void
69#if defined(_MSC_VER)
70     __cdecl
71#endif // _MSC_VER
72     signal_handler(int /*whichSignal*/)
73     {
74          if (currentModel != NULL)
75               currentModel->setMaximumIterations(0); // stop at next iterations
76          return;
77     }
78}
79
80//#############################################################################
81
82#ifdef NDEBUG
83#undef NDEBUG
84#endif
85
86int mainTest (int argc, const char *argv[], int algorithm,
87              ClpSimplex empty, ClpSolve solveOptions, int switchOff, bool doVector);
88static void statistics(ClpSimplex * originalModel, ClpSimplex * model);
89static void generateCode(const char * fileName, int type);
90// Returns next valid field
91int CbcOrClpRead_mode = 1;
92FILE * CbcOrClpReadCommand = stdin;
93extern int CbcOrClpEnvironmentIndex;
94#ifdef CLP_USER_DRIVEN1
95/* Returns true if variable sequenceOut can leave basis when
96   model->sequenceIn() enters.
97   This function may be entered several times for each sequenceOut. 
98   The first time realAlpha will be positive if going to lower bound
99   and negative if going to upper bound (scaled bounds in lower,upper) - then will be zero.
100   currentValue is distance to bound.
101   currentTheta is current theta.
102   alpha is fabs(pivot element).
103   Variable will change theta if currentValue - currentTheta*alpha < 0.0
104*/
105bool userChoiceValid1(const ClpSimplex * model,
106                      int sequenceOut,
107                      double currentValue,
108                      double currentTheta,
109                      double alpha,
110                      double realAlpha)
111{
112  return true;
113}
114/* This returns true if chosen in/out pair valid.
115   The main thing to check would be variable flipping bounds may be
116   OK.  This would be signaled by reasonable theta_ and valueOut_.
117   If you return false sequenceIn_ will be flagged as ineligible.
118*/
119bool userChoiceValid2(const ClpSimplex * model)
120{
121  return true;
122}
123/* If a good pivot then you may wish to unflag some variables.
124 */
125void userChoiceWasGood(ClpSimplex * model)
126{
127}
128#endif
129
130int
131#if defined(_MSC_VER)
132__cdecl
133#endif // _MSC_VER
134main (int argc, const char *argv[])
135{
136     // next {} is just to make sure all memory should be freed - for debug
137     {
138          double time1 = CoinCpuTime(), time2;
139          // Set up all non-standard stuff
140          //int numberModels=1;
141          ClpSimplex * models = new ClpSimplex[1];
142
143          // default action on import
144          int allowImportErrors = 0;
145          int keepImportNames = 1;
146          int doIdiot = -1;
147          int outputFormat = 2;
148          int slpValue = -1;
149          int cppValue = -1;
150          int printOptions = 0;
151          int printMode = 0;
152          int presolveOptions = 0;
153          int doCrash = 0;
154          int doVector = 0;
155          int doSprint = -1;
156          // set reasonable defaults
157          int preSolve = 5;
158          bool preSolveFile = false;
159          models->setPerturbation(50);
160          models->messageHandler()->setPrefix(false);
161          const char dirsep =  CoinFindDirSeparator();
162          std::string directory;
163          std::string dirSample;
164          std::string dirNetlib;
165          std::string dirMiplib;
166          if (dirsep == '/') {
167               directory = "./";
168               dirSample = "../../Data/Sample/";
169               dirNetlib = "../../Data/Netlib/";
170               dirMiplib = "../../Data/miplib3/";
171          } else {
172               directory = ".\\";
173#              ifdef COIN_MSVS
174               // Visual Studio builds are deeper
175               dirSample = "..\\..\\..\\..\\Data\\Sample\\";
176               dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
177               dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
178#              else
179               dirSample = "..\\..\\Data\\Sample\\";
180               dirNetlib = "..\\..\\Data\\Netlib\\";
181               dirMiplib = "..\\..\\Data\\miplib3\\";
182#              endif
183          }
184          std::string defaultDirectory = directory;
185          std::string importFile = "";
186          std::string exportFile = "default.mps";
187          std::string importBasisFile = "";
188          int basisHasValues = 0;
189          int substitution = 3;
190          int dualize = 3;  // dualize if looks promising
191          std::string exportBasisFile = "default.bas";
192          std::string saveFile = "default.prob";
193          std::string restoreFile = "default.prob";
194          std::string solutionFile = "stdout";
195          std::string solutionSaveFile = "solution.file";
196          std::string printMask = "";
197          CbcOrClpParam parameters[CBCMAXPARAMETERS];
198          int numberParameters ;
199          establishParams(numberParameters, parameters) ;
200          parameters[whichParam(CLP_PARAM_ACTION_BASISIN, numberParameters, parameters)].setStringValue(importBasisFile);
201          parameters[whichParam(CLP_PARAM_ACTION_BASISOUT, numberParameters, parameters)].setStringValue(exportBasisFile);
202          parameters[whichParam(CLP_PARAM_ACTION_PRINTMASK, numberParameters, parameters)].setStringValue(printMask);
203          parameters[whichParam(CLP_PARAM_ACTION_DIRECTORY, numberParameters, parameters)].setStringValue(directory);
204          parameters[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, numberParameters, parameters)].setStringValue(dirSample);
205          parameters[whichParam(CLP_PARAM_ACTION_DIRNETLIB, numberParameters, parameters)].setStringValue(dirNetlib);
206          parameters[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, numberParameters, parameters)].setStringValue(dirMiplib);
207          parameters[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters, parameters)].setDoubleValue(models->dualBound());
208          parameters[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters, parameters)].setDoubleValue(models->dualTolerance());
209          parameters[whichParam(CLP_PARAM_ACTION_EXPORT, numberParameters, parameters)].setStringValue(exportFile);
210          parameters[whichParam(CLP_PARAM_INT_IDIOT, numberParameters, parameters)].setIntValue(doIdiot);
211          parameters[whichParam(CLP_PARAM_ACTION_IMPORT, numberParameters, parameters)].setStringValue(importFile);
212          parameters[whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters, parameters)].setIntValue(models->logLevel());
213          parameters[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters, parameters)].setIntValue(models->factorizationFrequency());
214          parameters[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters, parameters)].setIntValue(models->maximumIterations());
215          parameters[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, numberParameters, parameters)].setIntValue(outputFormat);
216          parameters[whichParam(CLP_PARAM_INT_PRESOLVEPASS, numberParameters, parameters)].setIntValue(preSolve);
217          parameters[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters, parameters)].setIntValue(models->perturbation());
218          parameters[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters, parameters)].setDoubleValue(models->primalTolerance());
219          parameters[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters, parameters)].setDoubleValue(models->infeasibilityCost());
220          parameters[whichParam(CLP_PARAM_ACTION_RESTORE, numberParameters, parameters)].setStringValue(restoreFile);
221          parameters[whichParam(CLP_PARAM_ACTION_SAVE, numberParameters, parameters)].setStringValue(saveFile);
222          parameters[whichParam(CLP_PARAM_DBL_TIMELIMIT, numberParameters, parameters)].setDoubleValue(models->maximumSeconds());
223          parameters[whichParam(CLP_PARAM_ACTION_SOLUTION, numberParameters, parameters)].setStringValue(solutionFile);
224          parameters[whichParam(CLP_PARAM_ACTION_SAVESOL, numberParameters, parameters)].setStringValue(solutionSaveFile);
225          parameters[whichParam(CLP_PARAM_INT_SPRINT, numberParameters, parameters)].setIntValue(doSprint);
226          parameters[whichParam(CLP_PARAM_INT_SUBSTITUTION, numberParameters, parameters)].setIntValue(substitution);
227          parameters[whichParam(CLP_PARAM_INT_DUALIZE, numberParameters, parameters)].setIntValue(dualize);
228          parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].setDoubleValue(1.0e-8);
229          int verbose = 0;
230
231          // total number of commands read
232          int numberGoodCommands = 0;
233          bool * goodModels = new bool[1];
234
235          // Hidden stuff for barrier
236          int choleskyType = 0;
237          int gamma = 0;
238          parameters[whichParam(CLP_PARAM_STR_BARRIERSCALE, numberParameters, parameters)].setCurrentOption(2);
239          int scaleBarrier = 2;
240          int doKKT = 0;
241          int crossover = 2; // do crossover unless quadratic
242
243          int iModel = 0;
244          goodModels[0] = false;
245          //models[0].scaling(1);
246          //models[0].setDualBound(1.0e6);
247          //models[0].setDualTolerance(1.0e-7);
248          //ClpDualRowSteepest steep;
249          //models[0].setDualRowPivotAlgorithm(steep);
250          //models[0].setPrimalTolerance(1.0e-7);
251          //ClpPrimalColumnSteepest steepP;
252          //models[0].setPrimalColumnPivotAlgorithm(steepP);
253          std::string field;
254          std::cout << "Coin LP version " << CLP_VERSION
255                    << ", build " << __DATE__ << std::endl;
256          // Print command line
257          if (argc > 1) {
258               printf("command line - ");
259               for (int i = 0; i < argc; i++)
260                    printf("%s ", argv[i]);
261               printf("\n");
262          }
263
264          while (1) {
265               // next command
266               field = CoinReadGetCommand(argc, argv);
267
268               // exit if null or similar
269               if (!field.length()) {
270                    if (numberGoodCommands == 1 && goodModels[0]) {
271                         // we just had file name - do dual or primal
272                         field = "either";
273                    } else if (!numberGoodCommands) {
274                         // let's give the sucker a hint
275                         std::cout
276                                   << "Clp takes input from arguments ( - switches to stdin)"
277                                   << std::endl
278                                   << "Enter ? for list of commands or help" << std::endl;
279                         field = "-";
280                    } else {
281                         break;
282                    }
283               }
284
285               // see if ? at end
286               int numberQuery = 0;
287               if (field != "?" && field != "???") {
288                    size_t length = field.length();
289                    size_t i;
290                    for (i = length - 1; i > 0; i--) {
291                         if (field[i] == '?')
292                              numberQuery++;
293                         else
294                              break;
295                    }
296                    field = field.substr(0, length - numberQuery);
297               }
298               // find out if valid command
299               int iParam;
300               int numberMatches = 0;
301               int firstMatch = -1;
302               for ( iParam = 0; iParam < numberParameters; iParam++ ) {
303                    int match = parameters[iParam].matches(field);
304                    if (match == 1) {
305                         numberMatches = 1;
306                         firstMatch = iParam;
307                         break;
308                    } else {
309                         if (match && firstMatch < 0)
310                              firstMatch = iParam;
311                         numberMatches += match >> 1;
312                    }
313               }
314               if (iParam < numberParameters && !numberQuery) {
315                    // found
316                    CbcOrClpParam found = parameters[iParam];
317                    CbcOrClpParameterType type = found.type();
318                    int valid;
319                    numberGoodCommands++;
320                    if (type == CBC_PARAM_GENERALQUERY) {
321                         std::cout << "In argument list keywords have leading - "
322                                   ", -stdin or just - switches to stdin" << std::endl;
323                         std::cout << "One command per line (and no -)" << std::endl;
324                         std::cout << "abcd? gives list of possibilities, if only one + explanation" << std::endl;
325                         std::cout << "abcd?? adds explanation, if only one fuller help" << std::endl;
326                         std::cout << "abcd without value (where expected) gives current value" << std::endl;
327                         std::cout << "abcd value sets value" << std::endl;
328                         std::cout << "Commands are:" << std::endl;
329                         int maxAcross = 10;
330                         bool evenHidden = false;
331                         int printLevel =
332                              parameters[whichParam(CLP_PARAM_STR_ALLCOMMANDS,
333                                                    numberParameters, parameters)].currentOptionAsInteger();
334                         int convertP[] = {2, 1, 0};
335                         printLevel = convertP[printLevel];
336                         if ((verbose & 8) != 0) {
337                              // even hidden
338                              evenHidden = true;
339                              verbose &= ~8;
340                         }
341                         if (verbose)
342                              maxAcross = 1;
343                         int limits[] = {1, 101, 201, 301, 401};
344                         std::vector<std::string> types;
345                         types.push_back("Double parameters:");
346                         types.push_back("Int parameters:");
347                         types.push_back("Keyword parameters:");
348                         types.push_back("Actions or string parameters:");
349                         int iType;
350                         for (iType = 0; iType < 4; iType++) {
351                              int across = 0;
352                              int lengthLine = 0;
353                              if ((verbose % 4) != 0)
354                                   std::cout << std::endl;
355                              std::cout << types[iType] << std::endl;
356                              if ((verbose & 2) != 0)
357                                   std::cout << std::endl;
358                              for ( iParam = 0; iParam < numberParameters; iParam++ ) {
359                                   int type = parameters[iParam].type();
360                                   //printf("%d type %d limits %d %d display %d\n",iParam,
361                                   //   type,limits[iType],limits[iType+1],parameters[iParam].displayThis());
362                                   if ((parameters[iParam].displayThis() >= printLevel || evenHidden) &&
363                                             type >= limits[iType]
364                                             && type < limits[iType+1]) {
365                                        if (!across) {
366                                             if ((verbose & 2) != 0)
367                                                  std::cout << "Command ";
368                                        }
369                                        int length = parameters[iParam].lengthMatchName() + 1;
370                                        if (lengthLine + length > 80) {
371                                             std::cout << std::endl;
372                                             across = 0;
373                                             lengthLine = 0;
374                                        }
375                                        std::cout << " " << parameters[iParam].matchName();
376                                        lengthLine += length ;
377                                        across++;
378                                        if (across == maxAcross) {
379                                             across = 0;
380                                             if (verbose) {
381                                                  // put out description as well
382                                                  if ((verbose & 1) != 0)
383                                                       std::cout << parameters[iParam].shortHelp();
384                                                  std::cout << std::endl;
385                                                  if ((verbose & 2) != 0) {
386                                                       std::cout << "---- description" << std::endl;
387                                                       parameters[iParam].printLongHelp();
388                                                       std::cout << "----" << std::endl << std::endl;
389                                                  }
390                                             } else {
391                                                  std::cout << std::endl;
392                                             }
393                                        }
394                                   }
395                              }
396                              if (across)
397                                   std::cout << std::endl;
398                         }
399                    } else if (type == CBC_PARAM_FULLGENERALQUERY) {
400                         std::cout << "Full list of commands is:" << std::endl;
401                         int maxAcross = 5;
402                         int limits[] = {1, 101, 201, 301, 401};
403                         std::vector<std::string> types;
404                         types.push_back("Double parameters:");
405                         types.push_back("Int parameters:");
406                         types.push_back("Keyword parameters and others:");
407                         types.push_back("Actions:");
408                         int iType;
409                         for (iType = 0; iType < 4; iType++) {
410                              int across = 0;
411                              std::cout << types[iType] << std::endl;
412                              for ( iParam = 0; iParam < numberParameters; iParam++ ) {
413                                   int type = parameters[iParam].type();
414                                   if (type >= limits[iType]
415                                             && type < limits[iType+1]) {
416                                        if (!across)
417                                             std::cout << "  ";
418                                        std::cout << parameters[iParam].matchName() << "  ";
419                                        across++;
420                                        if (across == maxAcross) {
421                                             std::cout << std::endl;
422                                             across = 0;
423                                        }
424                                   }
425                              }
426                              if (across)
427                                   std::cout << std::endl;
428                         }
429                    } else if (type < 101) {
430                         // get next field as double
431                         double value = CoinReadGetDoubleField(argc, argv, &valid);
432                         if (!valid) {
433                              parameters[iParam].setDoubleParameter(models + iModel, value);
434                         } else if (valid == 1) {
435                              std::cout << " is illegal for double parameter " << parameters[iParam].name() << " value remains " <<
436                                        parameters[iParam].doubleValue() << std::endl;
437                         } else {
438                              std::cout << parameters[iParam].name() << " has value " <<
439                                        parameters[iParam].doubleValue() << std::endl;
440                         }
441                    } else if (type < 201) {
442                         // get next field as int
443                         int value = CoinReadGetIntField(argc, argv, &valid);
444                         if (!valid) {
445                              if (parameters[iParam].type() == CLP_PARAM_INT_PRESOLVEPASS)
446                                   preSolve = value;
447                              else if (parameters[iParam].type() == CLP_PARAM_INT_IDIOT)
448                                   doIdiot = value;
449                              else if (parameters[iParam].type() == CLP_PARAM_INT_SPRINT)
450                                   doSprint = value;
451                              else if (parameters[iParam].type() == CLP_PARAM_INT_OUTPUTFORMAT)
452                                   outputFormat = value;
453                              else if (parameters[iParam].type() == CLP_PARAM_INT_SLPVALUE)
454                                   slpValue = value;
455                              else if (parameters[iParam].type() == CLP_PARAM_INT_CPP)
456                                   cppValue = value;
457                              else if (parameters[iParam].type() == CLP_PARAM_INT_PRESOLVEOPTIONS)
458                                   presolveOptions = value;
459                              else if (parameters[iParam].type() == CLP_PARAM_INT_PRINTOPTIONS)
460                                   printOptions = value;
461                              else if (parameters[iParam].type() == CLP_PARAM_INT_SUBSTITUTION)
462                                   substitution = value;
463                              else if (parameters[iParam].type() == CLP_PARAM_INT_DUALIZE)
464                                   dualize = value;
465                              else if (parameters[iParam].type() == CLP_PARAM_INT_VERBOSE)
466                                   verbose = value;
467                              parameters[iParam].setIntParameter(models + iModel, value);
468                         } else if (valid == 1) {
469                              std::cout << " is illegal for integer parameter " << parameters[iParam].name() << " value remains " <<
470                                        parameters[iParam].intValue() << std::endl;
471                         } else {
472                              std::cout << parameters[iParam].name() << " has value " <<
473                                        parameters[iParam].intValue() << std::endl;
474                         }
475                    } else if (type < 301) {
476                         // one of several strings
477                         std::string value = CoinReadGetString(argc, argv);
478                         int action = parameters[iParam].parameterOption(value);
479                         if (action < 0) {
480                              if (value != "EOL") {
481                                   // no match
482                                   parameters[iParam].printOptions();
483                              } else {
484                                   // print current value
485                                   std::cout << parameters[iParam].name() << " has value " <<
486                                             parameters[iParam].currentOption() << std::endl;
487                              }
488                         } else {
489                              parameters[iParam].setCurrentOption(action);
490                              // for now hard wired
491                              switch (type) {
492                              case CLP_PARAM_STR_DIRECTION:
493                                   if (action == 0)
494                                        models[iModel].setOptimizationDirection(1);
495                                   else if (action == 1)
496                                        models[iModel].setOptimizationDirection(-1);
497                                   else
498                                        models[iModel].setOptimizationDirection(0);
499                                   break;
500                              case CLP_PARAM_STR_DUALPIVOT:
501                                   if (action == 0) {
502                                        ClpDualRowSteepest steep(3);
503                                        models[iModel].setDualRowPivotAlgorithm(steep);
504                                   } else if (action == 1) {
505                                        //ClpDualRowDantzig dantzig;
506                                        ClpDualRowSteepest dantzig(5);
507                                        models[iModel].setDualRowPivotAlgorithm(dantzig);
508                                   } else if (action == 2) {
509                                        // partial steep
510                                        ClpDualRowSteepest steep(2);
511                                        models[iModel].setDualRowPivotAlgorithm(steep);
512                                   } else {
513                                        ClpDualRowSteepest steep;
514                                        models[iModel].setDualRowPivotAlgorithm(steep);
515                                   }
516                                   break;
517                              case CLP_PARAM_STR_PRIMALPIVOT:
518                                   if (action == 0) {
519                                        ClpPrimalColumnSteepest steep(3);
520                                        models[iModel].setPrimalColumnPivotAlgorithm(steep);
521                                   } else if (action == 1) {
522                                        ClpPrimalColumnSteepest steep(0);
523                                        models[iModel].setPrimalColumnPivotAlgorithm(steep);
524                                   } else if (action == 2) {
525                                        ClpPrimalColumnDantzig dantzig;
526                                        models[iModel].setPrimalColumnPivotAlgorithm(dantzig);
527                                   } else if (action == 3) {
528                                        ClpPrimalColumnSteepest steep(4);
529                                        models[iModel].setPrimalColumnPivotAlgorithm(steep);
530                                   } else if (action == 4) {
531                                        ClpPrimalColumnSteepest steep(1);
532                                        models[iModel].setPrimalColumnPivotAlgorithm(steep);
533                                   } else if (action == 5) {
534                                        ClpPrimalColumnSteepest steep(2);
535                                        models[iModel].setPrimalColumnPivotAlgorithm(steep);
536                                   } else if (action == 6) {
537                                        ClpPrimalColumnSteepest steep(10);
538                                        models[iModel].setPrimalColumnPivotAlgorithm(steep);
539                                   }
540                                   break;
541                              case CLP_PARAM_STR_SCALING:
542                                   models[iModel].scaling(action);
543                                   break;
544                              case CLP_PARAM_STR_AUTOSCALE:
545                                   models[iModel].setAutomaticScaling(action != 0);
546                                   break;
547                              case CLP_PARAM_STR_SPARSEFACTOR:
548                                   models[iModel].setSparseFactorization((1 - action) != 0);
549                                   break;
550                              case CLP_PARAM_STR_BIASLU:
551                                   models[iModel].factorization()->setBiasLU(action);
552                                   break;
553                              case CLP_PARAM_STR_PERTURBATION:
554                                   if (action == 0)
555                                        models[iModel].setPerturbation(50);
556                                   else
557                                        models[iModel].setPerturbation(100);
558                                   break;
559                              case CLP_PARAM_STR_ERRORSALLOWED:
560                                   allowImportErrors = action;
561                                   break;
562                              case CLP_PARAM_STR_INTPRINT:
563                                   printMode = action;
564                                   break;
565                              case CLP_PARAM_STR_KEEPNAMES:
566                                   keepImportNames = 1 - action;
567                                   break;
568                              case CLP_PARAM_STR_PRESOLVE:
569                                   if (action == 0)
570                                        preSolve = 5;
571                                   else if (action == 1)
572                                        preSolve = 0;
573                                   else if (action == 2)
574                                        preSolve = 10;
575                                   else
576                                        preSolveFile = true;
577                                   break;
578                              case CLP_PARAM_STR_PFI:
579                                   models[iModel].factorization()->setForrestTomlin(action == 0);
580                                   break;
581                              case CLP_PARAM_STR_FACTORIZATION:
582                                   models[iModel].factorization()->forceOtherFactorization(action);
583                                   break;
584                              case CLP_PARAM_STR_CRASH:
585                                   doCrash = action;
586                                   break;
587                              case CLP_PARAM_STR_VECTOR:
588                                   doVector = action;
589                                   break;
590                              case CLP_PARAM_STR_MESSAGES:
591                                   models[iModel].messageHandler()->setPrefix(action != 0);
592                                   break;
593                              case CLP_PARAM_STR_CHOLESKY:
594                                   choleskyType = action;
595                                   break;
596                              case CLP_PARAM_STR_GAMMA:
597                                   gamma = action;
598                                   break;
599                              case CLP_PARAM_STR_BARRIERSCALE:
600                                   scaleBarrier = action;
601                                   break;
602                              case CLP_PARAM_STR_KKT:
603                                   doKKT = action;
604                                   break;
605                              case CLP_PARAM_STR_CROSSOVER:
606                                   crossover = action;
607                                   break;
608                              default:
609                                   //abort();
610                                   break;
611                              }
612                         }
613                    } else {
614                         // action
615                         if (type == CLP_PARAM_ACTION_EXIT)
616                              break; // stop all
617                         switch (type) {
618                         case CLP_PARAM_ACTION_DUALSIMPLEX:
619                         case CLP_PARAM_ACTION_PRIMALSIMPLEX:
620                         case CLP_PARAM_ACTION_EITHERSIMPLEX:
621                         case CLP_PARAM_ACTION_BARRIER:
622                              // synonym for dual
623                         case CBC_PARAM_ACTION_BAB:
624                              if (goodModels[iModel]) {
625                                   double objScale =
626                                        parameters[whichParam(CLP_PARAM_DBL_OBJSCALE2, numberParameters, parameters)].doubleValue();
627                                   if (objScale != 1.0) {
628                                        int iColumn;
629                                        int numberColumns = models[iModel].numberColumns();
630                                        double * dualColumnSolution =
631                                             models[iModel].dualColumnSolution();
632                                        ClpObjective * obj = models[iModel].objectiveAsObject();
633                                        assert(dynamic_cast<ClpLinearObjective *> (obj));
634                                        double offset;
635                                        double * objective = obj->gradient(NULL, NULL, offset, true);
636                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
637                                             dualColumnSolution[iColumn] *= objScale;
638                                             objective[iColumn] *= objScale;;
639                                        }
640                                        int iRow;
641                                        int numberRows = models[iModel].numberRows();
642                                        double * dualRowSolution =
643                                             models[iModel].dualRowSolution();
644                                        for (iRow = 0; iRow < numberRows; iRow++)
645                                             dualRowSolution[iRow] *= objScale;
646                                        models[iModel].setObjectiveOffset(objScale * models[iModel].objectiveOffset());
647                                   }
648                                   ClpSolve::SolveType method;
649                                   ClpSolve::PresolveType presolveType;
650                                   ClpSimplex * model2 = models + iModel;
651                                   ClpSolve solveOptions;
652                                   if (dualize==4) { 
653                                     solveOptions.setSpecialOption(4, 77);
654                                     dualize=0;
655                                   }
656                                   if (dualize) {
657                                        bool tryIt = true;
658                                        double fractionColumn = 1.0;
659                                        double fractionRow = 1.0;
660                                        if (dualize == 3) {
661                                             dualize = 1;
662                                             int numberColumns = model2->numberColumns();
663                                             int numberRows = model2->numberRows();
664                                             if (numberRows < 50000 || 5 * numberColumns > numberRows) {
665                                                  tryIt = false;
666                                             } else {
667                                                  fractionColumn = 0.1;
668                                                  fractionRow = 0.1;
669                                             }
670                                        }
671                                        if (tryIt) {
672                                             model2 = static_cast<ClpSimplexOther *> (model2)->dualOfModel(fractionRow, fractionColumn);
673                                             if (model2) {
674                                                  printf("Dual of model has %d rows and %d columns\n",
675                                                         model2->numberRows(), model2->numberColumns());
676                                                  model2->setOptimizationDirection(1.0);
677                                             } else {
678                                                  model2 = models + iModel;
679                                                  dualize = 0;
680                                             }
681                                        } else {
682                                             dualize = 0;
683                                        }
684                                   }
685                                   if (preSolveFile)
686                                        presolveOptions |= 0x40000000;
687                                   solveOptions.setPresolveActions(presolveOptions);
688                                   solveOptions.setSubstitution(substitution);
689                                   if (preSolve != 5 && preSolve) {
690                                        presolveType = ClpSolve::presolveNumber;
691                                        if (preSolve < 0) {
692                                             preSolve = - preSolve;
693                                             if (preSolve <= 100) {
694                                                  presolveType = ClpSolve::presolveNumber;
695                                                  printf("Doing %d presolve passes - picking up non-costed slacks\n",
696                                                         preSolve);
697                                                  solveOptions.setDoSingletonColumn(true);
698                                             } else {
699                                                  preSolve -= 100;
700                                                  presolveType = ClpSolve::presolveNumberCost;
701                                                  printf("Doing %d presolve passes - picking up costed slacks\n",
702                                                         preSolve);
703                                             }
704                                        }
705                                   } else if (preSolve) {
706                                        presolveType = ClpSolve::presolveOn;
707                                   } else {
708                                        presolveType = ClpSolve::presolveOff;
709                                   }
710                                   solveOptions.setPresolveType(presolveType, preSolve);
711                                   if (type == CLP_PARAM_ACTION_DUALSIMPLEX ||
712                                             type == CBC_PARAM_ACTION_BAB) {
713                                        method = ClpSolve::useDual;
714                                   } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) {
715                                        method = ClpSolve::usePrimalorSprint;
716                                   } else if (type == CLP_PARAM_ACTION_EITHERSIMPLEX) {
717                                        method = ClpSolve::automatic;
718                                   } else {
719                                        method = ClpSolve::useBarrier;
720                                        if (crossover == 1) {
721                                             method = ClpSolve::useBarrierNoCross;
722                                        } else if (crossover == 2) {
723                                             ClpObjective * obj = models[iModel].objectiveAsObject();
724                                             if (obj->type() > 1) {
725                                                  method = ClpSolve::useBarrierNoCross;
726                                                  presolveType = ClpSolve::presolveOff;
727                                                  solveOptions.setPresolveType(presolveType, preSolve);
728                                             }
729                                        }
730                                   }
731                                   solveOptions.setSolveType(method);
732                                   solveOptions.setSpecialOption(5, printOptions & 1);
733                                   if (doVector) {
734                                        ClpMatrixBase * matrix = models[iModel].clpMatrix();
735                                        if (dynamic_cast< ClpPackedMatrix*>(matrix)) {
736                                             ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix);
737                                             clpMatrix->makeSpecialColumnCopy();
738                                        }
739                                   }
740                                   if (method == ClpSolve::useDual) {
741                                        // dual
742                                        if (doCrash)
743                                             solveOptions.setSpecialOption(0, 1, doCrash); // crash
744                                        else if (doIdiot)
745                                             solveOptions.setSpecialOption(0, 2, doIdiot); // possible idiot
746                                   } else if (method == ClpSolve::usePrimalorSprint) {
747                                        // primal
748                                        // if slp turn everything off
749                                        if (slpValue > 0) {
750                                             doCrash = false;
751                                             doSprint = 0;
752                                             doIdiot = -1;
753                                             solveOptions.setSpecialOption(1, 10, slpValue); // slp
754                                             method = ClpSolve::usePrimal;
755                                        }
756                                        if (doCrash) {
757                                             solveOptions.setSpecialOption(1, 1, doCrash); // crash
758                                        } else if (doSprint > 0) {
759                                             // sprint overrides idiot
760                                             solveOptions.setSpecialOption(1, 3, doSprint); // sprint
761                                        } else if (doIdiot > 0) {
762                                             solveOptions.setSpecialOption(1, 2, doIdiot); // idiot
763                                        } else if (slpValue <= 0) {
764                                             if (doIdiot == 0) {
765                                                  if (doSprint == 0)
766                                                       solveOptions.setSpecialOption(1, 4); // all slack
767                                                  else
768                                                       solveOptions.setSpecialOption(1, 9); // all slack or sprint
769                                             } else {
770                                                  if (doSprint == 0)
771                                                       solveOptions.setSpecialOption(1, 8); // all slack or idiot
772                                                  else
773                                                       solveOptions.setSpecialOption(1, 7); // initiative
774                                             }
775                                        }
776                                        if (basisHasValues == -1)
777                                             solveOptions.setSpecialOption(1, 11); // switch off values
778                                   } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) {
779                                        int barrierOptions = choleskyType;
780                                        if (scaleBarrier) {
781                                             if ((scaleBarrier & 1) != 0)
782                                                  barrierOptions |= 8;
783                                             barrierOptions |= 2048 * (scaleBarrier >> 1);
784                                        }
785                                        if (doKKT)
786                                             barrierOptions |= 16;
787                                        if (gamma)
788                                             barrierOptions |= 32 * gamma;
789                                        if (crossover == 3)
790                                             barrierOptions |= 256; // try presolve in crossover
791                                        solveOptions.setSpecialOption(4, barrierOptions);
792                                   }
793                                   int status;
794                                   if (cppValue >= 0) {
795                                        // generate code
796                                        FILE * fp = fopen("user_driver.cpp", "w");
797                                        if (fp) {
798                                             // generate enough to do solveOptions
799                                             model2->generateCpp(fp);
800                                             solveOptions.generateCpp(fp);
801                                             fclose(fp);
802                                             // now call generate code
803                                             generateCode("user_driver.cpp", cppValue);
804                                        } else {
805                                             std::cout << "Unable to open file user_driver.cpp" << std::endl;
806                                        }
807                                   }
808#ifdef CLP_MULTIPLE_FACTORIZATIONS
809                                   int denseCode = parameters[whichParam(CBC_PARAM_INT_DENSE, numberParameters, parameters)].intValue();
810                                   model2->factorization()->setGoDenseThreshold(denseCode);
811                                   int smallCode = parameters[whichParam(CBC_PARAM_INT_SMALLFACT, numberParameters, parameters)].intValue();
812                                   model2->factorization()->setGoSmallThreshold(smallCode);
813                                   model2->factorization()->goDenseOrSmall(model2->numberRows());
814#endif
815                                   try {
816                                        status = model2->initialSolve(solveOptions);
817                                   } catch (CoinError& e) {
818                                        e.print();
819                                        status = -1;
820                                   }
821                                   if (dualize) {
822                                        int returnCode = static_cast<ClpSimplexOther *> (models + iModel)->restoreFromDual(model2);
823                                        if (model2->status() == 3)
824                                             returnCode = 0;
825                                        delete model2;
826                                        if (returnCode && dualize != 2) {
827                                             currentModel = models + iModel;
828                                             // register signal handler
829                                             signal(SIGINT, signal_handler);
830                                             models[iModel].primal(1);
831                                             currentModel = NULL;
832                                        }
833                                   }
834                                   if (status >= 0)
835                                        basisHasValues = 1;
836                              } else {
837                                   std::cout << "** Current model not valid" << std::endl;
838                              }
839                              break;
840                         case CLP_PARAM_ACTION_STATISTICS:
841                              if (goodModels[iModel]) {
842                                   // If presolve on look at presolved
843                                   bool deleteModel2 = false;
844                                   ClpSimplex * model2 = models + iModel;
845                                   if (preSolve) {
846                                        ClpPresolve pinfo;
847                                        int presolveOptions2 = presolveOptions&~0x40000000;
848                                        if ((presolveOptions2 & 0xffff) != 0)
849                                             pinfo.setPresolveActions(presolveOptions2);
850                                        pinfo.setSubstitution(substitution);
851                                        if ((printOptions & 1) != 0)
852                                             pinfo.statistics();
853                                        double presolveTolerance =
854                                             parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].doubleValue();
855                                        model2 =
856                                             pinfo.presolvedModel(models[iModel], presolveTolerance,
857                                                                  true, preSolve);
858                                        if (model2) {
859                                             printf("Statistics for presolved model\n");
860                                             deleteModel2 = true;
861                                        } else {
862                                             printf("Presolved model looks infeasible - will use unpresolved\n");
863                                             model2 = models + iModel;
864                                        }
865                                   } else {
866                                        printf("Statistics for unpresolved model\n");
867                                        model2 =  models + iModel;
868                                   }
869                                   statistics(models + iModel, model2);
870                                   if (deleteModel2)
871                                        delete model2;
872                              } else {
873                                   std::cout << "** Current model not valid" << std::endl;
874                              }
875                              break;
876                         case CLP_PARAM_ACTION_TIGHTEN:
877                              if (goodModels[iModel]) {
878                                   int numberInfeasibilities = models[iModel].tightenPrimalBounds();
879                                   if (numberInfeasibilities)
880                                        std::cout << "** Analysis indicates model infeasible" << std::endl;
881                              } else {
882                                   std::cout << "** Current model not valid" << std::endl;
883                              }
884                              break;
885                         case CLP_PARAM_ACTION_PLUSMINUS:
886                              if (goodModels[iModel]) {
887                                   ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
888                                   ClpPackedMatrix* clpMatrix =
889                                        dynamic_cast< ClpPackedMatrix*>(saveMatrix);
890                                   if (clpMatrix) {
891                                        ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
892                                        if (newMatrix->getIndices()) {
893                                             models[iModel].replaceMatrix(newMatrix);
894                                             delete saveMatrix;
895                                             std::cout << "Matrix converted to +- one matrix" << std::endl;
896                                        } else {
897                                             std::cout << "Matrix can not be converted to +- 1 matrix" << std::endl;
898                                        }
899                                   } else {
900                                        std::cout << "Matrix not a ClpPackedMatrix" << std::endl;
901                                   }
902                              } else {
903                                   std::cout << "** Current model not valid" << std::endl;
904                              }
905                              break;
906                         case CLP_PARAM_ACTION_NETWORK:
907                              if (goodModels[iModel]) {
908                                   ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
909                                   ClpPackedMatrix* clpMatrix =
910                                        dynamic_cast< ClpPackedMatrix*>(saveMatrix);
911                                   if (clpMatrix) {
912                                        ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
913                                        if (newMatrix->getIndices()) {
914                                             models[iModel].replaceMatrix(newMatrix);
915                                             delete saveMatrix;
916                                             std::cout << "Matrix converted to network matrix" << std::endl;
917                                        } else {
918                                             std::cout << "Matrix can not be converted to network matrix" << std::endl;
919                                        }
920                                   } else {
921                                        std::cout << "Matrix not a ClpPackedMatrix" << std::endl;
922                                   }
923                              } else {
924                                   std::cout << "** Current model not valid" << std::endl;
925                              }
926                              break;
927                         case CLP_PARAM_ACTION_IMPORT: {
928                              // get next field
929                              field = CoinReadGetString(argc, argv);
930                              if (field == "$") {
931                                   field = parameters[iParam].stringValue();
932                              } else if (field == "EOL") {
933                                   parameters[iParam].printString();
934                                   break;
935                              } else {
936                                   parameters[iParam].setStringValue(field);
937                              }
938                              std::string fileName;
939                              bool canOpen = false;
940                              // See if gmpl file
941                              int gmpl = 0;
942                              std::string gmplData;
943                              if (field == "-") {
944                                   // stdin
945                                   canOpen = true;
946                                   fileName = "-";
947                              } else {
948                                   // See if .lp
949                                   {
950                                        const char * c_name = field.c_str();
951                                        size_t length = strlen(c_name);
952                                        if (length > 3 && !strncmp(c_name + length - 3, ".lp", 3))
953                                             gmpl = -1; // .lp
954                                   }
955                                   bool absolutePath;
956                                   if (dirsep == '/') {
957                                        // non Windows (or cygwin)
958                                        absolutePath = (field[0] == '/');
959                                   } else {
960                                        //Windows (non cycgwin)
961                                        absolutePath = (field[0] == '\\');
962                                        // but allow for :
963                                        if (strchr(field.c_str(), ':'))
964                                             absolutePath = true;
965                                   }
966                                   if (absolutePath) {
967                                        fileName = field;
968                                        size_t length = field.size();
969                                        size_t percent = field.find('%');
970                                        if (percent < length && percent > 0) {
971                                             gmpl = 1;
972                                             fileName = field.substr(0, percent);
973                                             gmplData = field.substr(percent + 1);
974                                             if (percent < length - 1)
975                                                  gmpl = 2; // two files
976                                             printf("GMPL model file %s and data file %s\n",
977                                                    fileName.c_str(), gmplData.c_str());
978                                        }
979                                   } else if (field[0] == '~') {
980                                        char * environVar = getenv("HOME");
981                                        if (environVar) {
982                                             std::string home(environVar);
983                                             field = field.erase(0, 1);
984                                             fileName = home + field;
985                                        } else {
986                                             fileName = field;
987                                        }
988                                   } else {
989                                        fileName = directory + field;
990                                        // See if gmpl (model & data) - or even lp file
991                                        size_t length = field.size();
992                                        size_t percent = field.find('%');
993                                        if (percent < length && percent > 0) {
994                                             gmpl = 1;
995                                             fileName = directory + field.substr(0, percent);
996                                             gmplData = directory + field.substr(percent + 1);
997                                             if (percent < length - 1)
998                                                  gmpl = 2; // two files
999                                             printf("GMPL model file %s and data file %s\n",
1000                                                    fileName.c_str(), gmplData.c_str());
1001                                        }
1002                                   }
1003                                   std::string name = fileName;
1004                                   if (fileCoinReadable(name)) {
1005                                        // can open - lets go for it
1006                                        canOpen = true;
1007                                        if (gmpl == 2) {
1008                                             FILE *fp;
1009                                             fp = fopen(gmplData.c_str(), "r");
1010                                             if (fp) {
1011                                                  fclose(fp);
1012                                             } else {
1013                                                  canOpen = false;
1014                                                  std::cout << "Unable to open file " << gmplData << std::endl;
1015                                             }
1016                                        }
1017                                   } else {
1018                                        std::cout << "Unable to open file " << fileName << std::endl;
1019                                   }
1020                              }
1021                              if (canOpen) {
1022                                   int status;
1023                                   if (!gmpl)
1024                                        status = models[iModel].readMps(fileName.c_str(),
1025                                                                        keepImportNames != 0,
1026                                                                        allowImportErrors != 0);
1027                                   else if (gmpl > 0)
1028                                        status = models[iModel].readGMPL(fileName.c_str(),
1029                                                                         (gmpl == 2) ? gmplData.c_str() : NULL,
1030                                                                         keepImportNames != 0);
1031                                   else
1032#ifdef KILL_ZERO_READLP
1033                                     status = models[iModel].readLp(fileName.c_str(), models[iModel].getSmallElementValue());
1034#else
1035                                     status = models[iModel].readLp(fileName.c_str(), 1.0e-12);
1036#endif
1037                                   if (!status || (status > 0 && allowImportErrors)) {
1038                                        goodModels[iModel] = true;
1039                                        // sets to all slack (not necessary?)
1040                                        models[iModel].createStatus();
1041                                        time2 = CoinCpuTime();
1042                                        totalTime += time2 - time1;
1043                                        time1 = time2;
1044                                        // Go to canned file if just input file
1045                                        if (CbcOrClpRead_mode == 2 && argc == 2) {
1046                                             // only if ends .mps
1047                                             char * find = const_cast<char *>(strstr(fileName.c_str(), ".mps"));
1048                                             if (find && find[4] == '\0') {
1049                                                  find[1] = 'p';
1050                                                  find[2] = 'a';
1051                                                  find[3] = 'r';
1052                                                  FILE *fp = fopen(fileName.c_str(), "r");
1053                                                  if (fp) {
1054                                                       CbcOrClpReadCommand = fp; // Read from that file
1055                                                       CbcOrClpRead_mode = -1;
1056                                                  }
1057                                             }
1058                                        }
1059                                   } else {
1060                                        // errors
1061                                        std::cout << "There were " << status <<
1062                                                  " errors on input" << std::endl;
1063                                   }
1064                              }
1065                         }
1066                         break;
1067                         case CLP_PARAM_ACTION_EXPORT:
1068                              if (goodModels[iModel]) {
1069                                   double objScale =
1070                                        parameters[whichParam(CLP_PARAM_DBL_OBJSCALE2, numberParameters, parameters)].doubleValue();
1071                                   if (objScale != 1.0) {
1072                                        int iColumn;
1073                                        int numberColumns = models[iModel].numberColumns();
1074                                        double * dualColumnSolution =
1075                                             models[iModel].dualColumnSolution();
1076                                        ClpObjective * obj = models[iModel].objectiveAsObject();
1077                                        assert(dynamic_cast<ClpLinearObjective *> (obj));
1078                                        double offset;
1079                                        double * objective = obj->gradient(NULL, NULL, offset, true);
1080                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1081                                             dualColumnSolution[iColumn] *= objScale;
1082                                             objective[iColumn] *= objScale;;
1083                                        }
1084                                        int iRow;
1085                                        int numberRows = models[iModel].numberRows();
1086                                        double * dualRowSolution =
1087                                             models[iModel].dualRowSolution();
1088                                        for (iRow = 0; iRow < numberRows; iRow++)
1089                                             dualRowSolution[iRow] *= objScale;
1090                                        models[iModel].setObjectiveOffset(objScale * models[iModel].objectiveOffset());
1091                                   }
1092                                   // get next field
1093                                   field = CoinReadGetString(argc, argv);
1094                                   if (field == "$") {
1095                                        field = parameters[iParam].stringValue();
1096                                   } else if (field == "EOL") {
1097                                        parameters[iParam].printString();
1098                                        break;
1099                                   } else {
1100                                        parameters[iParam].setStringValue(field);
1101                                   }
1102                                   std::string fileName;
1103                                   bool canOpen = false;
1104                                   if (field[0] == '/' || field[0] == '\\') {
1105                                        fileName = field;
1106                                   } else if (field[0] == '~') {
1107                                        char * environVar = getenv("HOME");
1108                                        if (environVar) {
1109                                             std::string home(environVar);
1110                                             field = field.erase(0, 1);
1111                                             fileName = home + field;
1112                                        } else {
1113                                             fileName = field;
1114                                        }
1115                                   } else {
1116                                        fileName = directory + field;
1117                                   }
1118                                   FILE *fp = fopen(fileName.c_str(), "w");
1119                                   if (fp) {
1120                                        // can open - lets go for it
1121                                        fclose(fp);
1122                                        canOpen = true;
1123                                   } else {
1124                                        std::cout << "Unable to open file " << fileName << std::endl;
1125                                   }
1126                                   if (canOpen) {
1127                                        // If presolve on then save presolved
1128                                        bool deleteModel2 = false;
1129                                        ClpSimplex * model2 = models + iModel;
1130                                        if (dualize && dualize < 3) {
1131                                             model2 = static_cast<ClpSimplexOther *> (model2)->dualOfModel();
1132                                             printf("Dual of model has %d rows and %d columns\n",
1133                                                    model2->numberRows(), model2->numberColumns());
1134                                             model2->setOptimizationDirection(1.0);
1135                                             preSolve = 0; // as picks up from model
1136                                        }
1137                                        if (preSolve) {
1138                                             ClpPresolve pinfo;
1139                                             int presolveOptions2 = presolveOptions&~0x40000000;
1140                                             if ((presolveOptions2 & 0xffff) != 0)
1141                                                  pinfo.setPresolveActions(presolveOptions2);
1142                                             pinfo.setSubstitution(substitution);
1143                                             if ((printOptions & 1) != 0)
1144                                                  pinfo.statistics();
1145                                             double presolveTolerance =
1146                                                  parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].doubleValue();
1147                                             model2 =
1148                                                  pinfo.presolvedModel(models[iModel], presolveTolerance,
1149                                                                       true, preSolve, false, false);
1150                                             if (model2) {
1151                                                  printf("Saving presolved model on %s\n",
1152                                                         fileName.c_str());
1153                                                  deleteModel2 = true;
1154                                             } else {
1155                                                  printf("Presolved model looks infeasible - saving original on %s\n",
1156                                                         fileName.c_str());
1157                                                  deleteModel2 = false;
1158                                                  model2 = models + iModel;
1159
1160                                             }
1161                                        } else {
1162                                             printf("Saving model on %s\n",
1163                                                    fileName.c_str());
1164                                        }
1165#if 0
1166                                        // Convert names
1167                                        int iRow;
1168                                        int numberRows = model2->numberRows();
1169                                        int iColumn;
1170                                        int numberColumns = model2->numberColumns();
1171
1172                                        char ** rowNames = NULL;
1173                                        char ** columnNames = NULL;
1174                                        if (model2->lengthNames()) {
1175                                             rowNames = new char * [numberRows];
1176                                             for (iRow = 0; iRow < numberRows; iRow++) {
1177                                                  rowNames[iRow] =
1178                                                       CoinStrdup(model2->rowName(iRow).c_str());
1179#ifdef STRIPBLANKS
1180                                                  char * xx = rowNames[iRow];
1181                                                  int i;
1182                                                  int length = strlen(xx);
1183                                                  int n = 0;
1184                                                  for (i = 0; i < length; i++) {
1185                                                       if (xx[i] != ' ')
1186                                                            xx[n++] = xx[i];
1187                                                  }
1188                                                  xx[n] = '\0';
1189#endif
1190                                             }
1191
1192                                             columnNames = new char * [numberColumns];
1193                                             for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1194                                                  columnNames[iColumn] =
1195                                                       CoinStrdup(model2->columnName(iColumn).c_str());
1196#ifdef STRIPBLANKS
1197                                                  char * xx = columnNames[iColumn];
1198                                                  int i;
1199                                                  int length = strlen(xx);
1200                                                  int n = 0;
1201                                                  for (i = 0; i < length; i++) {
1202                                                       if (xx[i] != ' ')
1203                                                            xx[n++] = xx[i];
1204                                                  }
1205                                                  xx[n] = '\0';
1206#endif
1207                                             }
1208                                        }
1209                                        CoinMpsIO writer;
1210                                        writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
1211                                                          model2->getColLower(), model2->getColUpper(),
1212                                                          model2->getObjCoefficients(),
1213                                                          (const char*) 0 /*integrality*/,
1214                                                          model2->getRowLower(), model2->getRowUpper(),
1215                                                          columnNames, rowNames);
1216                                        // Pass in array saying if each variable integer
1217                                        writer.copyInIntegerInformation(model2->integerInformation());
1218                                        writer.setObjectiveOffset(model2->objectiveOffset());
1219                                        writer.writeMps(fileName.c_str(), 0, 1, 1);
1220                                        if (rowNames) {
1221                                             for (iRow = 0; iRow < numberRows; iRow++) {
1222                                                  free(rowNames[iRow]);
1223                                             }
1224                                             delete [] rowNames;
1225                                             for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1226                                                  free(columnNames[iColumn]);
1227                                             }
1228                                             delete [] columnNames;
1229                                        }
1230#else
1231                                        model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1) & 1));
1232#endif
1233                                        if (deleteModel2)
1234                                             delete model2;
1235                                        time2 = CoinCpuTime();
1236                                        totalTime += time2 - time1;
1237                                        time1 = time2;
1238                                   }
1239                              } else {
1240                                   std::cout << "** Current model not valid" << std::endl;
1241                              }
1242                              break;
1243                         case CLP_PARAM_ACTION_BASISIN:
1244                              if (goodModels[iModel]) {
1245                                   // get next field
1246                                   field = CoinReadGetString(argc, argv);
1247                                   if (field == "$") {
1248                                        field = parameters[iParam].stringValue();
1249                                   } else if (field == "EOL") {
1250                                        parameters[iParam].printString();
1251                                        break;
1252                                   } else {
1253                                        parameters[iParam].setStringValue(field);
1254                                   }
1255                                   std::string fileName;
1256                                   bool canOpen = false;
1257                                   if (field == "-") {
1258                                        // stdin
1259                                        canOpen = true;
1260                                        fileName = "-";
1261                                   } else {
1262                                        if (field[0] == '/' || field[0] == '\\') {
1263                                             fileName = field;
1264                                        } else if (field[0] == '~') {
1265                                             char * environVar = getenv("HOME");
1266                                             if (environVar) {
1267                                                  std::string home(environVar);
1268                                                  field = field.erase(0, 1);
1269                                                  fileName = home + field;
1270                                             } else {
1271                                                  fileName = field;
1272                                             }
1273                                        } else {
1274                                             fileName = directory + field;
1275                                        }
1276                                        FILE *fp = fopen(fileName.c_str(), "r");
1277                                        if (fp) {
1278                                             // can open - lets go for it
1279                                             fclose(fp);
1280                                             canOpen = true;
1281                                        } else {
1282                                             std::cout << "Unable to open file " << fileName << std::endl;
1283                                        }
1284                                   }
1285                                   if (canOpen) {
1286                                        int values = models[iModel].readBasis(fileName.c_str());
1287                                        if (values == 0)
1288                                             basisHasValues = -1;
1289                                        else
1290                                             basisHasValues = 1;
1291                                   }
1292                              } else {
1293                                   std::cout << "** Current model not valid" << std::endl;
1294                              }
1295                              break;
1296                         case CLP_PARAM_ACTION_PRINTMASK:
1297                              // get next field
1298                         {
1299                              std::string name = CoinReadGetString(argc, argv);
1300                              if (name != "EOL") {
1301                                   parameters[iParam].setStringValue(name);
1302                                   printMask = name;
1303                              } else {
1304                                   parameters[iParam].printString();
1305                              }
1306                         }
1307                         break;
1308                         case CLP_PARAM_ACTION_BASISOUT:
1309                              if (goodModels[iModel]) {
1310                                   // get next field
1311                                   field = CoinReadGetString(argc, argv);
1312                                   if (field == "$") {
1313                                        field = parameters[iParam].stringValue();
1314                                   } else if (field == "EOL") {
1315                                        parameters[iParam].printString();
1316                                        break;
1317                                   } else {
1318                                        parameters[iParam].setStringValue(field);
1319                                   }
1320                                   std::string fileName;
1321                                   bool canOpen = false;
1322                                   if (field[0] == '/' || field[0] == '\\') {
1323                                        fileName = field;
1324                                   } else if (field[0] == '~') {
1325                                        char * environVar = getenv("HOME");
1326                                        if (environVar) {
1327                                             std::string home(environVar);
1328                                             field = field.erase(0, 1);
1329                                             fileName = home + field;
1330                                        } else {
1331                                             fileName = field;
1332                                        }
1333                                   } else {
1334                                        fileName = directory + field;
1335                                   }
1336                                   FILE *fp = fopen(fileName.c_str(), "w");
1337                                   if (fp) {
1338                                        // can open - lets go for it
1339                                        fclose(fp);
1340                                        canOpen = true;
1341                                   } else {
1342                                        std::cout << "Unable to open file " << fileName << std::endl;
1343                                   }
1344                                   if (canOpen) {
1345                                        ClpSimplex * model2 = models + iModel;
1346                                        model2->writeBasis(fileName.c_str(), outputFormat > 1, outputFormat - 2);
1347                                        time2 = CoinCpuTime();
1348                                        totalTime += time2 - time1;
1349                                        time1 = time2;
1350                                   }
1351                              } else {
1352                                   std::cout << "** Current model not valid" << std::endl;
1353                              }
1354                              break;
1355                         case CLP_PARAM_ACTION_PARAMETRICS:
1356                              if (goodModels[iModel]) {
1357                                   // get next field
1358                                   field = CoinReadGetString(argc, argv);
1359                                   if (field == "$") {
1360                                        field = parameters[iParam].stringValue();
1361                                   } else if (field == "EOL") {
1362                                        parameters[iParam].printString();
1363                                        break;
1364                                   } else {
1365                                        parameters[iParam].setStringValue(field);
1366                                   }
1367                                   std::string fileName;
1368                                   //bool canOpen = false;
1369                                   if (field[0] == '/' || field[0] == '\\') {
1370                                        fileName = field;
1371                                   } else if (field[0] == '~') {
1372                                        char * environVar = getenv("HOME");
1373                                        if (environVar) {
1374                                             std::string home(environVar);
1375                                             field = field.erase(0, 1);
1376                                             fileName = home + field;
1377                                        } else {
1378                                             fileName = field;
1379                                        }
1380                                   } else {
1381                                        fileName = directory + field;
1382                                   }
1383                                   ClpSimplex * model2 = models + iModel;
1384                                   static_cast<ClpSimplexOther *> (model2)->parametrics(fileName.c_str());
1385                                   time2 = CoinCpuTime();
1386                                   totalTime += time2 - time1;
1387                                   time1 = time2;
1388                              } else {
1389                                   std::cout << "** Current model not valid" << std::endl;
1390                              }
1391                              break;
1392                         case CLP_PARAM_ACTION_SAVE: {
1393                              // get next field
1394                              field = CoinReadGetString(argc, argv);
1395                              if (field == "$") {
1396                                   field = parameters[iParam].stringValue();
1397                              } else if (field == "EOL") {
1398                                   parameters[iParam].printString();
1399                                   break;
1400                              } else {
1401                                   parameters[iParam].setStringValue(field);
1402                              }
1403                              std::string fileName;
1404                              bool canOpen = false;
1405                              if (field[0] == '/' || field[0] == '\\') {
1406                                   fileName = field;
1407                              } else if (field[0] == '~') {
1408                                   char * environVar = getenv("HOME");
1409                                   if (environVar) {
1410                                        std::string home(environVar);
1411                                        field = field.erase(0, 1);
1412                                        fileName = home + field;
1413                                   } else {
1414                                        fileName = field;
1415                                   }
1416                              } else {
1417                                   fileName = directory + field;
1418                              }
1419                              FILE *fp = fopen(fileName.c_str(), "wb");
1420                              if (fp) {
1421                                   // can open - lets go for it
1422                                   fclose(fp);
1423                                   canOpen = true;
1424                              } else {
1425                                   std::cout << "Unable to open file " << fileName << std::endl;
1426                              }
1427                              if (canOpen) {
1428                                   int status;
1429                                   // If presolve on then save presolved
1430                                   bool deleteModel2 = false;
1431                                   ClpSimplex * model2 = models + iModel;
1432                                   if (preSolve) {
1433                                        ClpPresolve pinfo;
1434                                        double presolveTolerance =
1435                                             parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].doubleValue();
1436                                        model2 =
1437                                             pinfo.presolvedModel(models[iModel], presolveTolerance,
1438                                                                  false, preSolve);
1439                                        if (model2) {
1440                                             printf("Saving presolved model on %s\n",
1441                                                    fileName.c_str());
1442                                             deleteModel2 = true;
1443                                        } else {
1444                                             printf("Presolved model looks infeasible - saving original on %s\n",
1445                                                    fileName.c_str());
1446                                             deleteModel2 = false;
1447                                             model2 = models + iModel;
1448
1449                                        }
1450                                   } else {
1451                                        printf("Saving model on %s\n",
1452                                               fileName.c_str());
1453                                   }
1454                                   status = model2->saveModel(fileName.c_str());
1455                                   if (deleteModel2)
1456                                        delete model2;
1457                                   if (!status) {
1458                                        goodModels[iModel] = true;
1459                                        time2 = CoinCpuTime();
1460                                        totalTime += time2 - time1;
1461                                        time1 = time2;
1462                                   } else {
1463                                        // errors
1464                                        std::cout << "There were errors on output" << std::endl;
1465                                   }
1466                              }
1467                         }
1468                         break;
1469                         case CLP_PARAM_ACTION_RESTORE: {
1470                              // get next field
1471                              field = CoinReadGetString(argc, argv);
1472                              if (field == "$") {
1473                                   field = parameters[iParam].stringValue();
1474                              } else if (field == "EOL") {
1475                                   parameters[iParam].printString();
1476                                   break;
1477                              } else {
1478                                   parameters[iParam].setStringValue(field);
1479                              }
1480                              std::string fileName;
1481                              bool canOpen = false;
1482                              if (field[0] == '/' || field[0] == '\\') {
1483                                   fileName = field;
1484                              } else if (field[0] == '~') {
1485                                   char * environVar = getenv("HOME");
1486                                   if (environVar) {
1487                                        std::string home(environVar);
1488                                        field = field.erase(0, 1);
1489                                        fileName = home + field;
1490                                   } else {
1491                                        fileName = field;
1492                                   }
1493                              } else {
1494                                   fileName = directory + field;
1495                              }
1496                              FILE *fp = fopen(fileName.c_str(), "rb");
1497                              if (fp) {
1498                                   // can open - lets go for it
1499                                   fclose(fp);
1500                                   canOpen = true;
1501                              } else {
1502                                   std::cout << "Unable to open file " << fileName << std::endl;
1503                              }
1504                              if (canOpen) {
1505                                   int status = models[iModel].restoreModel(fileName.c_str());
1506                                   if (!status) {
1507                                        goodModels[iModel] = true;
1508                                        time2 = CoinCpuTime();
1509                                        totalTime += time2 - time1;
1510                                        time1 = time2;
1511                                   } else {
1512                                        // errors
1513                                        std::cout << "There were errors on input" << std::endl;
1514                                   }
1515                              }
1516                         }
1517                         break;
1518                         case CLP_PARAM_ACTION_MAXIMIZE:
1519                              models[iModel].setOptimizationDirection(-1);
1520                              break;
1521                         case CLP_PARAM_ACTION_MINIMIZE:
1522                              models[iModel].setOptimizationDirection(1);
1523                              break;
1524                         case CLP_PARAM_ACTION_ALLSLACK:
1525                              models[iModel].allSlackBasis(true);
1526                              break;
1527                         case CLP_PARAM_ACTION_REVERSE:
1528                              if (goodModels[iModel]) {
1529                                   int iColumn;
1530                                   int numberColumns = models[iModel].numberColumns();
1531                                   double * dualColumnSolution =
1532                                        models[iModel].dualColumnSolution();
1533                                   ClpObjective * obj = models[iModel].objectiveAsObject();
1534                                   assert(dynamic_cast<ClpLinearObjective *> (obj));
1535                                   double offset;
1536                                   double * objective = obj->gradient(NULL, NULL, offset, true);
1537                                   for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1538                                        dualColumnSolution[iColumn] = -dualColumnSolution[iColumn];
1539                                        objective[iColumn] = -objective[iColumn];
1540                                   }
1541                                   int iRow;
1542                                   int numberRows = models[iModel].numberRows();
1543                                   double * dualRowSolution =
1544                                        models[iModel].dualRowSolution();
1545                                   for (iRow = 0; iRow < numberRows; iRow++) {
1546                                        dualRowSolution[iRow] = -dualRowSolution[iRow];
1547                                   }
1548                                   models[iModel].setObjectiveOffset(-models[iModel].objectiveOffset());
1549                              }
1550                              break;
1551                         case CLP_PARAM_ACTION_DIRECTORY: {
1552                              std::string name = CoinReadGetString(argc, argv);
1553                              if (name != "EOL") {
1554                                   size_t length = name.length();
1555                                   if (length > 0 && name[length-1] == dirsep) {
1556                                        directory = name;
1557                                   } else {
1558                                        directory = name + dirsep;
1559                                   }
1560                                   parameters[iParam].setStringValue(directory);
1561                              } else {
1562                                   parameters[iParam].printString();
1563                              }
1564                         }
1565                         break;
1566                         case CLP_PARAM_ACTION_DIRSAMPLE: {
1567                              std::string name = CoinReadGetString(argc, argv);
1568                              if (name != "EOL") {
1569                                   size_t length = name.length();
1570                                   if (length > 0 && name[length-1] == dirsep) {
1571                                        dirSample = name;
1572                                   } else {
1573                                        dirSample = name + dirsep;
1574                                   }
1575                                   parameters[iParam].setStringValue(dirSample);
1576                              } else {
1577                                   parameters[iParam].printString();
1578                              }
1579                         }
1580                         break;
1581                         case CLP_PARAM_ACTION_DIRNETLIB: {
1582                              std::string name = CoinReadGetString(argc, argv);
1583                              if (name != "EOL") {
1584                                   size_t length = name.length();
1585                                   if (length > 0 && name[length-1] == dirsep) {
1586                                        dirNetlib = name;
1587                                   } else {
1588                                        dirNetlib = name + dirsep;
1589                                   }
1590                                   parameters[iParam].setStringValue(dirNetlib);
1591                              } else {
1592                                   parameters[iParam].printString();
1593                              }
1594                         }
1595                         break;
1596                         case CBC_PARAM_ACTION_DIRMIPLIB: {
1597                              std::string name = CoinReadGetString(argc, argv);
1598                              if (name != "EOL") {
1599                                   size_t length = name.length();
1600                                   if (length > 0 && name[length-1] == dirsep) {
1601                                        dirMiplib = name;
1602                                   } else {
1603                                        dirMiplib = name + dirsep;
1604                                   }
1605                                   parameters[iParam].setStringValue(dirMiplib);
1606                              } else {
1607                                   parameters[iParam].printString();
1608                              }
1609                         }
1610                         break;
1611                         case CLP_PARAM_ACTION_STDIN:
1612                              CbcOrClpRead_mode = -1;
1613                              break;
1614                         case CLP_PARAM_ACTION_NETLIB_DUAL:
1615                         case CLP_PARAM_ACTION_NETLIB_EITHER:
1616                         case CLP_PARAM_ACTION_NETLIB_BARRIER:
1617                         case CLP_PARAM_ACTION_NETLIB_PRIMAL:
1618                         case CLP_PARAM_ACTION_NETLIB_TUNE: {
1619                              // create fields for unitTest
1620                              const char * fields[4];
1621                              int nFields = 4;
1622                              fields[0] = "fake main from unitTest";
1623                              std::string mpsfield = "-dirSample=";
1624                              mpsfield += dirSample.c_str();
1625                              fields[1] = mpsfield.c_str();
1626                              std::string netfield = "-dirNetlib=";
1627                              netfield += dirNetlib.c_str();
1628                              fields[2] = netfield.c_str();
1629                              fields[3] = "-netlib";
1630                              int algorithm;
1631                              if (type == CLP_PARAM_ACTION_NETLIB_DUAL) {
1632                                   std::cerr << "Doing netlib with dual algorithm" << std::endl;
1633                                   algorithm = 0;
1634                              } else if (type == CLP_PARAM_ACTION_NETLIB_BARRIER) {
1635                                   std::cerr << "Doing netlib with barrier algorithm" << std::endl;
1636                                   algorithm = 2;
1637                              } else if (type == CLP_PARAM_ACTION_NETLIB_EITHER) {
1638                                   std::cerr << "Doing netlib with dual or primal algorithm" << std::endl;
1639                                   algorithm = 3;
1640                              } else if (type == CLP_PARAM_ACTION_NETLIB_TUNE) {
1641                                   std::cerr << "Doing netlib with best algorithm!" << std::endl;
1642                                   algorithm = 5;
1643                                   // uncomment next to get active tuning
1644                                   // algorithm=6;
1645                              } else {
1646                                   std::cerr << "Doing netlib with primal agorithm" << std::endl;
1647                                   algorithm = 1;
1648                              }
1649                              int specialOptions = models[iModel].specialOptions();
1650                              models[iModel].setSpecialOptions(0);
1651                              ClpSolve solveOptions;
1652                              ClpSolve::PresolveType presolveType;
1653                              if (preSolve)
1654                                   presolveType = ClpSolve::presolveOn;
1655                              else
1656                                   presolveType = ClpSolve::presolveOff;
1657                              solveOptions.setPresolveType(presolveType, 5);
1658                              if (doSprint >= 0 || doIdiot >= 0) {
1659                                   if (doSprint > 0) {
1660                                        // sprint overrides idiot
1661                                        solveOptions.setSpecialOption(1, 3, doSprint); // sprint
1662                                   } else if (doIdiot > 0) {
1663                                        solveOptions.setSpecialOption(1, 2, doIdiot); // idiot
1664                                   } else {
1665                                        if (doIdiot == 0) {
1666                                             if (doSprint == 0)
1667                                                  solveOptions.setSpecialOption(1, 4); // all slack
1668                                             else
1669                                                  solveOptions.setSpecialOption(1, 9); // all slack or sprint
1670                                        } else {
1671                                             if (doSprint == 0)
1672                                                  solveOptions.setSpecialOption(1, 8); // all slack or idiot
1673                                             else
1674                                                  solveOptions.setSpecialOption(1, 7); // initiative
1675                                        }
1676                                   }
1677                              }
1678                              mainTest(nFields, fields, algorithm, models[iModel],
1679                                       solveOptions, specialOptions, doVector != 0);
1680                         }
1681                         break;
1682                         case CLP_PARAM_ACTION_UNITTEST: {
1683                              // create fields for unitTest
1684                              const char * fields[2];
1685                              int nFields = 2;
1686                              fields[0] = "fake main from unitTest";
1687                              std::string dirfield = "-dirSample=";
1688                              dirfield += dirSample.c_str();
1689                              fields[1] = dirfield.c_str();
1690                              int specialOptions = models[iModel].specialOptions();
1691                              models[iModel].setSpecialOptions(0);
1692                              int algorithm = -1;
1693                              if (models[iModel].numberRows())
1694                                   algorithm = 7;
1695                              ClpSolve solveOptions;
1696                              ClpSolve::PresolveType presolveType;
1697                              if (preSolve)
1698                                   presolveType = ClpSolve::presolveOn;
1699                              else
1700                                   presolveType = ClpSolve::presolveOff;
1701                              solveOptions.setPresolveType(presolveType, 5);
1702                              mainTest(nFields, fields, algorithm, models[iModel],
1703                                       solveOptions, specialOptions, doVector != 0);
1704                         }
1705                         break;
1706                         case CLP_PARAM_ACTION_FAKEBOUND:
1707                              if (goodModels[iModel]) {
1708                                   // get bound
1709                                   double value = CoinReadGetDoubleField(argc, argv, &valid);
1710                                   if (!valid) {
1711                                        std::cout << "Setting " << parameters[iParam].name() <<
1712                                                  " to DEBUG " << value << std::endl;
1713                                        int iRow;
1714                                        int numberRows = models[iModel].numberRows();
1715                                        double * rowLower = models[iModel].rowLower();
1716                                        double * rowUpper = models[iModel].rowUpper();
1717                                        for (iRow = 0; iRow < numberRows; iRow++) {
1718                                             // leave free ones for now
1719                                             if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) {
1720                                                  rowLower[iRow] = CoinMax(rowLower[iRow], -value);
1721                                                  rowUpper[iRow] = CoinMin(rowUpper[iRow], value);
1722                                             }
1723                                        }
1724                                        int iColumn;
1725                                        int numberColumns = models[iModel].numberColumns();
1726                                        double * columnLower = models[iModel].columnLower();
1727                                        double * columnUpper = models[iModel].columnUpper();
1728                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1729                                             // leave free ones for now
1730                                             if (columnLower[iColumn] > -1.0e20 ||
1731                                                       columnUpper[iColumn] < 1.0e20) {
1732                                                  columnLower[iColumn] = CoinMax(columnLower[iColumn], -value);
1733                                                  columnUpper[iColumn] = CoinMin(columnUpper[iColumn], value);
1734                                             }
1735                                        }
1736                                   } else if (valid == 1) {
1737                                        abort();
1738                                   } else {
1739                                        std::cout << "enter value for " << parameters[iParam].name() <<
1740                                                  std::endl;
1741                                   }
1742                              }
1743                              break;
1744                         case CLP_PARAM_ACTION_REALLY_SCALE:
1745                              if (goodModels[iModel]) {
1746                                   ClpSimplex newModel(models[iModel],
1747                                                       models[iModel].scalingFlag());
1748                                   printf("model really really scaled\n");
1749                                   models[iModel] = newModel;
1750                              }
1751                              break;
1752                         case CLP_PARAM_ACTION_USERCLP:
1753                              // Replace the sample code by whatever you want
1754                              if (goodModels[iModel]) {
1755                                   ClpSimplex * thisModel = &models[iModel];
1756                                   printf("Dummy user code - model has %d rows and %d columns\n",
1757                                          thisModel->numberRows(), thisModel->numberColumns());
1758                              }
1759                              break;
1760                         case CLP_PARAM_ACTION_HELP:
1761                              std::cout << "Coin LP version " << CLP_VERSION
1762                                        << ", build " << __DATE__ << std::endl;
1763                              std::cout << "Non default values:-" << std::endl;
1764                              std::cout << "Perturbation " << models[0].perturbation() << " (default 100)"
1765                                        << std::endl;
1766                              CoinReadPrintit(
1767                                   "Presolve being done with 5 passes\n\
1768Dual steepest edge steep/partial on matrix shape and factorization density\n\
1769Clpnnnn taken out of messages\n\
1770If Factorization frequency default then done on size of matrix\n\n\
1771(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
1772You can switch to interactive mode at any time so\n\
1773clp watson.mps -scaling off -primalsimplex\nis the same as\n\
1774clp watson.mps -\nscaling off\nprimalsimplex"
1775                              );
1776                              break;
1777                         case CLP_PARAM_ACTION_SOLUTION:
1778                         case CLP_PARAM_ACTION_GMPL_SOLUTION:
1779                              if (goodModels[iModel]) {
1780                                   // get next field
1781                                   field = CoinReadGetString(argc, argv);
1782                                   bool append = false;
1783                                   if (field == "append$") {
1784                                     field = "$";
1785                                     append = true;
1786                                   }
1787                                   if (field == "$") {
1788                                        field = parameters[iParam].stringValue();
1789                                   } else if (field == "EOL") {
1790                                        parameters[iParam].printString();
1791                                        break;
1792                                   } else {
1793                                        parameters[iParam].setStringValue(field);
1794                                   }
1795                                   std::string fileName;
1796                                   FILE *fp = NULL;
1797                                   if (field == "-" || field == "EOL" || field == "stdout") {
1798                                        // stdout
1799                                        fp = stdout;
1800                                        fprintf(fp, "\n");
1801                                   } else if (field == "stderr") {
1802                                        // stderr
1803                                        fp = stderr;
1804                                        fprintf(fp, "\n");
1805                                   } else {
1806                                        if (field[0] == '/' || field[0] == '\\') {
1807                                             fileName = field;
1808                                        } else if (field[0] == '~') {
1809                                             char * environVar = getenv("HOME");
1810                                             if (environVar) {
1811                                                  std::string home(environVar);
1812                                                  field = field.erase(0, 1);
1813                                                  fileName = home + field;
1814                                             } else {
1815                                                  fileName = field;
1816                                             }
1817                                        } else {
1818                                             fileName = directory + field;
1819                                        }
1820                                        if (!append)
1821                                          fp = fopen(fileName.c_str(), "w");
1822                                        else
1823                                          fp = fopen(fileName.c_str(), "a");
1824                                   }
1825                                   if (fp) {
1826                                     // See if Glpk
1827                                     if (type == CLP_PARAM_ACTION_GMPL_SOLUTION) {
1828                                       int numberRows = models[iModel].getNumRows();
1829                                       int numberColumns = models[iModel].getNumCols();
1830                                       int numberGlpkRows=numberRows+1;
1831#ifdef COIN_HAS_GLPK
1832                                       if (cbc_glp_prob) {
1833                                         // from gmpl
1834                                         numberGlpkRows=glp_get_num_rows(cbc_glp_prob);
1835                                         if (numberGlpkRows!=numberRows)
1836                                           printf("Mismatch - cbc %d rows, glpk %d\n",
1837                                                  numberRows,numberGlpkRows);
1838                                       }
1839#endif
1840                                       fprintf(fp,"%d %d\n",numberGlpkRows,
1841                                               numberColumns);
1842                                       int iStat = models[iModel].status();
1843                                       int iStat2 = GLP_UNDEF;
1844                                       if (iStat == 0) {
1845                                         // optimal
1846                                         iStat2 = GLP_FEAS;
1847                                       } else if (iStat == 1) {
1848                                         // infeasible
1849                                         iStat2 = GLP_NOFEAS;
1850                                       } else if (iStat == 2) {
1851                                         // unbounded
1852                                         // leave as 1
1853                                       } else if (iStat >= 3 && iStat <= 5) {
1854                                         iStat2 = GLP_FEAS;
1855                                       }
1856                                       double objValue = models[iModel].getObjValue() 
1857                                         * models[iModel].getObjSense();
1858                                       fprintf(fp,"%d 2 %g\n",iStat2,objValue);
1859                                       if (numberGlpkRows > numberRows) {
1860                                         // objective as row
1861                                         fprintf(fp,"4 %g 1.0\n",objValue);
1862                                       }
1863                                       int lookup[6]=
1864                                         {4,1,3,2,4,5};
1865                                       const double * primalRowSolution =
1866                                         models[iModel].primalRowSolution();
1867                                       const double * dualRowSolution =
1868                                         models[iModel].dualRowSolution();
1869                                       for (int i=0;i<numberRows;i++) {
1870                                         fprintf(fp,"%d %g %g\n",lookup[models[iModel].getRowStatus(i)],
1871                                                 primalRowSolution[i],dualRowSolution[i]);
1872                                       }
1873                                       const double * primalColumnSolution =
1874                                         models[iModel].primalColumnSolution();
1875                                       const double * dualColumnSolution =
1876                                         models[iModel].dualColumnSolution();
1877                                       for (int i=0;i<numberColumns;i++) {
1878                                         fprintf(fp,"%d %g %g\n",lookup[models[iModel].getColumnStatus(i)],
1879                                                 primalColumnSolution[i],dualColumnSolution[i]);
1880                                       }
1881                                       fclose(fp);
1882#ifdef COIN_HAS_GLPK
1883                                       if (cbc_glp_prob) {
1884                                         glp_read_sol(cbc_glp_prob,fileName.c_str());
1885                                         glp_mpl_postsolve(cbc_glp_tran,
1886                                                           cbc_glp_prob,
1887                                                           GLP_SOL);
1888                                         // free up as much as possible
1889                                         glp_free(cbc_glp_prob);
1890                                         glp_mpl_free_wksp(cbc_glp_tran);
1891                                         cbc_glp_prob = NULL;
1892                                         cbc_glp_tran = NULL;
1893                                         //gmp_free_mem();
1894                                         /* check that no memory blocks are still allocated */
1895                                         glp_free_env();
1896                                       }
1897#endif
1898                                       break;
1899                                     }
1900                                        // Write solution header (suggested by Luigi Poderico)
1901                                        double objValue = models[iModel].getObjValue() * models[iModel].getObjSense();
1902                                        int iStat = models[iModel].status();
1903                                        if (iStat == 0) {
1904                                             fprintf(fp, "optimal\n" );
1905                                        } else if (iStat == 1) {
1906                                             // infeasible
1907                                             fprintf(fp, "infeasible\n" );
1908                                        } else if (iStat == 2) {
1909                                             // unbounded
1910                                             fprintf(fp, "unbounded\n" );
1911                                        } else if (iStat == 3) {
1912                                             fprintf(fp, "stopped on iterations or time\n" );
1913                                        } else if (iStat == 4) {
1914                                             fprintf(fp, "stopped on difficulties\n" );
1915                                        } else if (iStat == 5) {
1916                                             fprintf(fp, "stopped on ctrl-c\n" );
1917                                        } else {
1918                                             fprintf(fp, "status unknown\n" );
1919                                        }
1920                                        fprintf(fp, "Objective value %15.8g\n", objValue);
1921                                        // make fancy later on
1922                                        int iRow;
1923                                        int numberRows = models[iModel].numberRows();
1924                                        int lengthName = models[iModel].lengthNames(); // 0 if no names
1925                                        int lengthPrint = CoinMax(lengthName, 8);
1926                                        // in general I don't want to pass around massive
1927                                        // amounts of data but seems simpler here
1928                                        std::vector<std::string> rowNames =
1929                                             *(models[iModel].rowNames());
1930                                        std::vector<std::string> columnNames =
1931                                             *(models[iModel].columnNames());
1932
1933                                        double * dualRowSolution = models[iModel].dualRowSolution();
1934                                        double * primalRowSolution =
1935                                             models[iModel].primalRowSolution();
1936                                        double * rowLower = models[iModel].rowLower();
1937                                        double * rowUpper = models[iModel].rowUpper();
1938                                        double primalTolerance = models[iModel].primalTolerance();
1939                                        bool doMask = (printMask != "" && lengthName);
1940                                        int * maskStarts = NULL;
1941                                        int maxMasks = 0;
1942                                        char ** masks = NULL;
1943                                        if (doMask) {
1944                                             int nAst = 0;
1945                                             const char * pMask2 = printMask.c_str();
1946                                             char pMask[100];
1947                                             size_t lengthMask = strlen(pMask2);
1948                                             assert (lengthMask < 100);
1949                                             if (*pMask2 == '"') {
1950                                                  if (pMask2[lengthMask-1] != '"') {
1951                                                       printf("mismatched \" in mask %s\n", pMask2);
1952                                                       break;
1953                                                  } else {
1954                                                       strcpy(pMask, pMask2 + 1);
1955                                                       *strchr(pMask, '"') = '\0';
1956                                                  }
1957                                             } else if (*pMask2 == '\'') {
1958                                                  if (pMask2[lengthMask-1] != '\'') {
1959                                                       printf("mismatched ' in mask %s\n", pMask2);
1960                                                       break;
1961                                                  } else {
1962                                                       strcpy(pMask, pMask2 + 1);
1963                                                       *strchr(pMask, '\'') = '\0';
1964                                                  }
1965                                             } else {
1966                                                  strcpy(pMask, pMask2);
1967                                             }
1968                                             if (lengthMask > static_cast<size_t>(lengthName)) {
1969                                                  printf("mask %s too long - skipping\n", pMask);
1970                                                  break;
1971                                             }
1972                                             maxMasks = 1;
1973                                             for (size_t iChar = 0; iChar < lengthMask; iChar++) {
1974                                                  if (pMask[iChar] == '*') {
1975                                                       nAst++;
1976                                                       maxMasks *= (lengthName + 1);
1977                                                  }
1978                                             }
1979                                             int nEntries = 1;
1980                                             maskStarts = new int[lengthName+2];
1981                                             masks = new char * [maxMasks];
1982                                             char ** newMasks = new char * [maxMasks];
1983                                             int i;
1984                                             for (i = 0; i < maxMasks; i++) {
1985                                                  masks[i] = new char[lengthName+1];
1986                                                  newMasks[i] = new char[lengthName+1];
1987                                             }
1988                                             strcpy(masks[0], pMask);
1989                                             for (int iAst = 0; iAst < nAst; iAst++) {
1990                                                  int nOldEntries = nEntries;
1991                                                  nEntries = 0;
1992                                                  for (int iEntry = 0; iEntry < nOldEntries; iEntry++) {
1993                                                       char * oldMask = masks[iEntry];
1994                                                       char * ast = strchr(oldMask, '*');
1995                                                       assert (ast);
1996                                                       size_t length = strlen(oldMask) - 1;
1997                                                       size_t nBefore = ast - oldMask;
1998                                                       size_t nAfter = length - nBefore;
1999                                                       // and add null
2000                                                       nAfter++;
2001                                                       for (size_t i = 0; i <= lengthName - length; i++) {
2002                                                            char * maskOut = newMasks[nEntries];
2003                                                            CoinMemcpyN(oldMask, static_cast<int>(nBefore), maskOut);
2004                                                            for (size_t k = 0; k < i; k++)
2005                                                                 maskOut[k+nBefore] = '?';
2006                                                            CoinMemcpyN(ast + 1, static_cast<int>(nAfter), maskOut + nBefore + i);
2007                                                            nEntries++;
2008                                                            assert (nEntries <= maxMasks);
2009                                                       }
2010                                                  }
2011                                                  char ** temp = masks;
2012                                                  masks = newMasks;
2013                                                  newMasks = temp;
2014                                             }
2015                                             // Now extend and sort
2016                                             int * sort = new int[nEntries];
2017                                             for (i = 0; i < nEntries; i++) {
2018                                                  char * maskThis = masks[i];
2019                                                  size_t length = strlen(maskThis);
2020                                                  while (length > 0 && maskThis[length-1] == ' ')
2021                                                       length--;
2022                                                  maskThis[length] = '\0';
2023                                                  sort[i] = static_cast<int>(length);
2024                                             }
2025                                             CoinSort_2(sort, sort + nEntries, masks);
2026                                             int lastLength = -1;
2027                                             for (i = 0; i < nEntries; i++) {
2028                                                  int length = sort[i];
2029                                                  while (length > lastLength)
2030                                                       maskStarts[++lastLength] = i;
2031                                             }
2032                                             maskStarts[++lastLength] = nEntries;
2033                                             delete [] sort;
2034                                             for (i = 0; i < maxMasks; i++)
2035                                                  delete [] newMasks[i];
2036                                             delete [] newMasks;
2037                                        }
2038                                        if (printMode > 5) {
2039                                          int numberColumns = models[iModel].numberColumns();
2040                                          // column length unless rhs ranging
2041                                          int number = numberColumns;
2042                                          switch (printMode) {
2043                                            // bound ranging
2044                                            case 6:
2045                                              fprintf(fp,"Bound ranging");
2046                                              break;
2047                                            // rhs ranging
2048                                            case 7:
2049                                              fprintf(fp,"Rhs ranging");
2050                                              number = numberRows;
2051                                              break;
2052                                            // objective ranging
2053                                            case 8:
2054                                              fprintf(fp,"Objective ranging");
2055                                              break;
2056                                          }
2057                                          if (lengthName)
2058                                            fprintf(fp,",name");
2059                                          fprintf(fp,",increase,variable,decrease,variable\n");
2060                                          int * which = new int [ number];
2061                                          if (printMode != 7) {
2062                                            if (!doMask) {
2063                                              for (int i = 0; i < number;i ++)
2064                                                which[i]=i;
2065                                            } else {
2066                                              int n = 0;
2067                                              for (int i = 0; i < number;i ++) {
2068                                                if (maskMatches(maskStarts,masks,columnNames[i]))
2069                                                  which[n++]=i;
2070                                              }
2071                                              if (n) {
2072                                                number=n;
2073                                              } else {
2074                                                printf("No names match - doing all\n");
2075                                                for (int i = 0; i < number;i ++)
2076                                                  which[i]=i;
2077                                              }
2078                                            }
2079                                          } else {
2080                                            if (!doMask) {
2081                                              for (int i = 0; i < number;i ++)
2082                                                which[i]=i+numberColumns;
2083                                            } else {
2084                                              int n = 0;
2085                                              for (int i = 0; i < number;i ++) {
2086                                                if (maskMatches(maskStarts,masks,rowNames[i]))
2087                                                  which[n++]=i+numberColumns;
2088                                              }
2089                                              if (n) {
2090                                                number=n;
2091                                              } else {
2092                                                printf("No names match - doing all\n");
2093                                                for (int i = 0; i < number;i ++)
2094                                                  which[i]=i+numberColumns;
2095                                              }
2096                                            }
2097                                          }
2098                                          double * valueIncrease = new double [ number];
2099                                          int * sequenceIncrease = new int [ number];
2100                                          double * valueDecrease = new double [ number];
2101                                          int * sequenceDecrease = new int [ number];
2102                                          switch (printMode) {
2103                                            // bound or rhs ranging
2104                                            case 6:
2105                                            case 7:
2106                                              models[iModel].primalRanging(numberRows,
2107                                                                           which, valueIncrease, sequenceIncrease,
2108                                                                           valueDecrease, sequenceDecrease);
2109                                              break;
2110                                            // objective ranging
2111                                            case 8:
2112                                              models[iModel].dualRanging(number,
2113                                                                           which, valueIncrease, sequenceIncrease,
2114                                                                           valueDecrease, sequenceDecrease);
2115                                              break;
2116                                          }
2117                                          for (int i = 0; i < number; i++) {
2118                                            int iWhich = which[i];
2119                                            fprintf(fp, "%d,", (iWhich<numberColumns) ? iWhich : iWhich-numberColumns);
2120                                            if (lengthName) {
2121                                              const char * name = (printMode==7) ? rowNames[iWhich-numberColumns].c_str() : columnNames[iWhich].c_str();
2122                                              fprintf(fp,"%s,",name);
2123                                            }
2124                                            if (valueIncrease[i]<1.0e30) {
2125                                              fprintf(fp, "%.10g,", valueIncrease[i]);
2126                                              int outSequence = sequenceIncrease[i];
2127                                              if (outSequence<numberColumns) {
2128                                                if (lengthName)
2129                                                  fprintf(fp,"%s,",columnNames[outSequence].c_str());
2130                                                else
2131                                                  fprintf(fp,"C%7.7d,",outSequence);
2132                                              } else {
2133                                                outSequence -= numberColumns;
2134                                                if (lengthName)
2135                                                  fprintf(fp,"%s,",rowNames[outSequence].c_str());
2136                                                else
2137                                                  fprintf(fp,"R%7.7d,",outSequence);
2138                                              }
2139                                            } else {
2140                                              fprintf(fp,"1.0e100,,");
2141                                            }
2142                                            if (valueDecrease[i]<1.0e30) {
2143                                              fprintf(fp, "%.10g,", valueDecrease[i]);
2144                                              int outSequence = sequenceDecrease[i];
2145                                              if (outSequence<numberColumns) {
2146                                                if (lengthName)
2147                                                  fprintf(fp,"%s",columnNames[outSequence].c_str());
2148                                                else
2149                                                  fprintf(fp,"C%7.7d",outSequence);
2150                                              } else {
2151                                                outSequence -= numberColumns;
2152                                                if (lengthName)
2153                                                  fprintf(fp,"%s",rowNames[outSequence].c_str());
2154                                                else
2155                                                  fprintf(fp,"R%7.7d",outSequence);
2156                                              }
2157                                            } else {
2158                                              fprintf(fp,"1.0e100,");
2159                                            }
2160                                            fprintf(fp,"\n");
2161                                          }
2162                                          if (fp != stdout)
2163                                            fclose(fp);
2164                                          delete [] which;
2165                                          delete [] valueIncrease;
2166                                          delete [] sequenceIncrease;
2167                                          delete [] valueDecrease;
2168                                          delete [] sequenceDecrease;
2169                                          if (masks) {
2170                                            delete [] maskStarts;
2171                                            for (int i = 0; i < maxMasks; i++)
2172                                              delete [] masks[i];
2173                                            delete [] masks;
2174                                          }
2175                                          break;
2176                                        }
2177                                        if (printMode > 2) {
2178                                             for (iRow = 0; iRow < numberRows; iRow++) {
2179                                                  int type = printMode - 3;
2180                                                  if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance ||
2181                                                            primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) {
2182                                                       fprintf(fp, "** ");
2183                                                       type = 2;
2184                                                  } else if (fabs(primalRowSolution[iRow]) > 1.0e-8) {
2185                                                       type = 1;
2186                                                  } else if (numberRows < 50) {
2187                                                       type = 3;
2188                                                  }
2189                                                  if (doMask && !maskMatches(maskStarts, masks, rowNames[iRow]))
2190                                                       type = 0;
2191                                                  if (type) {
2192                                                       fprintf(fp, "%7d ", iRow);
2193                                                       if (lengthName) {
2194                                                            const char * name = rowNames[iRow].c_str();
2195                                                            size_t n = strlen(name);
2196                                                            size_t i;
2197                                                            for (i = 0; i < n; i++)
2198                                                                 fprintf(fp, "%c", name[i]);
2199                                                            for (; i < static_cast<size_t>(lengthPrint); i++)
2200                                                                 fprintf(fp, " ");
2201                                                       }
2202                                                       fprintf(fp, " %15.8g        %15.8g\n", primalRowSolution[iRow],
2203                                                               dualRowSolution[iRow]);
2204                                                  }
2205                                             }
2206                                        }
2207                                        int iColumn;
2208                                        int numberColumns = models[iModel].numberColumns();
2209                                        double * dualColumnSolution =
2210                                             models[iModel].dualColumnSolution();
2211                                        double * primalColumnSolution =
2212                                             models[iModel].primalColumnSolution();
2213                                        double * columnLower = models[iModel].columnLower();
2214                                        double * columnUpper = models[iModel].columnUpper();
2215                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2216                                             int type = (printMode > 3) ? 1 : 0;
2217                                             if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance ||
2218                                                       primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) {
2219                                                  fprintf(fp, "** ");
2220                                                  type = 2;
2221                                             } else if (fabs(primalColumnSolution[iColumn]) > 1.0e-8) {
2222                                                  type = 1;
2223                                             } else if (numberColumns < 50) {
2224                                                  type = 3;
2225                                             }
2226                                             if (doMask && !maskMatches(maskStarts, masks,
2227                                                                        columnNames[iColumn]))
2228                                                  type = 0;
2229                                             if (type) {
2230                                                  fprintf(fp, "%7d ", iColumn);
2231                                                  if (lengthName) {
2232                                                       const char * name = columnNames[iColumn].c_str();
2233                                                       size_t n = strlen(name);
2234                                                       size_t i;
2235                                                       for (i = 0; i < n; i++)
2236                                                            fprintf(fp, "%c", name[i]);
2237                                                       for (; i < static_cast<size_t>(lengthPrint); i++)
2238                                                            fprintf(fp, " ");
2239                                                  }
2240                                                  fprintf(fp, " %15.8g        %15.8g\n",
2241                                                          primalColumnSolution[iColumn],
2242                                                          dualColumnSolution[iColumn]);
2243                                             }
2244                                        }
2245                                        if (fp != stdout)
2246                                             fclose(fp);
2247                                        if (masks) {
2248                                             delete [] maskStarts;
2249                                             for (int i = 0; i < maxMasks; i++)
2250                                                  delete [] masks[i];
2251                                             delete [] masks;
2252                                        }
2253                                   } else {
2254                                        std::cout << "Unable to open file " << fileName << std::endl;
2255                                   }
2256                              } else {
2257                                   std::cout << "** Current model not valid" << std::endl;
2258
2259                              }
2260
2261                              break;
2262                         case CLP_PARAM_ACTION_SAVESOL:
2263                              if (goodModels[iModel]) {
2264                                   // get next field
2265                                   field = CoinReadGetString(argc, argv);
2266                                   if (field == "$") {
2267                                        field = parameters[iParam].stringValue();
2268                                   } else if (field == "EOL") {
2269                                        parameters[iParam].printString();
2270                                        break;
2271                                   } else {
2272                                        parameters[iParam].setStringValue(field);
2273                                   }
2274                                   std::string fileName;
2275                                   if (field[0] == '/' || field[0] == '\\') {
2276                                        fileName = field;
2277                                   } else if (field[0] == '~') {
2278                                        char * environVar = getenv("HOME");
2279                                        if (environVar) {
2280                                             std::string home(environVar);
2281                                             field = field.erase(0, 1);
2282                                             fileName = home + field;
2283                                        } else {
2284                                             fileName = field;
2285                                        }
2286                                   } else {
2287                                        fileName = directory + field;
2288                                   }
2289                                   saveSolution(models + iModel, fileName);
2290                              } else {
2291                                   std::cout << "** Current model not valid" << std::endl;
2292
2293                              }
2294                              break;
2295                         case CLP_PARAM_ACTION_ENVIRONMENT:
2296                              CbcOrClpEnvironmentIndex = 0;
2297                              break;
2298                         default:
2299                              abort();
2300                         }
2301                    }
2302               } else if (!numberMatches) {
2303                    std::cout << "No match for " << field << " - ? for list of commands"
2304                              << std::endl;
2305               } else if (numberMatches == 1) {
2306                    if (!numberQuery) {
2307                         std::cout << "Short match for " << field << " - completion: ";
2308                         std::cout << parameters[firstMatch].matchName() << std::endl;
2309                    } else if (numberQuery) {
2310                         std::cout << parameters[firstMatch].matchName() << " : ";
2311                         std::cout << parameters[firstMatch].shortHelp() << std::endl;
2312                         if (numberQuery >= 2)
2313                              parameters[firstMatch].printLongHelp();
2314                    }
2315               } else {
2316                    if (!numberQuery)
2317                         std::cout << "Multiple matches for " << field << " - possible completions:"
2318                                   << std::endl;
2319                    else
2320                         std::cout << "Completions of " << field << ":" << std::endl;
2321                    for ( iParam = 0; iParam < numberParameters; iParam++ ) {
2322                         int match = parameters[iParam].matches(field);
2323                         if (match && parameters[iParam].displayThis()) {
2324                              std::cout << parameters[iParam].matchName();
2325                              if (numberQuery >= 2)
2326                                   std::cout << " : " << parameters[iParam].shortHelp();
2327                              std::cout << std::endl;
2328                         }
2329                    }
2330               }
2331          }
2332          delete [] models;
2333          delete [] goodModels;
2334     }
2335#ifdef COIN_HAS_GLPK
2336     if (cbc_glp_prob) {
2337       // free up as much as possible
2338       glp_free(cbc_glp_prob);
2339       glp_mpl_free_wksp(cbc_glp_tran);
2340       glp_free_env(); 
2341       cbc_glp_prob = NULL;
2342       cbc_glp_tran = NULL;
2343     }
2344#endif
2345     // By now all memory should be freed
2346#ifdef DMALLOC
2347     dmalloc_log_unfreed();
2348     dmalloc_shutdown();
2349#endif
2350     return 0;
2351}
2352static void breakdown(const char * name, int numberLook, const double * region)
2353{
2354     double range[] = {
2355          -COIN_DBL_MAX,
2356          -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, -1.0e2, -1.0e1,
2357          -1.0,
2358          -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15,
2359          0.0,
2360          1.0e-15, 1.0e-11, 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1,
2361          1.0,
2362          1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, 1.0e15,
2363          COIN_DBL_MAX
2364     };
2365     int nRanges = static_cast<int> (sizeof(range) / sizeof(double));
2366     int * number = new int[nRanges];
2367     memset(number, 0, nRanges * sizeof(int));
2368     int * numberExact = new int[nRanges];
2369     memset(numberExact, 0, nRanges * sizeof(int));
2370     int i;
2371     for ( i = 0; i < numberLook; i++) {
2372          double value = region[i];
2373          for (int j = 0; j < nRanges; j++) {
2374               if (value == range[j]) {
2375                    numberExact[j]++;
2376                    break;
2377               } else if (value < range[j]) {
2378                    number[j]++;
2379                    break;
2380               }
2381          }
2382     }
2383     printf("\n%s has %d entries\n", name, numberLook);
2384     for (i = 0; i < nRanges; i++) {
2385          if (number[i])
2386               printf("%d between %g and %g", number[i], range[i-1], range[i]);
2387          if (numberExact[i]) {
2388               if (number[i])
2389                    printf(", ");
2390               printf("%d exactly at %g", numberExact[i], range[i]);
2391          }
2392          if (number[i] + numberExact[i])
2393               printf("\n");
2394     }
2395     delete [] number;
2396     delete [] numberExact;
2397}
2398void sortOnOther(int * column,
2399                 const CoinBigIndex * rowStart,
2400                 int * order,
2401                 int * other,
2402                 int nRow,
2403                 int nInRow,
2404                 int where)
2405{
2406     if (nRow < 2 || where >= nInRow)
2407          return;
2408     // do initial sort
2409     int kRow;
2410     int iRow;
2411     for ( kRow = 0; kRow < nRow; kRow++) {
2412          iRow = order[kRow];
2413          other[kRow] = column[rowStart[iRow] + where];
2414     }
2415     CoinSort_2(other, other + nRow, order);
2416     int first = 0;
2417     iRow = order[0];
2418     int firstC = column[rowStart[iRow] + where];
2419     kRow = 1;
2420     while (kRow < nRow) {
2421          int lastC = 9999999;;
2422          for (; kRow < nRow + 1; kRow++) {
2423               if (kRow < nRow) {
2424                    iRow = order[kRow];
2425                    lastC = column[rowStart[iRow] + where];
2426               } else {
2427                    lastC = 9999999;
2428               }
2429               if (lastC > firstC)
2430                    break;
2431          }
2432          // sort
2433          sortOnOther(column, rowStart, order + first, other, kRow - first,
2434                      nInRow, where + 1);
2435          firstC = lastC;
2436          first = kRow;
2437     }
2438}
2439static void statistics(ClpSimplex * originalModel, ClpSimplex * model)
2440{
2441     int numberColumns = originalModel->numberColumns();
2442     const char * integerInformation  = originalModel->integerInformation();
2443     const double * columnLower = originalModel->columnLower();
2444     const double * columnUpper = originalModel->columnUpper();
2445     int numberIntegers = 0;
2446     int numberBinary = 0;
2447     int iRow, iColumn;
2448     if (integerInformation) {
2449          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2450               if (integerInformation[iColumn]) {
2451                    if (columnUpper[iColumn] > columnLower[iColumn]) {
2452                         numberIntegers++;
2453                         if (columnUpper[iColumn] == 0.0 && columnLower[iColumn] == 1)
2454                              numberBinary++;
2455                    }
2456               }
2457          }
2458     }
2459     numberColumns = model->numberColumns();
2460     int numberRows = model->numberRows();
2461     columnLower = model->columnLower();
2462     columnUpper = model->columnUpper();
2463     const double * rowLower = model->rowLower();
2464     const double * rowUpper = model->rowUpper();
2465     const double * objective = model->objective();
2466     CoinPackedMatrix * matrix = model->matrix();
2467     CoinBigIndex numberElements = matrix->getNumElements();
2468     const int * columnLength = matrix->getVectorLengths();
2469     //const CoinBigIndex * columnStart = matrix->getVectorStarts();
2470     const double * elementByColumn = matrix->getElements();
2471     int * number = new int[numberRows+1];
2472     memset(number, 0, (numberRows + 1)*sizeof(int));
2473     int numberObjSingletons = 0;
2474     /* cType
2475        0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up,
2476        8 0/1
2477     */
2478     int cType[9];
2479     std::string cName[] = {"0.0->inf,", "0.0->up,", "lo->inf,", "lo->up,", "free,", "fixed,", "-inf->0.0,",
2480                            "-inf->up,", "0.0->1.0"
2481                           };
2482     int nObjective = 0;
2483     memset(cType, 0, sizeof(cType));
2484     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2485          int length = columnLength[iColumn];
2486          if (length == 1 && objective[iColumn])
2487               numberObjSingletons++;
2488          number[length]++;
2489          if (objective[iColumn])
2490               nObjective++;
2491          if (columnLower[iColumn] > -1.0e20) {
2492               if (columnLower[iColumn] == 0.0) {
2493                    if (columnUpper[iColumn] > 1.0e20)
2494                         cType[0]++;
2495                    else if (columnUpper[iColumn] == 1.0)
2496                         cType[8]++;
2497                    else if (columnUpper[iColumn] == 0.0)
2498                         cType[5]++;
2499                    else
2500                         cType[1]++;
2501               } else {
2502                    if (columnUpper[iColumn] > 1.0e20)
2503                         cType[2]++;
2504                    else if (columnUpper[iColumn] == columnLower[iColumn])
2505                         cType[5]++;
2506                    else
2507                         cType[3]++;
2508               }
2509          } else {
2510               if (columnUpper[iColumn] > 1.0e20)
2511                    cType[4]++;
2512               else if (columnUpper[iColumn] == 0.0)
2513                    cType[6]++;
2514               else
2515                    cType[7]++;
2516          }
2517     }
2518     /* rType
2519        0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other,
2520        7 L 0,  8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free
2521     */
2522     int rType[13];
2523     std::string rName[] = {"E 0.0,", "E 1.0,", "E -1.0,", "E other,", "G 0.0,", "G 1.0,", "G other,",
2524                            "L 0.0,", "L 1.0,", "L other,", "Range 0.0->1.0,", "Range other,", "Free"
2525                           };
2526     memset(rType, 0, sizeof(rType));
2527     for (iRow = 0; iRow < numberRows; iRow++) {
2528          if (rowLower[iRow] > -1.0e20) {
2529               if (rowLower[iRow] == 0.0) {
2530                    if (rowUpper[iRow] > 1.0e20)
2531                         rType[4]++;
2532                    else if (rowUpper[iRow] == 1.0)
2533                         rType[10]++;
2534                    else if (rowUpper[iRow] == 0.0)
2535                         rType[0]++;
2536                    else
2537                         rType[11]++;
2538               } else if (rowLower[iRow] == 1.0) {
2539                    if (rowUpper[iRow] > 1.0e20)
2540                         rType[5]++;
2541                    else if (rowUpper[iRow] == rowLower[iRow])
2542                         rType[1]++;
2543                    else
2544                         rType[11]++;
2545               } else if (rowLower[iRow] == -1.0) {
2546                    if (rowUpper[iRow] > 1.0e20)
2547                         rType[6]++;
2548                    else if (rowUpper[iRow] == rowLower[iRow])
2549                         rType[2]++;
2550                    else
2551                         rType[11]++;
2552               } else {
2553                    if (rowUpper[iRow] > 1.0e20)
2554                         rType[6]++;
2555                    else if (rowUpper[iRow] == rowLower[iRow])
2556                         rType[3]++;
2557                    else
2558                         rType[11]++;
2559               }
2560          } else {
2561               if (rowUpper[iRow] > 1.0e20)
2562                    rType[12]++;
2563               else if (rowUpper[iRow] == 0.0)
2564                    rType[7]++;
2565               else if (rowUpper[iRow] == 1.0)
2566                    rType[8]++;
2567               else
2568                    rType[9]++;
2569          }
2570     }
2571     // Basic statistics
2572     printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n",
2573            numberRows, numberColumns, nObjective, numberElements);
2574     if (number[0] + number[1]) {
2575          printf("There are ");
2576          if (numberObjSingletons)
2577               printf("%d singletons with objective ", numberObjSingletons);
2578          int numberNoObj = number[1] - numberObjSingletons;
2579          if (numberNoObj)
2580               printf("%d singletons with no objective ", numberNoObj);
2581          if (number[0])
2582               printf("** %d columns have no entries", number[0]);
2583          printf("\n");
2584     }
2585     printf("Column breakdown:\n");
2586     int k;
2587     for (k = 0; k < static_cast<int> (sizeof(cType) / sizeof(int)); k++) {
2588          printf("%d of type %s ", cType[k], cName[k].c_str());
2589          if (((k + 1) % 3) == 0)
2590               printf("\n");
2591     }
2592     if ((k % 3) != 0)
2593          printf("\n");
2594     printf("Row breakdown:\n");
2595     for (k = 0; k < static_cast<int> (sizeof(rType) / sizeof(int)); k++) {
2596          printf("%d of type %s ", rType[k], rName[k].c_str());
2597          if (((k + 1) % 3) == 0)
2598               printf("\n");
2599     }
2600     if ((k % 3) != 0)
2601          printf("\n");
2602     //#define SYM
2603#ifndef SYM
2604     if (model->logLevel() < 2)
2605          return ;
2606#endif
2607     int kMax = model->logLevel() > 3 ? 1000000 : 10;
2608     k = 0;
2609     for (iRow = 1; iRow <= numberRows; iRow++) {
2610          if (number[iRow]) {
2611               k++;
2612               printf("%d columns have %d entries\n", number[iRow], iRow);
2613               if (k == kMax)
2614                    break;
2615          }
2616     }
2617     if (k < numberRows) {
2618          int kk = k;
2619          k = 0;
2620          for (iRow = numberRows; iRow >= 1; iRow--) {
2621               if (number[iRow]) {
2622                    k++;
2623                    if (k == kMax)
2624                         break;
2625               }
2626          }
2627          if (k > kk) {
2628               printf("\n    .........\n\n");
2629               iRow = k;
2630               k = 0;
2631               for (; iRow < numberRows; iRow++) {
2632                    if (number[iRow]) {
2633                         k++;
2634                         printf("%d columns have %d entries\n", number[iRow], iRow);
2635                         if (k == kMax)
2636                              break;
2637                    }
2638               }
2639          }
2640     }
2641     delete [] number;
2642     printf("\n\n");
2643     if (model->logLevel() == 63
2644#ifdef SYM
2645               || true
2646#endif
2647        ) {
2648          // get column copy
2649          CoinPackedMatrix columnCopy = *matrix;
2650          const int * columnLength = columnCopy.getVectorLengths();
2651          number = new int[numberRows+1];
2652          memset(number, 0, (numberRows + 1)*sizeof(int));
2653          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2654               int length = columnLength[iColumn];
2655               number[length]++;
2656          }
2657          k = 0;
2658          for (iRow = 1; iRow <= numberRows; iRow++) {
2659               if (number[iRow]) {
2660                    k++;
2661               }
2662          }
2663          int * row = columnCopy.getMutableIndices();
2664          const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
2665          double * element = columnCopy.getMutableElements();
2666          int * order = new int[numberColumns];
2667          int * other = new int[numberColumns];
2668          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2669               int length = columnLength[iColumn];
2670               order[iColumn] = iColumn;
2671               other[iColumn] = length;
2672               CoinBigIndex start = columnStart[iColumn];
2673               CoinSort_2(row + start, row + start + length, element + start);
2674          }
2675          CoinSort_2(other, other + numberColumns, order);
2676          int jColumn = number[0] + number[1];
2677          for (iRow = 2; iRow <= numberRows; iRow++) {
2678               if (number[iRow]) {
2679                    printf("XX %d columns have %d entries\n", number[iRow], iRow);
2680                    int kColumn = jColumn + number[iRow];
2681                    sortOnOther(row, columnStart,
2682                                order + jColumn, other, number[iRow], iRow, 0);
2683                    // Now print etc
2684                    if (iRow < 500000) {
2685                         for (int lColumn = jColumn; lColumn < kColumn; lColumn++) {
2686                              iColumn = order[lColumn];
2687                              CoinBigIndex start = columnStart[iColumn];
2688                              if (model->logLevel() == 63) {
2689                                   printf("column %d %g <= ", iColumn, columnLower[iColumn]);
2690                                   for (CoinBigIndex i = start; i < start + iRow; i++)
2691                                        printf("( %d, %g) ", row[i], element[i]);
2692                                   printf("<= %g\n", columnUpper[iColumn]);
2693                              }
2694                         }
2695                    }
2696                    jColumn = kColumn;
2697               }
2698          }
2699          delete [] order;
2700          delete [] other;
2701          delete [] number;
2702     }
2703     // get row copy
2704     CoinPackedMatrix rowCopy = *matrix;
2705     rowCopy.reverseOrdering();
2706     const int * rowLength = rowCopy.getVectorLengths();
2707     number = new int[numberColumns+1];
2708     memset(number, 0, (numberColumns + 1)*sizeof(int));
2709     for (iRow = 0; iRow < numberRows; iRow++) {
2710          int length = rowLength[iRow];
2711          number[length]++;
2712     }
2713     if (number[0])
2714          printf("** %d rows have no entries\n", number[0]);
2715     k = 0;
2716     for (iColumn = 1; iColumn <= numberColumns; iColumn++) {
2717          if (number[iColumn]) {
2718               k++;
2719               printf("%d rows have %d entries\n", number[iColumn], iColumn);
2720               if (k == kMax)
2721                    break;
2722          }
2723     }
2724     if (k < numberColumns) {
2725          int kk = k;
2726          k = 0;
2727          for (iColumn = numberColumns; iColumn >= 1; iColumn--) {
2728               if (number[iColumn]) {
2729                    k++;
2730                    if (k == kMax)
2731                         break;
2732               }
2733          }
2734          if (k > kk) {
2735               printf("\n    .........\n\n");
2736               iColumn = k;
2737               k = 0;
2738               for (; iColumn < numberColumns; iColumn++) {
2739                    if (number[iColumn]) {
2740                         k++;
2741                         printf("%d rows have %d entries\n", number[iColumn], iColumn);
2742                         if (k == kMax)
2743                              break;
2744                    }
2745               }
2746          }
2747     }
2748     if (model->logLevel() == 63
2749#ifdef SYM
2750               || true
2751#endif
2752        ) {
2753          int * column = rowCopy.getMutableIndices();
2754          const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
2755          double * element = rowCopy.getMutableElements();
2756          int * order = new int[numberRows];
2757          int * other = new int[numberRows];
2758          for (iRow = 0; iRow < numberRows; iRow++) {
2759               int length = rowLength[iRow];
2760               order[iRow] = iRow;
2761               other[iRow] = length;
2762               CoinBigIndex start = rowStart[iRow];
2763               CoinSort_2(column + start, column + start + length, element + start);
2764          }
2765          CoinSort_2(other, other + numberRows, order);
2766          int jRow = number[0] + number[1];
2767          double * weight = new double[numberRows];
2768          double * randomColumn = new double[numberColumns+1];
2769          double * randomRow = new double [numberRows+1];
2770          int * sortRow = new int [numberRows];
2771          int * possibleRow = new int [numberRows];
2772          int * backRow = new int [numberRows];
2773          int * stackRow = new int [numberRows];
2774          int * sortColumn = new int [numberColumns];
2775          int * possibleColumn = new int [numberColumns];
2776          int * backColumn = new int [numberColumns];
2777          int * backColumn2 = new int [numberColumns];
2778          int * mapRow = new int [numberRows];
2779          int * mapColumn = new int [numberColumns];
2780          int * stackColumn = new int [numberColumns];
2781          double randomLower = CoinDrand48();
2782          double randomUpper = CoinDrand48();
2783          double randomInteger = CoinDrand48();
2784          int * startAdd = new int[numberRows+1];
2785          int * columnAdd = new int [2*numberElements];
2786          double * elementAdd = new double[2*numberElements];
2787          int nAddRows = 0;
2788          startAdd[0] = 0;
2789          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2790               randomColumn[iColumn] = CoinDrand48();
2791               backColumn2[iColumn] = -1;
2792          }
2793          for (iColumn = 2; iColumn <= numberColumns; iColumn++) {
2794               if (number[iColumn]) {
2795                    printf("XX %d rows have %d entries\n", number[iColumn], iColumn);
2796                    int kRow = jRow + number[iColumn];
2797                    sortOnOther(column, rowStart,
2798                                order + jRow, other, number[iColumn], iColumn, 0);
2799                    // Now print etc
2800                    if (iColumn < 500000) {
2801                         int nLook = 0;
2802                         for (int lRow = jRow; lRow < kRow; lRow++) {
2803                              iRow = order[lRow];
2804                              CoinBigIndex start = rowStart[iRow];
2805                              if (model->logLevel() == 63) {
2806                                   printf("row %d %g <= ", iRow, rowLower[iRow]);
2807                                   for (CoinBigIndex i = start; i < start + iColumn; i++)
2808                                        printf("( %d, %g) ", column[i], element[i]);
2809                                   printf("<= %g\n", rowUpper[iRow]);
2810                              }
2811                              int first = column[start];
2812                              double sum = 0.0;
2813                              for (CoinBigIndex i = start; i < start + iColumn; i++) {
2814                                   int jColumn = column[i];
2815                                   double value = element[i];
2816                                   jColumn -= first;
2817                                   assert (jColumn >= 0);
2818                                   sum += value * randomColumn[jColumn];
2819                              }
2820                              if (rowLower[iRow] > -1.0e30 && rowLower[iRow])
2821                                   sum += rowLower[iRow] * randomLower;
2822                              else if (!rowLower[iRow])
2823                                   sum += 1.234567e-7 * randomLower;
2824                              if (rowUpper[iRow] < 1.0e30 && rowUpper[iRow])
2825                                   sum += rowUpper[iRow] * randomUpper;
2826                              else if (!rowUpper[iRow])
2827                                   sum += 1.234567e-7 * randomUpper;
2828                              sortRow[nLook] = iRow;
2829                              randomRow[nLook++] = sum;
2830                              // best way is to number unique elements and bounds and use
2831                              if (fabs(sum) > 1.0e4)
2832                                   sum *= 1.0e-6;
2833                              weight[iRow] = sum;
2834                         }
2835                         assert (nLook <= numberRows);
2836                         CoinSort_2(randomRow, randomRow + nLook, sortRow);
2837                         randomRow[nLook] = COIN_DBL_MAX;
2838                         double last = -COIN_DBL_MAX;
2839                         int iLast = -1;
2840                         for (int iLook = 0; iLook < nLook + 1; iLook++) {
2841                              if (randomRow[iLook] > last) {
2842                                   if (iLast >= 0) {
2843                                        int n = iLook - iLast;
2844                                        if (n > 1) {
2845                                             //printf("%d rows possible?\n",n);
2846                                        }
2847                                   }
2848                                   iLast = iLook;
2849                                   last = randomRow[iLook];
2850                              }
2851                         }
2852                    }
2853                    jRow = kRow;
2854               }
2855          }
2856          CoinPackedMatrix columnCopy = *matrix;
2857          const int * columnLength = columnCopy.getVectorLengths();
2858          const int * row = columnCopy.getIndices();
2859          const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
2860          const double * elementByColumn = columnCopy.getElements();
2861          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2862               int length = columnLength[iColumn];
2863               CoinBigIndex start = columnStart[iColumn];
2864               double sum = objective[iColumn];
2865               if (columnLower[iColumn] > -1.0e30 && columnLower[iColumn])
2866                    sum += columnLower[iColumn] * randomLower;
2867               else if (!columnLower[iColumn])
2868                    sum += 1.234567e-7 * randomLower;
2869               if (columnUpper[iColumn] < 1.0e30 && columnUpper[iColumn])
2870                    sum += columnUpper[iColumn] * randomUpper;
2871               else if (!columnUpper[iColumn])
2872                    sum += 1.234567e-7 * randomUpper;
2873               if (model->isInteger(iColumn))
2874                    sum += 9.87654321e-6 * randomInteger;
2875               for (CoinBigIndex i = start; i < start + length; i++) {
2876                    int iRow = row[i];
2877                    sum += elementByColumn[i] * weight[iRow];
2878               }
2879               sortColumn[iColumn] = iColumn;
2880               randomColumn[iColumn] = sum;
2881          }
2882          {
2883               CoinSort_2(randomColumn, randomColumn + numberColumns, sortColumn);
2884               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2885                    int i = sortColumn[iColumn];
2886                    backColumn[i] = iColumn;
2887               }
2888               randomColumn[numberColumns] = COIN_DBL_MAX;
2889               double last = -COIN_DBL_MAX;
2890               int iLast = -1;
2891               for (int iLook = 0; iLook < numberColumns + 1; iLook++) {
2892                    if (randomColumn[iLook] > last) {
2893                         if (iLast >= 0) {
2894                              int n = iLook - iLast;
2895                              if (n > 1) {
2896                                   //printf("%d columns possible?\n",n);
2897                              }
2898                              for (int i = iLast; i < iLook; i++) {
2899                                   possibleColumn[sortColumn[i]] = n;
2900                              }
2901                         }
2902                         iLast = iLook;
2903                         last = randomColumn[iLook];
2904                    }
2905               }
2906               for (iRow = 0; iRow < numberRows; iRow++) {
2907                    CoinBigIndex start = rowStart[iRow];
2908                    double sum = 0.0;
2909                    int length = rowLength[iRow];
2910                    for (CoinBigIndex i = start; i < start + length; i++) {
2911                         int jColumn = column[i];
2912                         double value = element[i];
2913                         jColumn = backColumn[jColumn];
2914                         sum += value * randomColumn[jColumn];
2915                         //if (iColumn==23089||iRow==23729)
2916                         //printf("row %d cola %d colb %d value %g rand %g sum %g\n",
2917                         //   iRow,jColumn,column[i],value,randomColumn[jColumn],sum);
2918                    }
2919                    sortRow[iRow] = iRow;
2920                    randomRow[iRow] = weight[iRow];
2921                    randomRow[iRow] = sum;
2922               }
2923               CoinSort_2(randomRow, randomRow + numberRows, sortRow);
2924               for (iRow = 0; iRow < numberRows; iRow++) {
2925                    int i = sortRow[iRow];
2926                    backRow[i] = iRow;
2927               }
2928               randomRow[numberRows] = COIN_DBL_MAX;
2929               last = -COIN_DBL_MAX;
2930               iLast = -1;
2931               // Do backward indices from order
2932               for (iRow = 0; iRow < numberRows; iRow++) {
2933                    other[order[iRow]] = iRow;
2934               }
2935               for (int iLook = 0; iLook < numberRows + 1; iLook++) {
2936                    if (randomRow[iLook] > last) {
2937                         if (iLast >= 0) {
2938                              int n = iLook - iLast;
2939                              if (n > 1) {
2940                                   //printf("%d rows possible?\n",n);
2941                                   // Within group sort as for original "order"
2942                                   for (int i = iLast; i < iLook; i++) {
2943                                        int jRow = sortRow[i];
2944                                        order[i] = other[jRow];
2945                                   }
2946                                   CoinSort_2(order + iLast, order + iLook, sortRow + iLast);
2947                              }
2948                              for (int i = iLast; i < iLook; i++) {
2949                                   possibleRow[sortRow[i]] = n;
2950                              }
2951                         }
2952                         iLast = iLook;
2953                         last = randomRow[iLook];
2954                    }
2955               }
2956               // Temp out
2957               for (int iLook = 0; iLook < numberRows - 1000000; iLook++) {
2958                    iRow = sortRow[iLook];
2959                    CoinBigIndex start = rowStart[iRow];
2960                    int length = rowLength[iRow];
2961                    int numberPossible = possibleRow[iRow];
2962                    for (CoinBigIndex i = start; i < start + length; i++) {
2963                         int jColumn = column[i];
2964                         if (possibleColumn[jColumn] != numberPossible)
2965                              numberPossible = -1;
2966                    }
2967                    int n = numberPossible;
2968                    if (numberPossible > 1) {
2969                         //printf("pppppossible %d\n",numberPossible);
2970                         for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) {
2971                              int jRow = sortRow[jLook];
2972                              CoinBigIndex start2 = rowStart[jRow];
2973                              assert (numberPossible == possibleRow[jRow]);
2974                              assert(length == rowLength[jRow]);
2975                              for (CoinBigIndex i = start2; i < start2 + length; i++) {
2976                                   int jColumn = column[i];
2977                                   if (possibleColumn[jColumn] != numberPossible)
2978                                        numberPossible = -1;
2979                              }
2980                         }
2981                         if (numberPossible < 2) {
2982                              // switch off
2983                              for (int jLook = iLook; jLook < iLook + n; jLook++)
2984                                   possibleRow[sortRow[jLook]] = -1;
2985                         }
2986                         // skip rest
2987                         iLook += n - 1;
2988                    } else {
2989                         possibleRow[iRow] = -1;
2990                    }
2991               }
2992               for (int iLook = 0; iLook < numberRows; iLook++) {
2993                    iRow = sortRow[iLook];
2994                    int numberPossible = possibleRow[iRow];
2995                    // Only if any integers
2996                    int numberIntegers = 0;
2997                    CoinBigIndex start = rowStart[iRow];
2998                    int length = rowLength[iRow];
2999                    for (CoinBigIndex i = start; i < start + length; i++) {
3000                         int jColumn = column[i];
3001                         if (model->isInteger(jColumn))
3002                              numberIntegers++;
3003                    }
3004                    if (numberPossible > 1 && !numberIntegers) {
3005                         //printf("possible %d - but no integers\n",numberPossible);
3006                    }
3007                    if (numberPossible > 1 && (numberIntegers || false)) {
3008                         //
3009                         printf("possible %d - %d integers\n", numberPossible, numberIntegers);
3010                         int lastLook = iLook;
3011                         int nMapRow = -1;
3012                         for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) {
3013                              // stop if too many failures
3014                              if (jLook > iLook + 10 && nMapRow < 0)
3015                                   break;
3016                              // Create identity mapping
3017                              int i;
3018                              for (i = 0; i < numberRows; i++)
3019                                   mapRow[i] = i;
3020                              for (i = 0; i < numberColumns; i++)
3021                                   mapColumn[i] = i;
3022                              int offset = jLook - iLook;
3023                              int nStackC = 0;
3024                              // build up row and column mapping
3025                              int nStackR = 1;
3026                              stackRow[0] = iLook;
3027                              bool good = true;
3028                              while (nStackR) {
3029                                   nStackR--;
3030                                   int look1 = stackRow[nStackR];
3031                                   int look2 = look1 + offset;
3032                                   assert (randomRow[look1] == randomRow[look2]);
3033                                   int row1 = sortRow[look1];
3034                                   int row2 = sortRow[look2];
3035                                   assert (mapRow[row1] == row1);
3036                                   assert (mapRow[row2] == row2);
3037                                   mapRow[row1] = row2;
3038                                   mapRow[row2] = row1;
3039                                   CoinBigIndex start1 = rowStart[row1];
3040                                   CoinBigIndex offset2 = rowStart[row2] - start1;
3041                                   int length = rowLength[row1];
3042                                   assert( length == rowLength[row2]);
3043                                   for (CoinBigIndex i = start1; i < start1 + length; i++) {
3044                                        int jColumn1 = column[i];
3045                                        int jColumn2 = column[i+offset2];
3046                                        if (randomColumn[backColumn[jColumn1]] !=
3047                                                  randomColumn[backColumn[jColumn2]]) {
3048                                             good = false;
3049                                             break;
3050                                        }
3051                                        if (mapColumn[jColumn1] == jColumn1) {
3052                                             // not touched
3053                                             assert (mapColumn[jColumn2] == jColumn2);
3054                                             if (jColumn1 != jColumn2) {
3055                                                  // Put on stack
3056                                                  mapColumn[jColumn1] = jColumn2;
3057                                                  mapColumn[jColumn2] = jColumn1;
3058                                                  stackColumn[nStackC++] = jColumn1;
3059                                             }
3060                                        } else {
3061                                             if (mapColumn[jColumn1] != jColumn2 ||
3062                                                       mapColumn[jColumn2] != jColumn1) {
3063                                                  // bad
3064                                                  good = false;
3065                                                  printf("bad col\n");
3066                                                  break;
3067                                             }
3068                                        }
3069                                   }
3070                                   if (!good)
3071                                        break;
3072                                   while (nStackC) {
3073                                        nStackC--;
3074                                        int iColumn = stackColumn[nStackC];
3075                                        int iColumn2 = mapColumn[iColumn];
3076                                        assert (iColumn != iColumn2);
3077                                        int length = columnLength[iColumn];
3078                                        assert (length == columnLength[iColumn2]);
3079                                        CoinBigIndex start = columnStart[iColumn];
3080                                        CoinBigIndex offset2 = columnStart[iColumn2] - start;
3081                                        for (CoinBigIndex i = start; i < start + length; i++) {
3082                                             int iRow = row[i];
3083                                             int iRow2 = row[i+offset2];
3084                                             if (mapRow[iRow] == iRow) {
3085                                                  // First (but be careful)
3086                                                  if (iRow != iRow2) {
3087                                                       //mapRow[iRow]=iRow2;
3088                                                       //mapRow[iRow2]=iRow;
3089                                                       int iBack = backRow[iRow];
3090                                                       int iBack2 = backRow[iRow2];
3091                                                       if (randomRow[iBack] == randomRow[iBack2] &&
3092                                                                 iBack2 - iBack == offset) {
3093                                                            stackRow[nStackR++] = iBack;
3094                                                       } else {
3095                                                            //printf("randomRow diff - weights %g %g\n",
3096                                                            //     weight[iRow],weight[iRow2]);
3097                                                            // bad
3098                                                            good = false;
3099                                                            break;
3100                                                       }
3101                                                  }
3102                                             } else {
3103                                                  if (mapRow[iRow] != iRow2 ||
3104                                                            mapRow[iRow2] != iRow) {
3105                                                       // bad
3106                                                       good = false;
3107                                                       printf("bad row\n");
3108                                                       break;
3109                                                  }
3110                                             }
3111                                        }
3112                                        if (!good)
3113                                             break;
3114                                   }
3115                              }
3116                              // then check OK
3117                              if (good) {
3118                                   for (iRow = 0; iRow < numberRows; iRow++) {
3119                                        CoinBigIndex start = rowStart[iRow];
3120                                        int length = rowLength[iRow];
3121                                        if (mapRow[iRow] == iRow) {
3122                                             for (CoinBigIndex i = start; i < start + length; i++) {
3123                                                  int jColumn = column[i];
3124                                                  backColumn2[jColumn] = i - start;
3125                                             }
3126                                             for (CoinBigIndex i = start; i < start + length; i++) {
3127                                                  int jColumn = column[i];
3128                                                  if (mapColumn[jColumn] != jColumn) {
3129                                                       int jColumn2 = mapColumn[jColumn];
3130                                                       CoinBigIndex i2 = backColumn2[jColumn2];
3131                                                       if (i2 < 0) {
3132                                                            good = false;
3133                                                       } else if (element[i] != element[i2+start]) {
3134                                                            good = false;
3135                                                       }
3136                                                  }
3137                                             }
3138                                             for (CoinBigIndex i = start; i < start + length; i++) {
3139                                                  int jColumn = column[i];
3140                                                  backColumn2[jColumn] = -1;
3141                                             }
3142                                        } else {
3143                                             int row2 = mapRow[iRow];
3144                                             assert (iRow = mapRow[row2]);
3145                                             if (rowLower[iRow] != rowLower[row2] ||
3146                                                       rowLower[row2] != rowLower[iRow])
3147                                                  good = false;
3148                                             CoinBigIndex offset2 = rowStart[row2] - start;
3149                                             for (CoinBigIndex i = start; i < start + length; i++) {
3150                                                  int jColumn = column[i];
3151                                                  double value = element[i];
3152                                                  int jColumn2 = column[i+offset2];
3153                                                  double value2 = element[i+offset2];
3154                                                  if (value != value2 || mapColumn[jColumn] != jColumn2 ||
3155                                                            mapColumn[jColumn2] != jColumn)
3156                                                       good = false;
3157                                             }
3158                                        }
3159                                   }
3160                                   if (good) {
3161                                        // check rim
3162                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3163                                             if (mapColumn[iColumn] != iColumn) {
3164                                                  int iColumn2 = mapColumn[iColumn];
3165                                                  if (objective[iColumn] != objective[iColumn2])
3166                                                       good = false;
3167                                                  if (columnLower[iColumn] != columnLower[iColumn2])
3168                                                       good = false;
3169                                                  if (columnUpper[iColumn] != columnUpper[iColumn2])
3170                                                       good = false;
3171                                                  if (model->isInteger(iColumn) != model->isInteger(iColumn2))
3172                                                       good = false;
3173                                             }
3174                                        }
3175                                   }
3176                                   if (good) {
3177                                        // temp
3178                                        if (nMapRow < 0) {
3179                                             //const double * solution = model->primalColumnSolution();
3180                                             // find mapped
3181                                             int nMapColumn = 0;
3182                                             for (int i = 0; i < numberColumns; i++) {
3183                                                  if (mapColumn[i] > i)
3184                                                       nMapColumn++;
3185                                             }
3186                                             nMapRow = 0;
3187                                             int kRow = -1;
3188                                             for (int i = 0; i < numberRows; i++) {
3189                                                  if (mapRow[i] > i) {
3190                                                       nMapRow++;
3191                                                       kRow = i;
3192                                                  }
3193                                             }
3194                                             printf("%d columns, %d rows\n", nMapColumn, nMapRow);
3195                                             if (nMapRow == 1) {
3196                                                  CoinBigIndex start = rowStart[kRow];
3197                                                  int length = rowLength[kRow];
3198                                                  printf("%g <= ", rowLower[kRow]);
3199                                                  for (CoinBigIndex i = start; i < start + length; i++) {
3200                                                       int jColumn = column[i];
3201                                                       if (mapColumn[jColumn] != jColumn)
3202                                                            printf("* ");
3203                                                       printf("%d,%g ", jColumn, element[i]);
3204                                                  }
3205                                                  printf("<= %g\n", rowUpper[kRow]);
3206                                             }
3207                                        }
3208                                        // temp
3209                                        int row1 = sortRow[lastLook];
3210                                        int row2 = sortRow[jLook];
3211                                        lastLook = jLook;
3212                                        CoinBigIndex start1 = rowStart[row1];
3213                                        CoinBigIndex offset2 = rowStart[row2] - start1;
3214                                        int length = rowLength[row1];
3215                                        assert( length == rowLength[row2]);
3216                                        CoinBigIndex put = startAdd[nAddRows];
3217                                        double multiplier = length < 11 ? 2.0 : 1.125;
3218                                        double value = 1.0;
3219                                        for (CoinBigIndex i = start1; i < start1 + length; i++) {
3220                                             int jColumn1 = column[i];
3221                                             int jColumn2 = column[i+offset2];
3222                                             columnAdd[put] = jColumn1;
3223                                             elementAdd[put++] = value;
3224                                             columnAdd[put] = jColumn2;
3225                                             elementAdd[put++] = -value;
3226                                             value *= multiplier;
3227                                        }
3228                                        nAddRows++;
3229                                        startAdd[nAddRows] = put;
3230                                   } else {
3231                                        printf("ouch - did not check out as good\n");
3232                                   }
3233                              }
3234                         }
3235                         // skip rest
3236                         iLook += numberPossible - 1;
3237                    }
3238               }
3239          }
3240          if (nAddRows) {
3241               double * lower = new double [nAddRows];
3242               double * upper = new double[nAddRows];
3243               int i;
3244               //const double * solution = model->primalColumnSolution();
3245               for (i = 0; i < nAddRows; i++) {
3246                    lower[i] = 0.0;
3247                    upper[i] = COIN_DBL_MAX;
3248               }
3249               printf("Adding %d rows with %d elements\n", nAddRows,
3250                      startAdd[nAddRows]);
3251               //ClpSimplex newModel(*model);
3252               //newModel.addRows(nAddRows,lower,upper,startAdd,columnAdd,elementAdd);
3253               //newModel.writeMps("modified.mps");
3254               delete [] lower;
3255               delete [] upper;
3256          }
3257          delete [] startAdd;
3258          delete [] columnAdd;
3259          delete [] elementAdd;
3260          delete [] order;
3261          delete [] other;
3262          delete [] randomColumn;
3263          delete [] weight;
3264          delete [] randomRow;
3265          delete [] sortRow;
3266          delete [] backRow;
3267          delete [] possibleRow;
3268          delete [] sortColumn;
3269          delete [] backColumn;
3270          delete [] backColumn2;
3271          delete [] possibleColumn;
3272          delete [] mapRow;
3273          delete [] mapColumn;
3274          delete [] stackRow;
3275          delete [] stackColumn;
3276     }
3277     delete [] number;
3278     // Now do breakdown of ranges
3279     breakdown("Elements", numberElements, elementByColumn);
3280     breakdown("RowLower", numberRows, rowLower);
3281     breakdown("RowUpper", numberRows, rowUpper);
3282     breakdown("ColumnLower", numberColumns, columnLower);
3283     breakdown("ColumnUpper", numberColumns, columnUpper);
3284     breakdown("Objective", numberColumns, objective);
3285}
3286static bool maskMatches(const int * starts, char ** masks,
3287                        std::string & check)
3288{
3289     // back to char as I am old fashioned
3290     const char * checkC = check.c_str();
3291     size_t length = strlen(checkC);
3292     while (checkC[length-1] == ' ')
3293          length--;
3294     for (int i = starts[length]; i < starts[length+1]; i++) {
3295          char * thisMask = masks[i];
3296          size_t k;
3297          for ( k = 0; k < length; k++) {
3298               if (thisMask[k] != '?' && thisMask[k] != checkC[k])
3299                    break;
3300          }
3301          if (k == length)
3302               return true;
3303     }
3304     return false;
3305}
3306static void clean(char * temp)
3307{
3308     char * put = temp;
3309     while (*put >= ' ')
3310          put++;
3311     *put = '\0';
3312}
3313static void generateCode(const char * fileName, int type)
3314{
3315     FILE * fp = fopen(fileName, "r");
3316     assert (fp);
3317     int numberLines = 0;
3318#define MAXLINES 500
3319#define MAXONELINE 200
3320     char line[MAXLINES][MAXONELINE];
3321     while (fgets(line[numberLines], MAXONELINE, fp)) {
3322          assert (numberLines < MAXLINES);
3323          clean(line[numberLines]);
3324          numberLines++;
3325     }
3326     fclose(fp);
3327     // add in actual solve
3328     strcpy(line[numberLines], "5  clpModel->initialSolve(clpSolve);");
3329     numberLines++;
3330     fp = fopen(fileName, "w");
3331     assert (fp);
3332     char apo = '"';
3333     char backslash = '\\';
3334
3335     fprintf(fp, "#include %cClpSimplex.hpp%c\n", apo, apo);
3336     fprintf(fp, "#include %cClpSolve.hpp%c\n", apo, apo);
3337
3338     fprintf(fp, "\nint main (int argc, const char *argv[])\n{\n");
3339     fprintf(fp, "  ClpSimplex  model;\n");
3340     fprintf(fp, "  int status=1;\n");
3341     fprintf(fp, "  if (argc<2)\n");
3342     fprintf(fp, "    fprintf(stderr,%cPlease give file name%cn%c);\n",
3343             apo, backslash, apo);
3344     fprintf(fp, "  else\n");
3345     fprintf(fp, "    status=model.readMps(argv[1],true);\n");
3346     fprintf(fp, "  if (status) {\n");
3347     fprintf(fp, "    fprintf(stderr,%cBad readMps %%s%cn%c,argv[1]);\n",
3348             apo, backslash, apo);
3349     fprintf(fp, "    exit(1);\n");
3350     fprintf(fp, "  }\n\n");
3351     fprintf(fp, "  // Now do requested saves and modifications\n");
3352     fprintf(fp, "  ClpSimplex * clpModel = & model;\n");
3353     int wanted[9];
3354     memset(wanted, 0, sizeof(wanted));
3355     wanted[0] = wanted[3] = wanted[5] = wanted[8] = 1;
3356     if (type > 0)
3357          wanted[1] = wanted[6] = 1;
3358     if (type > 1)
3359          wanted[2] = wanted[4] = wanted[7] = 1;
3360     std::string header[9] = { "", "Save values", "Redundant save of default values", "Set changed values",
3361                               "Redundant set default values", "Solve", "Restore values", "Redundant restore values", "Add to model"
3362                             };
3363     for (int iType = 0; iType < 9; iType++) {
3364          if (!wanted[iType])
3365               continue;
3366          int n = 0;
3367          int iLine;
3368          for (iLine = 0; iLine < numberLines; iLine++) {
3369               if (line[iLine][0] == '0' + iType) {
3370                    if (!n)
3371                         fprintf(fp, "\n  // %s\n\n", header[iType].c_str());
3372                    n++;
3373                    fprintf(fp, "%s\n", line[iLine] + 1);
3374               }
3375          }
3376     }
3377     fprintf(fp, "\n  // Now you would use solution etc etc\n\n");
3378     fprintf(fp, "  return 0;\n}\n");
3379     fclose(fp);
3380     printf("C++ file written to %s\n", fileName);
3381}
3382/*
3383  Version 1.00.00 October 13 2004.
3384  1.00.01 October 18.  Added basis handling helped/prodded by Thorsten Koch.
3385  Also modifications to make faster with sbb (I hope I haven't broken anything).
3386  1.00.02 March 21 2005.  Redid ClpNonLinearCost to save memory also redid
3387  createRim to try and improve cache characteristics.
3388  1.00.03 April 8 2005.  Added Volume algorithm as crash and made code more
3389  robust on testing.  Also added "either" and "tune" algorithm.
3390  1.01.01 April 12 2005.  Decided to go to different numbering.  Backups will
3391  be last 2 digits while middle 2 are for improvements.  Still take a long
3392  time to get to 2.00.01
3393  1.01.02 May 4 2005.  Will be putting in many changes - so saving stable version
3394  1.02.01 May 6 2005.  Lots of changes to try and make faster and more stable in
3395  branch and cut.
3396  1.02.02 May 19 2005.  Stuff for strong branching and some improvements to simplex
3397  1.03.01 May 24 2006.  Lots done but I can't remember what!
3398  1.03.03 June 13 2006.  For clean up after dual perturbation
3399  1.04.01 June 26 2007.  Lots of changes but I got lazy
3400  1.05.00 June 27 2007.  This is trunk so when gets to stable will be 1.5
3401  1.11.00 November 5 2009 (Guy Fawkes) - OSL factorization and better ordering
3402 */
Note: See TracBrowser for help on using the repository browser.