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

Last change on this file since 1525 was 1525, checked in by mjs, 10 years ago

Formatted .cpp, .hpp, .c, .h files with "astyle -A4 -p". This matches the formatting used in the grand CBC reorganization.

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