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

Last change on this file since 1502 was 1502, checked in by forrest, 10 years ago

moving sandbox stuff to trunk

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