source: trunk/Clp/src/ClpMain.cpp @ 1681

Last change on this file since 1681 was 1681, checked in by forrest, 9 years ago

allow gmpl report

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