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

Last change on this file since 1034 was 1034, checked in by forrest, 13 years ago

moving branches/devel to trunk

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 68.8 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3   
4#include "CoinPragma.hpp"
5
6#include <cassert>
7#include <cstdio>
8#include <cmath>
9#include <cfloat>
10#include <string>
11#include <iostream>
12
13
14#include "CoinPragma.hpp"
15#include "CoinHelperFunctions.hpp"
16#include "CoinSort.hpp"
17// History since 1.0 at end
18#define CLPVERSION "1.03.03"
19
20#include "CoinMpsIO.hpp"
21#include "CoinFileIO.hpp"
22
23#include "ClpFactorization.hpp"
24#include "CoinTime.hpp"
25#include "ClpSimplex.hpp"
26#include "ClpSimplexOther.hpp"
27#include "ClpSolve.hpp"
28#include "ClpPackedMatrix.hpp"
29#include "ClpPlusMinusOneMatrix.hpp"
30#include "ClpNetworkMatrix.hpp"
31#include "ClpDualRowSteepest.hpp"
32#include "ClpDualRowDantzig.hpp"
33#include "ClpLinearObjective.hpp"
34#include "ClpPrimalColumnSteepest.hpp"
35#include "ClpPrimalColumnDantzig.hpp"
36#include "ClpPresolve.hpp"
37#include "CbcOrClpParam.hpp"
38#ifdef DMALLOC
39#include "dmalloc.h"
40#endif
41#ifdef WSSMP_BARRIER
42#define FOREIGN_BARRIER
43#endif
44#ifdef UFL_BARRIER
45#define FOREIGN_BARRIER
46#endif
47#ifdef TAUCS_BARRIER
48#define FOREIGN_BARRIER
49#endif
50
51static double totalTime=0.0;
52static bool maskMatches(const int * starts, char ** masks,
53                        std::string & check);
54
55//#############################################################################
56
57#ifdef NDEBUG
58#undef NDEBUG
59#endif
60
61int mainTest (int argc, const char *argv[],int algorithm,
62              ClpSimplex empty, bool doPresolve,int switchOff,bool doVector);
63static void statistics(ClpSimplex * originalModel, ClpSimplex * model);
64static void generateCode(const char * fileName,int type);
65// Returns next valid field
66int CbcOrClpRead_mode=1;
67FILE * CbcOrClpReadCommand=stdin;
68int main (int argc, const char *argv[])
69{
70  // next {} is just to make sure all memory should be freed - for debug
71  {
72    double time1 = CoinCpuTime(),time2;
73    // Set up all non-standard stuff
74    //int numberModels=1;
75    ClpSimplex * models = new ClpSimplex[1];
76   
77    // default action on import
78    int allowImportErrors=0;
79    int keepImportNames=1;
80    int doIdiot=-1;
81    int outputFormat=2;
82    int slpValue=-1;
83    int cppValue=-1;
84    int printOptions=0;
85    int printMode=0;
86    int presolveOptions=0;
87    int doCrash=0;
88    int doVector=0;
89    int doSprint=-1;
90    // set reasonable defaults
91    int preSolve=5;
92    bool preSolveFile=false;
93    models->setPerturbation(50);
94    models->messageHandler()->setPrefix(false);
95    const char dirsep =  CoinFindDirSeparator();
96    std::string directory = (dirsep == '/' ? "./" : ".\\");
97    std::string defaultDirectory = directory;
98    std::string importFile ="";
99    std::string exportFile ="default.mps";
100    std::string importBasisFile ="";
101    int basisHasValues=0;
102    int substitution=3;
103    int dualize=0;
104    std::string exportBasisFile ="default.bas";
105    std::string saveFile ="default.prob";
106    std::string restoreFile ="default.prob";
107    std::string solutionFile ="stdout";
108    std::string solutionSaveFile ="solution.file";
109    std::string printMask="";
110    CbcOrClpParam parameters[CBCMAXPARAMETERS];
111    int numberParameters ;
112    establishParams(numberParameters,parameters) ;
113    parameters[whichParam(BASISIN,numberParameters,parameters)].setStringValue(importBasisFile);
114    parameters[whichParam(BASISOUT,numberParameters,parameters)].setStringValue(exportBasisFile);
115    parameters[whichParam(PRINTMASK,numberParameters,parameters)].setStringValue(printMask);
116    parameters[whichParam(DIRECTORY,numberParameters,parameters)].setStringValue(directory);
117    parameters[whichParam(DUALBOUND,numberParameters,parameters)].setDoubleValue(models->dualBound());
118    parameters[whichParam(DUALTOLERANCE,numberParameters,parameters)].setDoubleValue(models->dualTolerance());
119    parameters[whichParam(EXPORT,numberParameters,parameters)].setStringValue(exportFile);
120    parameters[whichParam(IDIOT,numberParameters,parameters)].setIntValue(doIdiot);
121    parameters[whichParam(IMPORT,numberParameters,parameters)].setStringValue(importFile);
122    parameters[whichParam(SOLVERLOGLEVEL,numberParameters,parameters)].setIntValue(models->logLevel());
123    parameters[whichParam(MAXFACTOR,numberParameters,parameters)].setIntValue(models->factorizationFrequency());
124    parameters[whichParam(MAXITERATION,numberParameters,parameters)].setIntValue(models->maximumIterations());
125    parameters[whichParam(OUTPUTFORMAT,numberParameters,parameters)].setIntValue(outputFormat);
126    parameters[whichParam(PRESOLVEPASS,numberParameters,parameters)].setIntValue(preSolve);
127    parameters[whichParam(PERTVALUE,numberParameters,parameters)].setIntValue(models->perturbation());
128    parameters[whichParam(PRIMALTOLERANCE,numberParameters,parameters)].setDoubleValue(models->primalTolerance());
129    parameters[whichParam(PRIMALWEIGHT,numberParameters,parameters)].setDoubleValue(models->infeasibilityCost());
130    parameters[whichParam(RESTORE,numberParameters,parameters)].setStringValue(restoreFile);
131    parameters[whichParam(SAVE,numberParameters,parameters)].setStringValue(saveFile);
132    parameters[whichParam(TIMELIMIT,numberParameters,parameters)].setDoubleValue(models->maximumSeconds());
133    parameters[whichParam(SOLUTION,numberParameters,parameters)].setStringValue(solutionFile);
134    parameters[whichParam(SAVESOL,numberParameters,parameters)].setStringValue(solutionSaveFile);
135    parameters[whichParam(SPRINT,numberParameters,parameters)].setIntValue(doSprint);
136    parameters[whichParam(SUBSTITUTION,numberParameters,parameters)].setIntValue(substitution);
137    parameters[whichParam(DUALIZE,numberParameters,parameters)].setIntValue(dualize);
138    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].setDoubleValue(1.0e-8);
139    int verbose=0;
140   
141    // total number of commands read
142    int numberGoodCommands=0;
143    bool * goodModels = new bool[1];
144
145    // Hidden stuff for barrier
146    int choleskyType = 0;
147    int gamma=0;
148    int scaleBarrier=0;
149    int doKKT=0;
150    int crossover=2; // do crossover unless quadratic
151   
152    int iModel=0;
153    goodModels[0]=false;
154    //models[0].scaling(1);
155    //models[0].setDualBound(1.0e6);
156    //models[0].setDualTolerance(1.0e-7);
157    //ClpDualRowSteepest steep;
158    //models[0].setDualRowPivotAlgorithm(steep);
159    //models[0].setPrimalTolerance(1.0e-7);
160    //ClpPrimalColumnSteepest steepP;
161    //models[0].setPrimalColumnPivotAlgorithm(steepP);
162    std::string field;
163    std::cout<<"Coin LP version "<<CLPVERSION
164             <<", build "<<__DATE__<<std::endl;
165    // Print command line
166    if (argc>1) {
167      printf("command line - ");
168      for (int i=0;i<argc;i++)
169        printf("%s ",argv[i]);
170      printf("\n");
171    }
172   
173    while (1) {
174      // next command
175      field=CoinReadGetCommand(argc,argv);
176     
177      // exit if null or similar
178      if (!field.length()) {
179        if (numberGoodCommands==1&&goodModels[0]) {
180          // we just had file name - do dual or primal
181          field="either";
182        } else if (!numberGoodCommands) {
183          // let's give the sucker a hint
184          std::cout
185            <<"Clp takes input from arguments ( - switches to stdin)"
186            <<std::endl
187            <<"Enter ? for list of commands or help"<<std::endl;
188          field="-";
189        } else {
190          break;
191        }
192      }
193     
194      // see if ? at end
195      int numberQuery=0;
196      if (field!="?"&&field!="???") {
197        int length = field.length();
198        int i;
199        for (i=length-1;i>0;i--) {
200          if (field[i]=='?') 
201            numberQuery++;
202          else
203            break;
204        }
205        field=field.substr(0,length-numberQuery);
206      }
207      // find out if valid command
208      int iParam;
209      int numberMatches=0;
210      int firstMatch=-1;
211      for ( iParam=0; iParam<numberParameters; iParam++ ) {
212        int match = parameters[iParam].matches(field);
213        if (match==1) {
214          numberMatches = 1;
215          firstMatch=iParam;
216          break;
217        } else {
218          if (match&&firstMatch<0)
219            firstMatch=iParam;
220          numberMatches += match>>1;
221        }
222      }
223      if (iParam<numberParameters&&!numberQuery) {
224        // found
225        CbcOrClpParam found = parameters[iParam];
226        CbcOrClpParameterType type = found.type();
227        int valid;
228        numberGoodCommands++;
229        if (type==GENERALQUERY) {
230          std::cout<<"In argument list keywords have leading - "
231            ", -stdin or just - switches to stdin"<<std::endl;
232          std::cout<<"One command per line (and no -)"<<std::endl;
233          std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
234          std::cout<<"abcd?? adds explanation, if only one fuller help"<<std::endl;
235          std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
236          std::cout<<"abcd value sets value"<<std::endl;
237          std::cout<<"Commands are:"<<std::endl;
238          int maxAcross=5;
239          bool evenHidden=false;
240          if ((verbose&8)!=0) {
241            // even hidden
242            evenHidden = true;
243            verbose &= ~8;
244          }
245          if (verbose)
246            maxAcross=1;
247          int limits[]={1,101,201,301,401};
248          std::vector<std::string> types;
249          types.push_back("Double parameters:");
250          types.push_back("Int parameters:");
251          types.push_back("Keyword parameters:");
252          types.push_back("Actions or string parameters:");
253          int iType;
254          for (iType=0;iType<4;iType++) {
255            int across=0;
256            if ((verbose%4)!=0)
257              std::cout<<std::endl;
258            std::cout<<types[iType]<<std::endl;
259            if ((verbose&2)!=0)
260              std::cout<<std::endl;
261            for ( iParam=0; iParam<numberParameters; iParam++ ) {
262              int type = parameters[iParam].type();
263              if ((parameters[iParam].displayThis()||evenHidden)&&
264                  type>=limits[iType]
265                  &&type<limits[iType+1]) {
266                if (!across) {
267                  if ((verbose&2)==0) 
268                    std::cout<<"  ";
269                  else
270                    std::cout<<"Command ";
271                }
272                std::cout<<parameters[iParam].matchName()<<"  ";
273                across++;
274                if (across==maxAcross) {
275                  across=0;
276                  if (verbose) {
277                    // put out description as well
278                    if ((verbose&1)!=0) 
279                      std::cout<<parameters[iParam].shortHelp();
280                    std::cout<<std::endl;
281                    if ((verbose&2)!=0) {
282                      std::cout<<"---- description"<<std::endl;
283                      parameters[iParam].printLongHelp();
284                      std::cout<<"----"<<std::endl<<std::endl;
285                    }
286                  } else {
287                    std::cout<<std::endl;
288                  }
289                }
290              }
291            }
292            if (across)
293              std::cout<<std::endl;
294          }
295        } else if (type==FULLGENERALQUERY) {
296          std::cout<<"Full list of commands is:"<<std::endl;
297          int maxAcross=5;
298          int limits[]={1,101,201,301,401};
299          std::vector<std::string> types;
300          types.push_back("Double parameters:");
301          types.push_back("Int parameters:");
302          types.push_back("Keyword parameters and others:");
303          types.push_back("Actions:");
304          int iType;
305          for (iType=0;iType<4;iType++) {
306            int across=0;
307            std::cout<<types[iType]<<std::endl;
308            for ( iParam=0; iParam<numberParameters; iParam++ ) {
309              int type = parameters[iParam].type();
310              if (type>=limits[iType]
311                  &&type<limits[iType+1]) {
312                if (!across)
313                  std::cout<<"  ";
314                std::cout<<parameters[iParam].matchName()<<"  ";
315                across++;
316                if (across==maxAcross) {
317                  std::cout<<std::endl;
318                  across=0;
319                }
320              }
321            }
322            if (across)
323              std::cout<<std::endl;
324          }
325        } else if (type<101) {
326          // get next field as double
327          double value = CoinReadGetDoubleField(argc,argv,&valid);
328          if (!valid) {
329            parameters[iParam].setDoubleParameter(models+iModel,value);
330          } else if (valid==1) {
331            abort();
332          } else {
333            std::cout<<parameters[iParam].name()<<" has value "<<
334              parameters[iParam].doubleValue()<<std::endl;
335          }
336        } else if (type<201) {
337          // get next field as int
338          int value = CoinReadGetIntField(argc,argv,&valid);
339          if (!valid) {
340            if (parameters[iParam].type()==PRESOLVEPASS)
341              preSolve = value;
342            else if (parameters[iParam].type()==IDIOT)
343              doIdiot = value;
344            else if (parameters[iParam].type()==SPRINT)
345              doSprint = value;
346            else if (parameters[iParam].type()==OUTPUTFORMAT)
347              outputFormat = value;
348            else if (parameters[iParam].type()==SLPVALUE)
349              slpValue = value;
350            else if (parameters[iParam].type()==CPP)
351              cppValue = value;
352            else if (parameters[iParam].type()==PRESOLVEOPTIONS)
353              presolveOptions = value;
354            else if (parameters[iParam].type()==PRINTOPTIONS)
355              printOptions = value;
356            else if (parameters[iParam].type()==SUBSTITUTION)
357              substitution = value;
358            else if (parameters[iParam].type()==DUALIZE)
359              dualize = value;
360            else if (parameters[iParam].type()==VERBOSE)
361              verbose = value;
362            parameters[iParam].setIntParameter(models+iModel,value);
363          } else if (valid==1) {
364            abort();
365          } else {
366            std::cout<<parameters[iParam].name()<<" has value "<<
367              parameters[iParam].intValue()<<std::endl;
368          }
369        } else if (type<301) {
370          // one of several strings
371          std::string value = CoinReadGetString(argc,argv);
372          int action = parameters[iParam].parameterOption(value);
373          if (action<0) {
374            if (value!="EOL") {
375              // no match
376              parameters[iParam].printOptions();
377            } else {
378              // print current value
379              std::cout<<parameters[iParam].name()<<" has value "<<
380                parameters[iParam].currentOption()<<std::endl;
381            }
382          } else {
383            parameters[iParam].setCurrentOption(action);
384            // for now hard wired
385            switch (type) {
386            case DIRECTION:
387              if (action==0)
388                models[iModel].setOptimizationDirection(1);
389              else if (action==1)
390                models[iModel].setOptimizationDirection(-1);
391              else
392                models[iModel].setOptimizationDirection(0);
393              break;
394            case DUALPIVOT:
395              if (action==0) {
396                ClpDualRowSteepest steep(3);
397                models[iModel].setDualRowPivotAlgorithm(steep);
398              } else if (action==1) {
399                //ClpDualRowDantzig dantzig;
400                ClpDualRowSteepest dantzig(5);
401                models[iModel].setDualRowPivotAlgorithm(dantzig);
402              } else if (action==2) {
403                // partial steep
404                ClpDualRowSteepest steep(2);
405                models[iModel].setDualRowPivotAlgorithm(steep);
406              } else {
407                ClpDualRowSteepest steep;
408                models[iModel].setDualRowPivotAlgorithm(steep);
409              }
410              break;
411            case PRIMALPIVOT:
412              if (action==0) {
413                ClpPrimalColumnSteepest steep(3);
414                models[iModel].setPrimalColumnPivotAlgorithm(steep);
415              } else if (action==1) {
416                ClpPrimalColumnSteepest steep(0);
417                models[iModel].setPrimalColumnPivotAlgorithm(steep);
418              } else if (action==2) {
419                ClpPrimalColumnDantzig dantzig;
420                models[iModel].setPrimalColumnPivotAlgorithm(dantzig);
421              } else if (action==3) {
422                ClpPrimalColumnSteepest steep(2);
423                models[iModel].setPrimalColumnPivotAlgorithm(steep);
424              } else if (action==4) {
425                ClpPrimalColumnSteepest steep(1);
426                models[iModel].setPrimalColumnPivotAlgorithm(steep);
427              } else if (action==5) {
428                ClpPrimalColumnSteepest steep(4);
429                models[iModel].setPrimalColumnPivotAlgorithm(steep);
430              } else if (action==6) {
431                ClpPrimalColumnSteepest steep(10);
432                models[iModel].setPrimalColumnPivotAlgorithm(steep);
433              }
434              break;
435            case SCALING:
436              models[iModel].scaling(action);
437              break;
438            case AUTOSCALE:
439              models[iModel].setAutomaticScaling(action!=0);
440              break;
441            case SPARSEFACTOR:
442              models[iModel].setSparseFactorization((1-action)!=0);
443              break;
444            case BIASLU:
445              models[iModel].factorization()->setBiasLU(action);
446              break;
447            case PERTURBATION:
448              if (action==0)
449                models[iModel].setPerturbation(50);
450              else
451                models[iModel].setPerturbation(100);
452              break;
453            case ERRORSALLOWED:
454              allowImportErrors = action;
455              break;
456            case INTPRINT:
457              printMode=action;
458              break;
459            case KEEPNAMES:
460              keepImportNames = 1-action;
461              break;
462            case PRESOLVE:
463              if (action==0)
464                preSolve = 5;
465              else if (action==1)
466                preSolve=0;
467              else if (action==2)
468                preSolve=10;
469              else
470                preSolveFile=true;
471              break;
472            case PFI:
473              models[iModel].factorization()->setForrestTomlin(action==0);
474              break;
475            case CRASH:
476              doCrash=action;
477              break;
478            case VECTOR:
479              doVector=action;
480              break;
481            case MESSAGES:
482              models[iModel].messageHandler()->setPrefix(action!=0);
483              break;
484            case CHOLESKY:
485              choleskyType = action;
486              break;
487            case GAMMA:
488              gamma=action;
489              break;
490            case BARRIERSCALE:
491              scaleBarrier=action;
492              break;
493            case KKT:
494              doKKT=action;
495              break;
496            case CROSSOVER:
497              crossover=action;
498              break;
499            default:
500              abort();
501            }
502          }
503        } else {
504          // action
505          if (type==EXIT)
506            break; // stop all
507          switch (type) {
508          case DUALSIMPLEX:
509          case PRIMALSIMPLEX:
510          case EITHERSIMPLEX:
511          case BARRIER:
512            // synonym for dual
513          case BAB:
514            if (goodModels[iModel]) {
515              double objScale = 
516                parameters[whichParam(OBJSCALE2,numberParameters,parameters)].doubleValue();
517              if (objScale!=1.0) {
518                int iColumn;
519                int numberColumns=models[iModel].numberColumns();
520                double * dualColumnSolution = 
521                  models[iModel].dualColumnSolution();
522                ClpObjective * obj = models[iModel].objectiveAsObject();
523                assert(dynamic_cast<ClpLinearObjective *> (obj));
524                double offset;
525                double * objective = obj->gradient(NULL,NULL,offset,true);
526                for (iColumn=0;iColumn<numberColumns;iColumn++) {
527                  dualColumnSolution[iColumn] *= objScale;
528                  objective[iColumn] *= objScale;;
529                }
530                int iRow;
531                int numberRows=models[iModel].numberRows();
532                double * dualRowSolution = 
533                  models[iModel].dualRowSolution();
534                for (iRow=0;iRow<numberRows;iRow++) 
535                  dualRowSolution[iRow] *= objScale;
536                models[iModel].setObjectiveOffset(objScale*models[iModel].objectiveOffset());
537              }
538              ClpSolve::SolveType method;
539              ClpSolve::PresolveType presolveType;
540              ClpSimplex * model2 = models+iModel;
541              if (dualize) {
542                model2 = ((ClpSimplexOther *) model2)->dualOfModel();
543                printf("Dual of model has %d rows and %d columns\n",
544                       model2->numberRows(),model2->numberColumns());
545                model2->setOptimizationDirection(1.0);
546              }
547              ClpSolve solveOptions;
548              solveOptions.setPresolveActions(presolveOptions);
549              solveOptions.setSubstitution(substitution);
550              if (preSolve!=5&&preSolve) {
551                presolveType=ClpSolve::presolveNumber;
552                if (preSolve<0) {
553                  preSolve = - preSolve;
554                  if (preSolve<=100) {
555                    presolveType=ClpSolve::presolveNumber;
556                    printf("Doing %d presolve passes - picking up non-costed slacks\n",
557                           preSolve);
558                    solveOptions.setDoSingletonColumn(true);
559                  } else {
560                    preSolve -=100;
561                    presolveType=ClpSolve::presolveNumberCost;
562                    printf("Doing %d presolve passes - picking up costed slacks\n",
563                           preSolve);
564                  }
565                } 
566              } else if (preSolve) {
567                presolveType=ClpSolve::presolveOn;
568              } else {
569                presolveType=ClpSolve::presolveOff;
570              }
571              solveOptions.setPresolveType(presolveType,preSolve);
572              if (type==DUALSIMPLEX||type==BAB) {
573                method=ClpSolve::useDual;
574              } else if (type==PRIMALSIMPLEX) {
575                method=ClpSolve::usePrimalorSprint;
576              } else if (type==EITHERSIMPLEX) {
577                method=ClpSolve::automatic;
578              } else {
579                method = ClpSolve::useBarrier;
580                if (crossover==1) {
581                  method=ClpSolve::useBarrierNoCross;
582                } else if (crossover==2) {
583                  ClpObjective * obj = models[iModel].objectiveAsObject();
584                  if (obj->type()>1) {
585                    method=ClpSolve::useBarrierNoCross;
586                    presolveType=ClpSolve::presolveOff;
587                    solveOptions.setPresolveType(presolveType,preSolve);
588                  } 
589                }
590              }
591              solveOptions.setSolveType(method);
592              if(preSolveFile)
593                presolveOptions |= 0x40000000;
594              solveOptions.setSpecialOption(4,presolveOptions);
595              solveOptions.setSpecialOption(5,printOptions&1);
596              if (doVector) {
597                ClpMatrixBase * matrix = models[iModel].clpMatrix();
598                if (dynamic_cast< ClpPackedMatrix*>(matrix)) {
599                  ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix);
600                  clpMatrix->makeSpecialColumnCopy();
601                }
602              }
603              if (method==ClpSolve::useDual) {
604                // dual
605                if (doCrash)
606                  solveOptions.setSpecialOption(0,1,doCrash); // crash
607                else if (doIdiot)
608                  solveOptions.setSpecialOption(0,2,doIdiot); // possible idiot
609              } else if (method==ClpSolve::usePrimalorSprint) {
610                // primal
611                // if slp turn everything off
612                if (slpValue>0) {
613                  doCrash=false;
614                  doSprint=0;
615                  doIdiot=-1;
616                  solveOptions.setSpecialOption(1,10,slpValue); // slp
617                  method=ClpSolve::usePrimal;
618                }
619                if (doCrash) {
620                  solveOptions.setSpecialOption(1,1,doCrash); // crash
621                } else if (doSprint>0) {
622                  // sprint overrides idiot
623                  solveOptions.setSpecialOption(1,3,doSprint); // sprint
624                } else if (doIdiot>0) {
625                  solveOptions.setSpecialOption(1,2,doIdiot); // idiot
626                } else if (slpValue<=0) {
627                  if (doIdiot==0) {
628                    if (doSprint==0)
629                      solveOptions.setSpecialOption(1,4); // all slack
630                    else
631                      solveOptions.setSpecialOption(1,9); // all slack or sprint
632                  } else {
633                    if (doSprint==0)
634                      solveOptions.setSpecialOption(1,8); // all slack or idiot
635                    else
636                      solveOptions.setSpecialOption(1,7); // initiative
637                  }
638                }
639                if (basisHasValues==-1)
640                  solveOptions.setSpecialOption(1,11); // switch off values
641              } else if (method==ClpSolve::useBarrier||method==ClpSolve::useBarrierNoCross) {
642                int barrierOptions = choleskyType;
643                if (scaleBarrier)
644                  barrierOptions |= 8;
645                if (doKKT)
646                  barrierOptions |= 16;
647                if (gamma)
648                  barrierOptions |= 32*gamma;
649                if (crossover==3) 
650                  barrierOptions |= 256; // try presolve in crossover
651                solveOptions.setSpecialOption(4,barrierOptions);
652              }
653              int status;
654              if (cppValue>=0) {
655                // generate code
656                FILE * fp = fopen("user_driver.cpp","w");
657                if (fp) {
658                  // generate enough to do solveOptions
659                  model2->generateCpp(fp);
660                  solveOptions.generateCpp(fp);
661                  fclose(fp);
662                  // now call generate code
663                  generateCode("user_driver.cpp",cppValue);
664                } else {
665                  std::cout<<"Unable to open file user_driver.cpp"<<std::endl;
666                }
667              }
668              try {
669                status=model2->initialSolve(solveOptions);
670              }
671              catch (CoinError e) {
672                e.print();
673                status=-1;
674              }
675              if (dualize) {
676                int returnCode=((ClpSimplexOther *) models+iModel)->restoreFromDual(model2);
677                delete model2;
678                if (returnCode&&dualize!=2)
679                  models[iModel].primal(1);
680              }
681              if (status>=0)
682                basisHasValues=1;
683            } else {
684              std::cout<<"** Current model not valid"<<std::endl;
685            }
686            break;
687          case STATISTICS:
688            if (goodModels[iModel]) {
689              // If presolve on look at presolved
690              bool deleteModel2=false;
691              ClpSimplex * model2 = models+iModel;
692              if (preSolve) {
693                ClpPresolve pinfo;
694                int presolveOptions2 = presolveOptions&~0x40000000;
695                if ((presolveOptions2&0xffff)!=0)
696                  pinfo.setPresolveActions(presolveOptions2);
697                pinfo.setSubstitution(substitution);
698                if ((printOptions&1)!=0)
699                  pinfo.statistics();
700                double presolveTolerance = 
701                  parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
702                model2 = 
703                  pinfo.presolvedModel(models[iModel],presolveTolerance,
704                                       true,preSolve);
705                if (model2) {
706                  printf("Statistics for presolved model\n");
707                  deleteModel2=true;
708                } else {
709                  printf("Presolved model looks infeasible - will use unpresolved\n");
710                  model2 = models+iModel;
711                }
712              } else {
713                printf("Statistics for unpresolved model\n");
714                model2 =  models+iModel;
715              }
716              statistics(models+iModel,model2);
717              if (deleteModel2)
718                delete model2;
719            } else {
720              std::cout<<"** Current model not valid"<<std::endl;
721            }
722            break;
723          case TIGHTEN:
724            if (goodModels[iModel]) {
725              int numberInfeasibilities = models[iModel].tightenPrimalBounds();
726              if (numberInfeasibilities)
727                std::cout<<"** Analysis indicates model infeasible"<<std::endl;
728            } else {
729              std::cout<<"** Current model not valid"<<std::endl;
730            }
731            break;
732          case PLUSMINUS:
733            if (goodModels[iModel]) {
734              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
735              ClpPackedMatrix* clpMatrix =
736                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
737              if (clpMatrix) {
738                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
739                if (newMatrix->getIndices()) {
740                  models[iModel].replaceMatrix(newMatrix);
741                  delete saveMatrix;
742                  std::cout<<"Matrix converted to +- one matrix"<<std::endl;
743                } else {
744                  std::cout<<"Matrix can not be converted to +- 1 matrix"<<std::endl;
745                }
746              } else {
747                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
748              }
749            } else {
750              std::cout<<"** Current model not valid"<<std::endl;
751            }
752            break;
753          case NETWORK:
754            if (goodModels[iModel]) {
755              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
756              ClpPackedMatrix* clpMatrix =
757                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
758              if (clpMatrix) {
759                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
760                if (newMatrix->getIndices()) {
761                  models[iModel].replaceMatrix(newMatrix);
762                  delete saveMatrix;
763                  std::cout<<"Matrix converted to network matrix"<<std::endl;
764                } else {
765                  std::cout<<"Matrix can not be converted to network matrix"<<std::endl;
766                }
767              } else {
768                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
769              }
770            } else {
771              std::cout<<"** Current model not valid"<<std::endl;
772            }
773            break;
774          case IMPORT:
775            {
776              // get next field
777              field = CoinReadGetString(argc,argv);
778              if (field=="$") {
779                field = parameters[iParam].stringValue();
780              } else if (field=="EOL") {
781                parameters[iParam].printString();
782                break;
783              } else {
784                parameters[iParam].setStringValue(field);
785              }
786              std::string fileName;
787              bool canOpen=false;
788              // See if gmpl file
789              int gmpl=0;
790              std::string gmplData;
791              if (field=="-") {
792                // stdin
793                canOpen=true;
794                fileName = "-";
795              } else {
796                // See if .lp
797                {
798                  const char * c_name = field.c_str();
799                  int length = strlen(c_name);
800                  if (length>3&&!strncmp(c_name+length-3,".lp",3))
801                    gmpl=-1; // .lp
802                }
803                bool absolutePath;
804                if (dirsep=='/') {
805                  // non Windows (or cygwin)
806                  absolutePath=(field[0]=='/');
807                } else {
808                  //Windows (non cycgwin)
809                  absolutePath=(field[0]=='\\');
810                  // but allow for :
811                  if (strchr(field.c_str(),':'))
812                    absolutePath=true;
813                }
814                if (absolutePath) {
815                  fileName = field;
816                } else if (field[0]=='~') {
817                  char * environVar = getenv("HOME");
818                  if (environVar) {
819                    std::string home(environVar);
820                    field=field.erase(0,1);
821                    fileName = home+field;
822                  } else {
823                    fileName=field;
824                  }
825                } else {
826                  fileName = directory+field;
827                  // See if gmpl (model & data) - or even lp file
828                  int length = field.size();
829                  int percent = field.find('%');
830                  if (percent<length&&percent>0) {
831                    gmpl=1;
832                    fileName = directory+field.substr(0,percent);
833                    gmplData = directory+field.substr(percent+1);
834                    if (percent<length-1)
835                      gmpl=2; // two files
836                    printf("GMPL model file %s and data file %s\n",
837                           fileName.c_str(),gmplData.c_str());
838                  }
839                }
840                std::string name=fileName;
841                if (fileCoinReadable(name)) {
842                  // can open - lets go for it
843                  canOpen=true;
844                  if (gmpl==2) {
845                    FILE *fp;
846                    fp=fopen(gmplData.c_str(),"r");
847                    if (fp) {
848                      fclose(fp);
849                    } else {
850                      canOpen=false;
851                      std::cout<<"Unable to open file "<<gmplData<<std::endl;
852                    }
853                  }
854                } else {
855                  std::cout<<"Unable to open file "<<fileName<<std::endl;
856                }
857              }
858              if (canOpen) {
859                int status;
860                if (!gmpl)
861                  status =models[iModel].readMps(fileName.c_str(),
862                                                 keepImportNames!=0,
863                                                 allowImportErrors!=0);
864                else if (gmpl>0)
865                  status= models[iModel].readGMPL(fileName.c_str(),
866                                                  (gmpl==2) ? gmplData.c_str() : NULL,
867                                                  keepImportNames!=0);
868                else
869                  status= models[iModel].readLp(fileName.c_str(),1.0e-12);
870                if (!status||(status>0&&allowImportErrors)) {
871                  goodModels[iModel]=true;
872                  // sets to all slack (not necessary?)
873                  models[iModel].createStatus();
874                  time2 = CoinCpuTime();
875                  totalTime += time2-time1;
876                  time1=time2;
877                  // Go to canned file if just input file
878                  if (CbcOrClpRead_mode==2&&argc==2) {
879                    // only if ends .mps
880                    char * find = (char *)strstr(fileName.c_str(),".mps");
881                    if (find&&find[4]=='\0') {
882                      find[1]='p'; find[2]='a';find[3]='r';
883                      FILE *fp=fopen(fileName.c_str(),"r");
884                      if (fp) {
885                        CbcOrClpReadCommand=fp; // Read from that file
886                        CbcOrClpRead_mode=-1;
887                      }
888                    }
889                  }
890                } else {
891                  // errors
892                  std::cout<<"There were "<<status<<
893                    " errors on input"<<std::endl;
894                }
895              }
896            }
897            break;
898          case EXPORT:
899            if (goodModels[iModel]) {
900              double objScale = 
901                parameters[whichParam(OBJSCALE2,numberParameters,parameters)].doubleValue();
902              if (objScale!=1.0) {
903                int iColumn;
904                int numberColumns=models[iModel].numberColumns();
905                double * dualColumnSolution = 
906                  models[iModel].dualColumnSolution();
907                ClpObjective * obj = models[iModel].objectiveAsObject();
908                assert(dynamic_cast<ClpLinearObjective *> (obj));
909                double offset;
910                double * objective = obj->gradient(NULL,NULL,offset,true);
911                for (iColumn=0;iColumn<numberColumns;iColumn++) {
912                  dualColumnSolution[iColumn] *= objScale;
913                  objective[iColumn] *= objScale;;
914                }
915                int iRow;
916                int numberRows=models[iModel].numberRows();
917                double * dualRowSolution = 
918                  models[iModel].dualRowSolution();
919                for (iRow=0;iRow<numberRows;iRow++) 
920                  dualRowSolution[iRow] *= objScale;
921                models[iModel].setObjectiveOffset(objScale*models[iModel].objectiveOffset());
922              }
923              // get next field
924              field = CoinReadGetString(argc,argv);
925              if (field=="$") {
926                field = parameters[iParam].stringValue();
927              } else if (field=="EOL") {
928                parameters[iParam].printString();
929                break;
930              } else {
931                parameters[iParam].setStringValue(field);
932              }
933              std::string fileName;
934              bool canOpen=false;
935              if (field[0]=='/'||field[0]=='\\') {
936                fileName = field;
937              } else if (field[0]=='~') {
938                char * environVar = getenv("HOME");
939                if (environVar) {
940                  std::string home(environVar);
941                  field=field.erase(0,1);
942                  fileName = home+field;
943                } else {
944                  fileName=field;
945                }
946              } else {
947                fileName = directory+field;
948              }
949              FILE *fp=fopen(fileName.c_str(),"w");
950              if (fp) {
951                // can open - lets go for it
952                fclose(fp);
953                canOpen=true;
954              } else {
955                std::cout<<"Unable to open file "<<fileName<<std::endl;
956              }
957              if (canOpen) {
958                // If presolve on then save presolved
959                bool deleteModel2=false;
960                ClpSimplex * model2 = models+iModel;
961                if (dualize) {
962                  model2 = ((ClpSimplexOther *) model2)->dualOfModel();
963                  printf("Dual of model has %d rows and %d columns\n",
964                         model2->numberRows(),model2->numberColumns());
965                  model2->setOptimizationDirection(1.0);
966                  preSolve=0; // as picks up from model
967                }
968                if (preSolve) {
969                  ClpPresolve pinfo;
970                  int presolveOptions2 = presolveOptions&~0x40000000;
971                  if ((presolveOptions2&0xffff)!=0)
972                    pinfo.setPresolveActions(presolveOptions2);
973                  pinfo.setSubstitution(substitution);
974                  if ((printOptions&1)!=0)
975                    pinfo.statistics();
976                  double presolveTolerance = 
977                    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
978                  model2 = 
979                    pinfo.presolvedModel(models[iModel],presolveTolerance,
980                                         true,preSolve,false,false);
981                  if (model2) {
982                    printf("Saving presolved model on %s\n",
983                           fileName.c_str());
984                    deleteModel2=true;
985                  } else {
986                    printf("Presolved model looks infeasible - saving original on %s\n",
987                           fileName.c_str());
988                    deleteModel2=false;
989                    model2 = models+iModel;
990
991                  }
992                } else {
993                  printf("Saving model on %s\n",
994                           fileName.c_str());
995                }
996#if 0
997                // Convert names
998                int iRow;
999                int numberRows=model2->numberRows();
1000                int iColumn;
1001                int numberColumns=model2->numberColumns();
1002
1003                char ** rowNames = NULL;
1004                char ** columnNames = NULL;
1005                if (model2->lengthNames()) {
1006                  rowNames = new char * [numberRows];
1007                  for (iRow=0;iRow<numberRows;iRow++) {
1008                    rowNames[iRow] =
1009                      strdup(model2->rowName(iRow).c_str());
1010#ifdef STRIPBLANKS
1011                    char * xx = rowNames[iRow];
1012                    int i;
1013                    int length = strlen(xx);
1014                    int n=0;
1015                    for (i=0;i<length;i++) {
1016                      if (xx[i]!=' ')
1017                        xx[n++]=xx[i];
1018                    }
1019                    xx[n]='\0';
1020#endif
1021                  }
1022                 
1023                  columnNames = new char * [numberColumns];
1024                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1025                    columnNames[iColumn] =
1026                      strdup(model2->columnName(iColumn).c_str());
1027#ifdef STRIPBLANKS
1028                    char * xx = columnNames[iColumn];
1029                    int i;
1030                    int length = strlen(xx);
1031                    int n=0;
1032                    for (i=0;i<length;i++) {
1033                      if (xx[i]!=' ')
1034                        xx[n++]=xx[i];
1035                    }
1036                    xx[n]='\0';
1037#endif
1038                  }
1039                }
1040                CoinMpsIO writer;
1041                writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
1042                                  model2->getColLower(), model2->getColUpper(),
1043                                  model2->getObjCoefficients(),
1044                                  (const char*) 0 /*integrality*/,
1045                                  model2->getRowLower(), model2->getRowUpper(),
1046                                  columnNames, rowNames);
1047                // Pass in array saying if each variable integer
1048                writer.copyInIntegerInformation(model2->integerInformation());
1049                writer.setObjectiveOffset(model2->objectiveOffset());
1050                writer.writeMps(fileName.c_str(),0,1,1);
1051                if (rowNames) {
1052                  for (iRow=0;iRow<numberRows;iRow++) {
1053                    free(rowNames[iRow]);
1054                  }
1055                  delete [] rowNames;
1056                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1057                    free(columnNames[iColumn]);
1058                  }
1059                  delete [] columnNames;
1060                }
1061#else
1062                model2->writeMps(fileName.c_str(),(outputFormat-1)/2,1+((outputFormat-1)&1));
1063#endif
1064                if (deleteModel2)
1065                  delete model2;
1066                time2 = CoinCpuTime();
1067                totalTime += time2-time1;
1068                time1=time2;
1069              }
1070            } else {
1071              std::cout<<"** Current model not valid"<<std::endl;
1072            }
1073            break;
1074          case BASISIN:
1075            if (goodModels[iModel]) {
1076              // get next field
1077              field = CoinReadGetString(argc,argv);
1078              if (field=="$") {
1079                field = parameters[iParam].stringValue();
1080              } else if (field=="EOL") {
1081                parameters[iParam].printString();
1082                break;
1083              } else {
1084                parameters[iParam].setStringValue(field);
1085              }
1086              std::string fileName;
1087              bool canOpen=false;
1088              if (field=="-") {
1089                // stdin
1090                canOpen=true;
1091                fileName = "-";
1092              } else {
1093                if (field[0]=='/'||field[0]=='\\') {
1094                  fileName = field;
1095                } else if (field[0]=='~') {
1096                  char * environVar = getenv("HOME");
1097                  if (environVar) {
1098                    std::string home(environVar);
1099                    field=field.erase(0,1);
1100                    fileName = home+field;
1101                  } else {
1102                    fileName=field;
1103                  }
1104                } else {
1105                  fileName = directory+field;
1106                }
1107                FILE *fp=fopen(fileName.c_str(),"r");
1108                if (fp) {
1109                  // can open - lets go for it
1110                  fclose(fp);
1111                  canOpen=true;
1112                } else {
1113                  std::cout<<"Unable to open file "<<fileName<<std::endl;
1114                }
1115              }
1116              if (canOpen) {
1117                int values = models[iModel].readBasis(fileName.c_str());
1118                if (values==0)
1119                  basisHasValues=-1;
1120                else
1121                  basisHasValues=1;
1122              }
1123            } else {
1124              std::cout<<"** Current model not valid"<<std::endl;
1125            }
1126            break;
1127          case PRINTMASK:
1128            // get next field
1129            {
1130              std::string name = CoinReadGetString(argc,argv);
1131              if (name!="EOL") {
1132                parameters[iParam].setStringValue(name);
1133                printMask = name;
1134              } else {
1135                parameters[iParam].printString();
1136              }
1137            }
1138            break;
1139          case BASISOUT:
1140            if (goodModels[iModel]) {
1141              // get next field
1142              field = CoinReadGetString(argc,argv);
1143              if (field=="$") {
1144                field = parameters[iParam].stringValue();
1145              } else if (field=="EOL") {
1146                parameters[iParam].printString();
1147                break;
1148              } else {
1149                parameters[iParam].setStringValue(field);
1150              }
1151              std::string fileName;
1152              bool canOpen=false;
1153              if (field[0]=='/'||field[0]=='\\') {
1154                fileName = field;
1155              } else if (field[0]=='~') {
1156                char * environVar = getenv("HOME");
1157                if (environVar) {
1158                  std::string home(environVar);
1159                  field=field.erase(0,1);
1160                  fileName = home+field;
1161                } else {
1162                  fileName=field;
1163                }
1164              } else {
1165                fileName = directory+field;
1166              }
1167              FILE *fp=fopen(fileName.c_str(),"w");
1168              if (fp) {
1169                // can open - lets go for it
1170                fclose(fp);
1171                canOpen=true;
1172              } else {
1173                std::cout<<"Unable to open file "<<fileName<<std::endl;
1174              }
1175              if (canOpen) {
1176                ClpSimplex * model2 = models+iModel;
1177                model2->writeBasis(fileName.c_str(),outputFormat>1,outputFormat-2);
1178                time2 = CoinCpuTime();
1179                totalTime += time2-time1;
1180                time1=time2;
1181              }
1182            } else {
1183              std::cout<<"** Current model not valid"<<std::endl;
1184            }
1185            break;
1186          case SAVE:
1187            {
1188              // get next field
1189              field = CoinReadGetString(argc,argv);
1190              if (field=="$") {
1191                field = parameters[iParam].stringValue();
1192              } else if (field=="EOL") {
1193                parameters[iParam].printString();
1194                break;
1195              } else {
1196                parameters[iParam].setStringValue(field);
1197              }
1198              std::string fileName;
1199              bool canOpen=false;
1200              if (field[0]=='/'||field[0]=='\\') {
1201                fileName = field;
1202              } else if (field[0]=='~') {
1203                char * environVar = getenv("HOME");
1204                if (environVar) {
1205                  std::string home(environVar);
1206                  field=field.erase(0,1);
1207                  fileName = home+field;
1208                } else {
1209                  fileName=field;
1210                }
1211              } else {
1212                fileName = directory+field;
1213              }
1214              FILE *fp=fopen(fileName.c_str(),"wb");
1215              if (fp) {
1216                // can open - lets go for it
1217                fclose(fp);
1218                canOpen=true;
1219              } else {
1220                std::cout<<"Unable to open file "<<fileName<<std::endl;
1221              }
1222              if (canOpen) {
1223                int status;
1224                // If presolve on then save presolved
1225                bool deleteModel2=false;
1226                ClpSimplex * model2 = models+iModel;
1227                if (preSolve) {
1228                  ClpPresolve pinfo;
1229                  double presolveTolerance = 
1230                    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
1231                  model2 = 
1232                    pinfo.presolvedModel(models[iModel],presolveTolerance,
1233                                         false,preSolve);
1234                  if (model2) {
1235                    printf("Saving presolved model on %s\n",
1236                           fileName.c_str());
1237                    deleteModel2=true;
1238                  } else {
1239                    printf("Presolved model looks infeasible - saving original on %s\n",
1240                           fileName.c_str());
1241                    deleteModel2=false;
1242                    model2 = models+iModel;
1243
1244                  }
1245                } else {
1246                  printf("Saving model on %s\n",
1247                           fileName.c_str());
1248                }
1249                status =model2->saveModel(fileName.c_str());
1250                if (deleteModel2)
1251                  delete model2;
1252                if (!status) {
1253                  goodModels[iModel]=true;
1254                  time2 = CoinCpuTime();
1255                  totalTime += time2-time1;
1256                  time1=time2;
1257                } else {
1258                  // errors
1259                  std::cout<<"There were errors on output"<<std::endl;
1260                }
1261              }
1262            }
1263            break;
1264          case RESTORE:
1265            {
1266              // get next field
1267              field = CoinReadGetString(argc,argv);
1268              if (field=="$") {
1269                field = parameters[iParam].stringValue();
1270              } else if (field=="EOL") {
1271                parameters[iParam].printString();
1272                break;
1273              } else {
1274                parameters[iParam].setStringValue(field);
1275              }
1276              std::string fileName;
1277              bool canOpen=false;
1278              if (field[0]=='/'||field[0]=='\\') {
1279                fileName = field;
1280              } else if (field[0]=='~') {
1281                char * environVar = getenv("HOME");
1282                if (environVar) {
1283                  std::string home(environVar);
1284                  field=field.erase(0,1);
1285                  fileName = home+field;
1286                } else {
1287                  fileName=field;
1288                }
1289              } else {
1290                fileName = directory+field;
1291              }
1292              FILE *fp=fopen(fileName.c_str(),"rb");
1293              if (fp) {
1294                // can open - lets go for it
1295                fclose(fp);
1296                canOpen=true;
1297              } else {
1298                std::cout<<"Unable to open file "<<fileName<<std::endl;
1299              }
1300              if (canOpen) {
1301                int status =models[iModel].restoreModel(fileName.c_str());
1302                if (!status) {
1303                  goodModels[iModel]=true;
1304                  time2 = CoinCpuTime();
1305                  totalTime += time2-time1;
1306                  time1=time2;
1307                } else {
1308                  // errors
1309                  std::cout<<"There were errors on input"<<std::endl;
1310                }
1311              }
1312            }
1313            break;
1314          case MAXIMIZE:
1315            models[iModel].setOptimizationDirection(-1);
1316            break;
1317          case MINIMIZE:
1318            models[iModel].setOptimizationDirection(1);
1319            break;
1320          case ALLSLACK:
1321            models[iModel].allSlackBasis(true);
1322            break;
1323          case REVERSE:
1324            if (goodModels[iModel]) {
1325              int iColumn;
1326              int numberColumns=models[iModel].numberColumns();
1327              double * dualColumnSolution = 
1328                models[iModel].dualColumnSolution();
1329              ClpObjective * obj = models[iModel].objectiveAsObject();
1330              assert(dynamic_cast<ClpLinearObjective *> (obj));
1331              double offset;
1332              double * objective = obj->gradient(NULL,NULL,offset,true);
1333              for (iColumn=0;iColumn<numberColumns;iColumn++) {
1334                dualColumnSolution[iColumn] = -dualColumnSolution[iColumn];
1335                objective[iColumn] = -objective[iColumn];
1336              }
1337              int iRow;
1338              int numberRows=models[iModel].numberRows();
1339              double * dualRowSolution = 
1340                models[iModel].dualRowSolution();
1341              for (iRow=0;iRow<numberRows;iRow++) 
1342                dualRowSolution[iRow] = -dualRowSolution[iRow];
1343              models[iModel].setObjectiveOffset(-models[iModel].objectiveOffset());
1344            }
1345            break;
1346          case DIRECTORY:
1347            {
1348              std::string name = CoinReadGetString(argc,argv);
1349              if (name!="EOL") {
1350                int length=name.length();
1351                if (name[length-1]=='/'||name[length-1]=='\\')
1352                  directory=name;
1353                else
1354                  directory = name+"/";
1355                parameters[iParam].setStringValue(directory);
1356              } else {
1357                parameters[iParam].printString();
1358              }
1359            }
1360            break;
1361          case STDIN:
1362            CbcOrClpRead_mode=-1;
1363            break;
1364          case NETLIB_DUAL:
1365          case NETLIB_EITHER:
1366          case NETLIB_BARRIER:
1367          case NETLIB_PRIMAL:
1368          case NETLIB_TUNE:
1369            {
1370              // create fields for unitTest
1371              const char * fields[4];
1372              int nFields=2;
1373              fields[0]="fake main from unitTest";
1374              fields[1]="-netlib";
1375              if (directory!=defaultDirectory) {
1376                fields[2]="-netlibDir";
1377                fields[3]=directory.c_str();
1378                nFields=4;
1379              }
1380              int algorithm;
1381              if (type==NETLIB_DUAL) {
1382                std::cerr<<"Doing netlib with dual algorithm"<<std::endl;
1383                algorithm =0;
1384              } else if (type==NETLIB_BARRIER) {
1385                std::cerr<<"Doing netlib with barrier algorithm"<<std::endl;
1386                algorithm =2;
1387              } else if (type==NETLIB_EITHER) {
1388                std::cerr<<"Doing netlib with dual or primal algorithm"<<std::endl;
1389                algorithm =3;
1390              } else if (type==NETLIB_TUNE) {
1391                std::cerr<<"Doing netlib with best algorithm!"<<std::endl;
1392                algorithm =5;
1393                // uncomment next to get active tuning
1394                // algorithm=6;
1395              } else {
1396                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
1397                algorithm=1;
1398              }
1399              int specialOptions = models[iModel].specialOptions();
1400              models[iModel].setSpecialOptions(0);
1401              mainTest(nFields,fields,algorithm,models[iModel],
1402                       (preSolve!=0),specialOptions,doVector!=0);
1403            }
1404            break;
1405          case UNITTEST:
1406            {
1407              // create fields for unitTest
1408              const char * fields[3];
1409              int nFields=1;
1410              fields[0]="fake main from unitTest";
1411              if (directory!=defaultDirectory) {
1412                fields[1]="-mpsDir";
1413                fields[2]=directory.c_str();
1414                nFields=3;
1415              }
1416              int specialOptions = models[iModel].specialOptions();
1417              models[iModel].setSpecialOptions(0);
1418              int algorithm=-1;
1419              if (models[iModel].numberRows())
1420                algorithm=7;
1421              mainTest(nFields,fields,algorithm,models[iModel],(preSolve!=0),specialOptions,doVector!=0);
1422            }
1423            break;
1424          case FAKEBOUND:
1425            if (goodModels[iModel]) {
1426              // get bound
1427              double value = CoinReadGetDoubleField(argc,argv,&valid);
1428              if (!valid) {
1429                std::cout<<"Setting "<<parameters[iParam].name()<<
1430                  " to DEBUG "<<value<<std::endl;
1431                int iRow;
1432                int numberRows=models[iModel].numberRows();
1433                double * rowLower = models[iModel].rowLower();
1434                double * rowUpper = models[iModel].rowUpper();
1435                for (iRow=0;iRow<numberRows;iRow++) {
1436                  // leave free ones for now
1437                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
1438                    rowLower[iRow]=CoinMax(rowLower[iRow],-value);
1439                    rowUpper[iRow]=CoinMin(rowUpper[iRow],value);
1440                  }
1441                }
1442                int iColumn;
1443                int numberColumns=models[iModel].numberColumns();
1444                double * columnLower = models[iModel].columnLower();
1445                double * columnUpper = models[iModel].columnUpper();
1446                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1447                  // leave free ones for now
1448                  if (columnLower[iColumn]>-1.0e20||
1449                      columnUpper[iColumn]<1.0e20) {
1450                    columnLower[iColumn]=CoinMax(columnLower[iColumn],-value);
1451                    columnUpper[iColumn]=CoinMin(columnUpper[iColumn],value);
1452                  }
1453                }
1454              } else if (valid==1) {
1455                abort();
1456              } else {
1457                std::cout<<"enter value for "<<parameters[iParam].name()<<
1458                  std::endl;
1459              }
1460            }
1461            break;
1462          case REALLY_SCALE:
1463            if (goodModels[iModel]) {
1464              ClpSimplex newModel(models[iModel],
1465                                  models[iModel].scalingFlag());
1466              printf("model really really scaled\n");
1467              models[iModel]=newModel;
1468            }
1469            break;
1470          case USERCLP:
1471            // Replace the sample code by whatever you want
1472            if (goodModels[iModel]) {
1473              ClpSimplex * thisModel = &models[iModel];
1474              printf("Dummy user code - model has %d rows and %d columns\n",
1475                     thisModel->numberRows(),thisModel->numberColumns());
1476            }
1477            break;
1478          case HELP:
1479            std::cout<<"Coin LP version "<<CLPVERSION
1480                     <<", build "<<__DATE__<<std::endl;
1481            std::cout<<"Non default values:-"<<std::endl;
1482            std::cout<<"Perturbation "<<models[0].perturbation()<<" (default 100)"
1483                     <<std::endl;
1484            CoinReadPrintit(
1485                    "Presolve being done with 5 passes\n\
1486Dual steepest edge steep/partial on matrix shape and factorization density\n\
1487Clpnnnn taken out of messages\n\
1488If Factorization frequency default then done on size of matrix\n\n\
1489(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
1490You can switch to interactive mode at any time so\n\
1491clp watson.mps -scaling off -primalsimplex\nis the same as\n\
1492clp watson.mps -\nscaling off\nprimalsimplex"
1493                    );
1494            break;
1495          case SOLUTION:
1496            if (goodModels[iModel]) {
1497              // get next field
1498              field = CoinReadGetString(argc,argv);
1499              if (field=="$") {
1500                field = parameters[iParam].stringValue();
1501              } else if (field=="EOL") {
1502                parameters[iParam].printString();
1503                break;
1504              } else {
1505                parameters[iParam].setStringValue(field);
1506              }
1507              std::string fileName;
1508              FILE *fp=NULL;
1509              if (field=="-"||field=="EOL"||field=="stdout") {
1510                // stdout
1511                fp=stdout;
1512                fprintf(fp,"\n");
1513              } else if (field=="stderr") {
1514                // stderr
1515                fp=stderr;
1516                fprintf(fp,"\n");
1517              } else {
1518                if (field[0]=='/'||field[0]=='\\') {
1519                  fileName = field;
1520                } else if (field[0]=='~') {
1521                  char * environVar = getenv("HOME");
1522                  if (environVar) {
1523                    std::string home(environVar);
1524                    field=field.erase(0,1);
1525                    fileName = home+field;
1526                  } else {
1527                    fileName=field;
1528                  }
1529                } else {
1530                  fileName = directory+field;
1531                }
1532                fp=fopen(fileName.c_str(),"w");
1533              }
1534              if (fp) {
1535                // make fancy later on
1536                int iRow;
1537                int numberRows=models[iModel].numberRows();
1538                int lengthName = models[iModel].lengthNames(); // 0 if no names
1539                // in general I don't want to pass around massive
1540                // amounts of data but seems simpler here
1541                std::vector<std::string> rowNames =
1542                  *(models[iModel].rowNames());
1543                std::vector<std::string> columnNames =
1544                  *(models[iModel].columnNames());
1545
1546                double * dualRowSolution = models[iModel].dualRowSolution();
1547                double * primalRowSolution = 
1548                  models[iModel].primalRowSolution();
1549                double * rowLower = models[iModel].rowLower();
1550                double * rowUpper = models[iModel].rowUpper();
1551                double primalTolerance = models[iModel].primalTolerance();
1552                char format[6];
1553                sprintf(format,"%%-%ds",CoinMax(lengthName,8));
1554                bool doMask = (printMask!=""&&lengthName);
1555                int * maskStarts=NULL;
1556                int maxMasks=0;
1557                char ** masks =NULL;
1558                if (doMask) {
1559                  int nAst =0;
1560                  const char * pMask2 = printMask.c_str();
1561                  char pMask[100];
1562                  int iChar;
1563                  int lengthMask = strlen(pMask2);
1564                  assert (lengthMask<100);
1565                  if (*pMask2=='"') {
1566                    if (pMask2[lengthMask-1]!='"') {
1567                      printf("mismatched \" in mask %s\n",pMask2);
1568                      break;
1569                    } else {
1570                      strcpy(pMask,pMask2+1);
1571                      *strchr(pMask,'"')='\0';
1572                    }
1573                  } else if (*pMask2=='\'') {
1574                    if (pMask2[lengthMask-1]!='\'') {
1575                      printf("mismatched ' in mask %s\n",pMask2);
1576                      break;
1577                    } else {
1578                      strcpy(pMask,pMask2+1);
1579                      *strchr(pMask,'\'')='\0';
1580                    }
1581                  } else {
1582                    strcpy(pMask,pMask2);
1583                  }
1584                  if (lengthMask>lengthName) {
1585                    printf("mask %s too long - skipping\n",pMask);
1586                    break;
1587                  }
1588                  maxMasks = 1;
1589                  for (iChar=0;iChar<lengthMask;iChar++) {
1590                    if (pMask[iChar]=='*') {
1591                      nAst++;
1592                      maxMasks *= (lengthName+1);
1593                    }
1594                  }
1595                  int nEntries = 1;
1596                  maskStarts = new int[lengthName+2];
1597                  masks = new char * [maxMasks];
1598                  char ** newMasks = new char * [maxMasks];
1599                  int i;
1600                  for (i=0;i<maxMasks;i++) {
1601                    masks[i] = new char[lengthName+1];
1602                    newMasks[i] = new char[lengthName+1];
1603                  }
1604                  strcpy(masks[0],pMask);
1605                  for (int iAst=0;iAst<nAst;iAst++) {
1606                    int nOldEntries = nEntries;
1607                    nEntries=0;
1608                    for (int iEntry = 0;iEntry<nOldEntries;iEntry++) {
1609                      char * oldMask = masks[iEntry];
1610                      char * ast = strchr(oldMask,'*');
1611                      assert (ast);
1612                      int length = strlen(oldMask)-1;
1613                      int nBefore = ast-oldMask;
1614                      int nAfter = length-nBefore;
1615                      // and add null
1616                      nAfter++;
1617                      for (int i=0;i<=lengthName-length;i++) {
1618                        char * maskOut = newMasks[nEntries];
1619                        memcpy(maskOut,oldMask,nBefore);
1620                        for (int k=0;k<i;k++) 
1621                          maskOut[k+nBefore]='?';
1622                        memcpy(maskOut+nBefore+i,ast+1,nAfter);
1623                        nEntries++;
1624                        assert (nEntries<=maxMasks);
1625                      }
1626                    }
1627                    char ** temp = masks;
1628                    masks = newMasks;
1629                    newMasks = temp;
1630                  }
1631                  // Now extend and sort
1632                  int * sort = new int[nEntries];
1633                  for (i=0;i<nEntries;i++) {
1634                    char * maskThis = masks[i];
1635                    int length = strlen(maskThis);
1636                    while (maskThis[length-1]==' ')
1637                      length--;
1638                    maskThis[length]='\0';
1639                    sort[i]=length;
1640                  }
1641                  CoinSort_2(sort,sort+nEntries,masks);
1642                  int lastLength=-1;
1643                  for (i=0;i<nEntries;i++) {
1644                    int length = sort[i];
1645                    while (length>lastLength) 
1646                      maskStarts[++lastLength] = i;
1647                  }
1648                  maskStarts[++lastLength]=nEntries;
1649                  delete [] sort;
1650                  for (i=0;i<maxMasks;i++)
1651                    delete [] newMasks[i];
1652                  delete [] newMasks;
1653                }
1654                if (printMode>2) {
1655                  for (iRow=0;iRow<numberRows;iRow++) {
1656                    int type=printMode-3;
1657                    if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
1658                        primalRowSolution[iRow]<rowLower[iRow]-primalTolerance) {
1659                      fprintf(fp,"** ");
1660                      type=2;
1661                    } else if (fabs(primalRowSolution[iRow])>1.0e-8) {
1662                      type=1;
1663                    } else if (numberRows<50) {
1664                      type=3;
1665                    } 
1666                    if (doMask&&!maskMatches(maskStarts,masks,rowNames[iRow]))
1667                      type=0;
1668                    if (type) {
1669                      fprintf(fp,"%7d ",iRow);
1670                      if (lengthName)
1671                        fprintf(fp,format,rowNames[iRow].c_str());
1672                      fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
1673                              dualRowSolution[iRow]);
1674                    }
1675                  }
1676                }
1677                int iColumn;
1678                int numberColumns=models[iModel].numberColumns();
1679                double * dualColumnSolution = 
1680  models[iModel].dualColumnSolution();
1681                double * primalColumnSolution = 
1682  models[iModel].primalColumnSolution();
1683                double * columnLower = models[iModel].columnLower();
1684                double * columnUpper = models[iModel].columnUpper();
1685                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1686                  int type=(printMode>3) ? 1 : 0;
1687                  if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
1688                      primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance) {
1689                    fprintf(fp,"** ");
1690                    type=2;
1691                  } else if (fabs(primalColumnSolution[iColumn])>1.0e-8) {
1692                    type=1;
1693                  } else if (numberColumns<50) {
1694                    type=3;
1695                  }
1696                  if (doMask&&!maskMatches(maskStarts,masks,
1697                                           columnNames[iColumn]))
1698                    type =0;
1699                  if (type) {
1700                    fprintf(fp,"%7d ",iColumn);
1701                    if (lengthName)
1702                      fprintf(fp,format,columnNames[iColumn].c_str());
1703                    fprintf(fp,"%15.8g        %15.8g\n",
1704                            primalColumnSolution[iColumn],
1705                            dualColumnSolution[iColumn]);
1706                  }
1707                }
1708                if (fp!=stdout)
1709                  fclose(fp);
1710                if (masks) {
1711                  delete [] maskStarts;
1712                  for (int i=0;i<maxMasks;i++)
1713                    delete [] masks[i];
1714                  delete [] masks;
1715                }
1716              } else {
1717                std::cout<<"Unable to open file "<<fileName<<std::endl;
1718              }
1719            } else {
1720              std::cout<<"** Current model not valid"<<std::endl;
1721             
1722            }
1723         
1724            break;
1725          case SAVESOL:
1726            if (goodModels[iModel]) {
1727              // get next field
1728              field = CoinReadGetString(argc,argv);
1729              if (field=="$") {
1730                field = parameters[iParam].stringValue();
1731              } else if (field=="EOL") {
1732                parameters[iParam].printString();
1733                break;
1734              } else {
1735                parameters[iParam].setStringValue(field);
1736              }
1737              std::string fileName;
1738              if (field[0]=='/'||field[0]=='\\') {
1739                fileName = field;
1740              } else if (field[0]=='~') {
1741                char * environVar = getenv("HOME");
1742                if (environVar) {
1743                  std::string home(environVar);
1744                  field=field.erase(0,1);
1745                  fileName = home+field;
1746                } else {
1747                  fileName=field;
1748                }
1749              } else {
1750                fileName = directory+field;
1751              }
1752              saveSolution(models+iModel,fileName);
1753            } else {
1754              std::cout<<"** Current model not valid"<<std::endl;
1755             
1756            }
1757            break;
1758          default:
1759            abort();
1760          }
1761        } 
1762      } else if (!numberMatches) {
1763        std::cout<<"No match for "<<field<<" - ? for list of commands"
1764                 <<std::endl;
1765      } else if (numberMatches==1) {
1766        if (!numberQuery) {
1767          std::cout<<"Short match for "<<field<<" - completion: ";
1768          std::cout<<parameters[firstMatch].matchName()<<std::endl;
1769        } else if (numberQuery) {
1770          std::cout<<parameters[firstMatch].matchName()<<" : ";
1771          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
1772          if (numberQuery>=2) 
1773            parameters[firstMatch].printLongHelp();
1774        }
1775      } else {
1776        if (!numberQuery) 
1777          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
1778                   <<std::endl;
1779        else
1780          std::cout<<"Completions of "<<field<<":"<<std::endl;
1781        for ( iParam=0; iParam<numberParameters; iParam++ ) {
1782          int match = parameters[iParam].matches(field);
1783          if (match&&parameters[iParam].displayThis()) {
1784            std::cout<<parameters[iParam].matchName();
1785            if (numberQuery>=2) 
1786              std::cout<<" : "<<parameters[iParam].shortHelp();
1787            std::cout<<std::endl;
1788          }
1789        }
1790      }
1791    }
1792    delete [] models;
1793    delete [] goodModels;
1794  }
1795  // By now all memory should be freed
1796#ifdef DMALLOC
1797  dmalloc_log_unfreed();
1798  dmalloc_shutdown();
1799#endif
1800  return 0;
1801}   
1802static void breakdown(const char * name, int numberLook, const double * region)
1803{
1804  double range[] = {
1805    -COIN_DBL_MAX,
1806    -1.0e15,-1.0e11,-1.0e8,-1.0e5,-1.0e4,-1.0e3,-1.0e2,-1.0e1,
1807    -1.0,
1808    -1.0e-1,-1.0e-2,-1.0e-3,-1.0e-4,-1.0e-5,-1.0e-8,-1.0e-11,-1.0e-15,
1809    0.0,
1810    1.0e-15,1.0e-11,1.0e-8,1.0e-5,1.0e-4,1.0e-3,1.0e-2,1.0e-1,
1811    1.0,
1812    1.0e1,1.0e2,1.0e3,1.0e4,1.0e5,1.0e8,1.0e11,1.0e15,
1813    COIN_DBL_MAX};
1814  int nRanges = (int) (sizeof(range)/sizeof(double));
1815  int * number = new int[nRanges];
1816  memset(number,0,nRanges*sizeof(int));
1817  int * numberExact = new int[nRanges];
1818  memset(numberExact,0,nRanges*sizeof(int));
1819  int i;
1820  for ( i=0;i<numberLook;i++) {
1821    double value = region[i];
1822    for (int j=0;j<nRanges;j++) {
1823      if (value==range[j]) {
1824        numberExact[j]++;
1825        break;
1826      } else if (value<range[j]) {
1827        number[j]++;
1828        break;
1829      }
1830    }
1831  }
1832  printf("\n%s has %d entries\n",name,numberLook);
1833  for (i=0;i<nRanges;i++) {
1834    if (number[i]) 
1835      printf("%d between %g and %g",number[i],range[i-1],range[i]);
1836    if (numberExact[i]) {
1837      if (number[i])
1838        printf(", ");
1839      printf("%d exactly at %g",numberExact[i],range[i]);
1840    }
1841    if (number[i]+numberExact[i])
1842      printf("\n");
1843  }
1844  delete [] number;
1845  delete [] numberExact;
1846}
1847static void statistics(ClpSimplex * originalModel, ClpSimplex * model)
1848{
1849  int numberColumns = originalModel->numberColumns();
1850  const char * integerInformation  = originalModel->integerInformation(); 
1851  const double * columnLower = originalModel->columnLower();
1852  const double * columnUpper = originalModel->columnUpper();
1853  int numberIntegers=0;
1854  int numberBinary=0;
1855  int iRow,iColumn;
1856  if (integerInformation) {
1857    for (iColumn=0;iColumn<numberColumns;iColumn++) {
1858      if (integerInformation[iColumn]) {
1859        if (columnUpper[iColumn]>columnLower[iColumn]) {
1860          numberIntegers++;
1861          if (columnUpper[iColumn]==0.0&&columnLower[iColumn]==1) 
1862            numberBinary++;
1863        }
1864      }
1865    }
1866  }
1867  numberColumns = model->numberColumns();
1868  int numberRows = model->numberRows();
1869  columnLower = model->columnLower();
1870  columnUpper = model->columnUpper();
1871  const double * rowLower = model->rowLower();
1872  const double * rowUpper = model->rowUpper();
1873  const double * objective = model->objective();
1874  CoinPackedMatrix * matrix = model->matrix();
1875  CoinBigIndex numberElements = matrix->getNumElements();
1876  const int * columnLength = matrix->getVectorLengths();
1877  //const CoinBigIndex * columnStart = matrix->getVectorStarts();
1878  const double * elementByColumn = matrix->getElements();
1879  int * number = new int[numberRows+1];
1880  memset(number,0,(numberRows+1)*sizeof(int));
1881  int numberObjSingletons=0;
1882  /* cType
1883     0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up,
1884     8 0/1
1885  */ 
1886  int cType[9];
1887  std::string cName[]={"0.0->inf,","0.0->up,","lo->inf,","lo->up,","free,","fixed,","-inf->0.0,",
1888                       "-inf->up,","0.0->1.0"};
1889  int nObjective=0;
1890  memset(cType,0,sizeof(cType));
1891  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1892    int length=columnLength[iColumn];
1893    if (length==1&&objective[iColumn])
1894      numberObjSingletons++;
1895    number[length]++;
1896    if (objective[iColumn])
1897      nObjective++;
1898    if (columnLower[iColumn]>-1.0e20) {
1899      if (columnLower[iColumn]==0.0) {
1900        if (columnUpper[iColumn]>1.0e20)
1901          cType[0]++;
1902        else if (columnUpper[iColumn]==1.0)
1903          cType[8]++;
1904        else if (columnUpper[iColumn]==0.0)
1905          cType[5]++;
1906        else
1907          cType[1]++;
1908      } else {
1909        if (columnUpper[iColumn]>1.0e20) 
1910          cType[2]++;
1911        else if (columnUpper[iColumn]==columnLower[iColumn])
1912          cType[5]++;
1913        else
1914          cType[3]++;
1915      }
1916    } else {
1917      if (columnUpper[iColumn]>1.0e20) 
1918        cType[4]++;
1919      else if (columnUpper[iColumn]==0.0) 
1920        cType[6]++;
1921      else
1922        cType[7]++;
1923    }
1924  }
1925  /* rType
1926     0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other,
1927     7 L 0,  8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free
1928  */ 
1929  int rType[13];
1930  std::string rName[]={"E 0.0,","E 1.0,","E -1.0,","E other,","G 0.0,","G 1.0,","G other,",
1931                       "L 0.0,","L 1.0,","L other,","Range 0.0->1.0,","Range other,","Free"};
1932  memset(rType,0,sizeof(rType));
1933  for (iRow=0;iRow<numberRows;iRow++) {
1934    if (rowLower[iRow]>-1.0e20) {
1935      if (rowLower[iRow]==0.0) {
1936        if (rowUpper[iRow]>1.0e20)
1937          rType[4]++;
1938        else if (rowUpper[iRow]==1.0)
1939          rType[10]++;
1940        else if (rowUpper[iRow]==0.0)
1941          rType[0]++;
1942        else
1943          rType[11]++;
1944      } else if (rowLower[iRow]==1.0) {
1945        if (rowUpper[iRow]>1.0e20) 
1946          rType[5]++;
1947        else if (rowUpper[iRow]==rowLower[iRow])
1948          rType[1]++;
1949        else
1950          rType[11]++;
1951      } else if (rowLower[iRow]==-1.0) {
1952        if (rowUpper[iRow]>1.0e20) 
1953          rType[6]++;
1954        else if (rowUpper[iRow]==rowLower[iRow])
1955          rType[2]++;
1956        else
1957          rType[11]++;
1958      } else {
1959        if (rowUpper[iRow]>1.0e20) 
1960          rType[6]++;
1961        else if (rowUpper[iRow]==rowLower[iRow])
1962          rType[3]++;
1963        else
1964          rType[11]++;
1965      }
1966    } else {
1967      if (rowUpper[iRow]>1.0e20) 
1968        rType[12]++;
1969      else if (rowUpper[iRow]==0.0) 
1970        rType[7]++;
1971      else if (rowUpper[iRow]==1.0) 
1972        rType[8]++;
1973      else
1974        rType[9]++;
1975    }
1976  }
1977  // Basic statistics
1978  printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n",
1979         numberRows,numberColumns,nObjective,numberElements);
1980  if (number[0]+number[1]) {
1981    printf("There are ");
1982    if (numberObjSingletons)
1983      printf("%d singletons with objective ",numberObjSingletons);
1984    int numberNoObj = number[1]-numberObjSingletons;
1985    if (numberNoObj)
1986      printf("%d singletons with no objective ",numberNoObj);
1987    if (number[0])
1988      printf("** %d columns have no entries",number[0]);
1989    printf("\n");
1990  }
1991  printf("Column breakdown:\n");
1992  int k;
1993  for (k=0;k<(int) (sizeof(cType)/sizeof(int));k++) {
1994    printf("%d of type %s ",cType[k],cName[k].c_str());
1995    if (((k+1)%3)==0)
1996      printf("\n");
1997  }
1998  if ((k%3)!=0)
1999    printf("\n");
2000  printf("Row breakdown:\n");
2001  for (k=0;k<(int) (sizeof(rType)/sizeof(int));k++) {
2002    printf("%d of type %s ",rType[k],rName[k].c_str());
2003    if (((k+1)%3)==0)
2004      printf("\n");
2005  }
2006  if ((k%3)!=0)
2007    printf("\n");
2008  if (model->logLevel()<2)
2009    return ;
2010  int kMax = model->logLevel()>3 ? 1000000 : 10;
2011  k=0;
2012  for (iRow=1;iRow<=numberRows;iRow++) {
2013    if (number[iRow]) {
2014      k++;
2015      printf("%d columns have %d entries\n",number[iRow],iRow);
2016      if (k==kMax)
2017        break;
2018    }
2019  }
2020  if (k<numberRows) {
2021    int kk=k;
2022    k=0;
2023    for (iRow=numberRows;iRow>=1;iRow--) {
2024      if (number[iRow]) {
2025        k++;
2026        if (k==kMax)
2027          break;
2028      }
2029    }
2030    if (k>kk) {
2031      printf("\n    .........\n\n");
2032      iRow=k;
2033      k=0;
2034      for (;iRow<numberRows;iRow++) {
2035        if (number[iRow]) {
2036          k++;
2037          printf("%d columns have %d entries\n",number[iRow],iRow);
2038          if (k==kMax)
2039            break;
2040        }
2041      }
2042    }
2043  }
2044  delete [] number;
2045  printf("\n\n");
2046  // get row copy
2047  CoinPackedMatrix rowCopy = *matrix;
2048  rowCopy.reverseOrdering();
2049  //const int * column = rowCopy.getIndices();
2050  const int * rowLength = rowCopy.getVectorLengths();
2051  //const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
2052  //const double * element = rowCopy.getElements();
2053  number = new int[numberColumns+1];
2054  memset(number,0,(numberColumns+1)*sizeof(int));
2055  for (iRow=0;iRow<numberRows;iRow++) {
2056    int length=rowLength[iRow];
2057    number[length]++;
2058  }
2059  if (number[0])
2060    printf("** %d rows have no entries\n",number[0]);
2061  k=0;
2062  for (iColumn=1;iColumn<=numberColumns;iColumn++) {
2063    if (number[iColumn]) {
2064      k++;
2065      printf("%d rows have %d entries\n",number[iColumn],iColumn);
2066      if (k==kMax)
2067        break;
2068    }
2069  }
2070  if (k<numberColumns) {
2071    int kk=k;
2072    k=0;
2073    for (iColumn=numberColumns;iColumn>=1;iColumn--) {
2074      if (number[iColumn]) {
2075        k++;
2076        if (k==kMax)
2077          break;
2078      }
2079    }
2080    if (k>kk) {
2081      printf("\n    .........\n\n");
2082      iColumn=k;
2083      k=0;
2084      for (;iColumn<numberColumns;iColumn++) {
2085        if (number[iColumn]) {
2086          k++;
2087          printf("%d rows have %d entries\n",number[iColumn],iColumn);
2088          if (k==kMax)
2089            break;
2090        }
2091      }
2092    }
2093  }
2094  delete [] number;
2095  // Now do breakdown of ranges
2096  breakdown("Elements",numberElements,elementByColumn);
2097  breakdown("RowLower",numberRows,rowLower);
2098  breakdown("RowUpper",numberRows,rowUpper);
2099  breakdown("ColumnLower",numberColumns,columnLower);
2100  breakdown("ColumnUpper",numberColumns,columnUpper);
2101  breakdown("Objective",numberColumns,objective);
2102}
2103static bool maskMatches(const int * starts, char ** masks,
2104                        std::string & check)
2105{
2106  // back to char as I am old fashioned
2107  const char * checkC = check.c_str();
2108  int length = strlen(checkC);
2109  while (checkC[length-1]==' ')
2110    length--;
2111  for (int i=starts[length];i<starts[length+1];i++) {
2112    char * thisMask = masks[i];
2113    int k;
2114    for ( k=0;k<length;k++) {
2115      if (thisMask[k]!='?'&&thisMask[k]!=checkC[k]) 
2116        break;
2117    }
2118    if (k==length)
2119      return true;
2120  }
2121  return false;
2122}
2123static void clean(char * temp)
2124{
2125  char * put = temp;
2126  while (*put>=' ')
2127    put++;
2128  *put='\0';
2129}
2130static void generateCode(const char * fileName,int type)
2131{
2132  FILE * fp = fopen(fileName,"r");
2133  assert (fp);
2134  int numberLines=0;
2135#define MAXLINES 500
2136#define MAXONELINE 200
2137  char line[MAXLINES][MAXONELINE];
2138  while (fgets(line[numberLines],MAXONELINE,fp)) {
2139    assert (numberLines<MAXLINES);
2140    clean(line[numberLines]);
2141    numberLines++;
2142  }
2143  fclose(fp);
2144  // add in actual solve
2145  strcpy(line[numberLines],"5  clpModel->initialSolve(clpSolve);");
2146  numberLines++;
2147  fp = fopen(fileName,"w");
2148  assert (fp);
2149  char apo='"';   
2150  char backslash = '\\';
2151
2152  fprintf(fp,"#include %cClpSimplex.hpp%c\n",apo,apo);
2153  fprintf(fp,"#include %cClpSolve.hpp%c\n",apo,apo);
2154
2155  fprintf(fp,"\nint main (int argc, const char *argv[])\n{\n");
2156  fprintf(fp,"  ClpSimplex  model;\n");
2157  fprintf(fp,"  int status=1;\n");
2158  fprintf(fp,"  if (argc<2)\n");
2159  fprintf(fp,"    fprintf(stderr,%cPlease give file name%cn%c);\n",
2160          apo,backslash,apo);
2161  fprintf(fp,"  else\n");
2162  fprintf(fp,"    status=model.readMps(argv[1],true);\n");
2163  fprintf(fp,"  if (status) {\n");
2164  fprintf(fp,"    fprintf(stderr,%cBad readMps %%s%cn%c,argv[1]);\n",
2165                apo,backslash,apo);
2166  fprintf(fp,"    exit(1);\n");
2167  fprintf(fp,"  }\n\n");
2168  fprintf(fp,"  // Now do requested saves and modifications\n");
2169  fprintf(fp,"  ClpSimplex * clpModel = & model;\n");
2170  int wanted[9];
2171  memset(wanted,0,sizeof(wanted));
2172  wanted[0]=wanted[3]=wanted[5]=wanted[8]=1;
2173  if (type>0) 
2174    wanted[1]=wanted[6]=1;
2175  if (type>1) 
2176    wanted[2]=wanted[4]=wanted[7]=1;
2177  std::string header[9]=
2178  { "","Save values","Redundant save of default values","Set changed values",
2179    "Redundant set default values","Solve","Restore values","Redundant restore values","Add to model"};
2180  for (int iType=0;iType<9;iType++) {
2181    if (!wanted[iType])
2182      continue;
2183    int n=0;
2184    int iLine;
2185    for (iLine=0;iLine<numberLines;iLine++) {
2186      if (line[iLine][0]=='0'+iType) {
2187        if (!n)
2188          fprintf(fp,"\n  // %s\n\n",header[iType].c_str());
2189        n++;
2190        fprintf(fp,"%s\n",line[iLine]+1);
2191      }
2192    }
2193  }
2194  fprintf(fp,"\n  // Now you would use solution etc etc\n\n");
2195  fprintf(fp,"  return 0;\n}\n");
2196  fclose(fp);
2197  printf("C++ file written to %s\n",fileName);
2198}
2199/*
2200  Version 1.00.00 October 13 2004.
2201  1.00.01 October 18.  Added basis handling helped/prodded by Thorsten Koch.
2202  Also modifications to make faster with sbb (I hope I haven't broken anything).
2203  1.00.02 March 21 2005.  Redid ClpNonLinearCost to save memory also redid
2204  createRim to try and improve cache characteristics.
2205  1.00.03 April 8 2005.  Added Volume algorithm as crash and made code more
2206  robust on testing.  Also added "either" and "tune" algorithm.
2207  1.01.01 April 12 2005.  Decided to go to different numbering.  Backups will
2208  be last 2 digits while middle 2 are for improvements.  Still take a long
2209  time to get to 2.00.01
2210  1.01.02 May 4 2005.  Will be putting in many changes - so saving stable version
2211  1.02.01 May 6 2005.  Lots of changes to try and make faster and more stable in
2212  branch and cut.
2213  1.02.02 May 19 2005.  Stuff for strong branching and some improvements to simplex
2214  1.03.01 May 24 2006.  Lots done but I can't remember what!
2215  1.03.03 June 13 2006.  For clean up after dual perturbation
2216 */
Note: See TracBrowser for help on using the repository browser.