source: branches/devel/Clp/src/ClpMain.cpp @ 989

Last change on this file since 989 was 989, checked in by forrest, 14 years ago

this may be a mistake

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.0 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)
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                bool absolutePath;
797                if (dirsep=='/') {
798                  // non Windows (or cygwin)
799                  absolutePath=(field[0]=='/');
800                } else {
801                  //Windows (non cycgwin)
802                  absolutePath=(field[0]=='\\');
803                  // but allow for :
804                  if (strchr(field.c_str(),':'))
805                    absolutePath=true;
806                }
807                if (absolutePath) {
808                  fileName = field;
809                } else if (field[0]=='~') {
810                  char * environVar = getenv("HOME");
811                  if (environVar) {
812                    std::string home(environVar);
813                    field=field.erase(0,1);
814                    fileName = home+field;
815                  } else {
816                    fileName=field;
817                  }
818                } else {
819                  fileName = directory+field;
820                  // See if gmpl (model & data)
821                  int length = field.size();
822                  int percent = field.find('%');
823                  if (percent<length&&percent>0) {
824                    gmpl=1;
825                    fileName = directory+field.substr(0,percent);
826                    gmplData = directory+field.substr(percent+1);
827                    if (percent<length-1)
828                      gmpl=2; // two files
829                    printf("GMPL model file %s and data file %s\n",
830                           fileName.c_str(),gmplData.c_str());
831                  }
832                }
833                std::string name=fileName;
834                if (fileCoinReadable(name)) {
835                  // can open - lets go for it
836                  canOpen=true;
837                  if (gmpl==2) {
838                    FILE *fp;
839                    fp=fopen(gmplData.c_str(),"r");
840                    if (fp) {
841                      fclose(fp);
842                    } else {
843                      canOpen=false;
844                      std::cout<<"Unable to open file "<<gmplData<<std::endl;
845                    }
846                  }
847                } else {
848                  std::cout<<"Unable to open file "<<fileName<<std::endl;
849                }
850              }
851              if (canOpen) {
852                int status;
853                if (!gmpl)
854                  status =models[iModel].readMps(fileName.c_str(),
855                                                 keepImportNames!=0,
856                                                 allowImportErrors!=0);
857                else
858                  status= models[iModel].readGMPL(fileName.c_str(),
859                                                  (gmpl==2) ? gmplData.c_str() : NULL,
860                                                  keepImportNames!=0);
861                if (!status||(status>0&&allowImportErrors)) {
862                  goodModels[iModel]=true;
863                  // sets to all slack (not necessary?)
864                  models[iModel].createStatus();
865                  time2 = CoinCpuTime();
866                  totalTime += time2-time1;
867                  time1=time2;
868                  // Go to canned file if just input file
869                  if (CbcOrClpRead_mode==2&&argc==2) {
870                    // only if ends .mps
871                    char * find = (char *)strstr(fileName.c_str(),".mps");
872                    if (find&&find[4]=='\0') {
873                      find[1]='p'; find[2]='a';find[3]='r';
874                      FILE *fp=fopen(fileName.c_str(),"r");
875                      if (fp) {
876                        CbcOrClpReadCommand=fp; // Read from that file
877                        CbcOrClpRead_mode=-1;
878                      }
879                    }
880                  }
881                } else {
882                  // errors
883                  std::cout<<"There were "<<status<<
884                    " errors on input"<<std::endl;
885                }
886              }
887            }
888            break;
889          case EXPORT:
890            if (goodModels[iModel]) {
891              double objScale = 
892                parameters[whichParam(OBJSCALE2,numberParameters,parameters)].doubleValue();
893              if (objScale!=1.0) {
894                int iColumn;
895                int numberColumns=models[iModel].numberColumns();
896                double * dualColumnSolution = 
897                  models[iModel].dualColumnSolution();
898                ClpObjective * obj = models[iModel].objectiveAsObject();
899                assert(dynamic_cast<ClpLinearObjective *> (obj));
900                double offset;
901                double * objective = obj->gradient(NULL,NULL,offset,true);
902                for (iColumn=0;iColumn<numberColumns;iColumn++) {
903                  dualColumnSolution[iColumn] *= objScale;
904                  objective[iColumn] *= objScale;;
905                }
906                int iRow;
907                int numberRows=models[iModel].numberRows();
908                double * dualRowSolution = 
909                  models[iModel].dualRowSolution();
910                for (iRow=0;iRow<numberRows;iRow++) 
911                  dualRowSolution[iRow] *= objScale;
912                models[iModel].setObjectiveOffset(objScale*models[iModel].objectiveOffset());
913              }
914              // get next field
915              field = CoinReadGetString(argc,argv);
916              if (field=="$") {
917                field = parameters[iParam].stringValue();
918              } else if (field=="EOL") {
919                parameters[iParam].printString();
920                break;
921              } else {
922                parameters[iParam].setStringValue(field);
923              }
924              std::string fileName;
925              bool canOpen=false;
926              if (field[0]=='/'||field[0]=='\\') {
927                fileName = field;
928              } else if (field[0]=='~') {
929                char * environVar = getenv("HOME");
930                if (environVar) {
931                  std::string home(environVar);
932                  field=field.erase(0,1);
933                  fileName = home+field;
934                } else {
935                  fileName=field;
936                }
937              } else {
938                fileName = directory+field;
939              }
940              FILE *fp=fopen(fileName.c_str(),"w");
941              if (fp) {
942                // can open - lets go for it
943                fclose(fp);
944                canOpen=true;
945              } else {
946                std::cout<<"Unable to open file "<<fileName<<std::endl;
947              }
948              if (canOpen) {
949                // If presolve on then save presolved
950                bool deleteModel2=false;
951                ClpSimplex * model2 = models+iModel;
952                if (dualize) {
953                  model2 = ((ClpSimplexOther *) model2)->dualOfModel();
954                  printf("Dual of model has %d rows and %d columns\n",
955                         model2->numberRows(),model2->numberColumns());
956                  model2->setOptimizationDirection(1.0);
957                  preSolve=0; // as picks up from model
958                }
959                if (preSolve) {
960                  ClpPresolve pinfo;
961                  int presolveOptions2 = presolveOptions&~0x40000000;
962                  if ((presolveOptions2&0xffff)!=0)
963                    pinfo.setPresolveActions(presolveOptions2);
964                  pinfo.setSubstitution(substitution);
965                  if ((printOptions&1)!=0)
966                    pinfo.statistics();
967                  double presolveTolerance = 
968                    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
969                  model2 = 
970                    pinfo.presolvedModel(models[iModel],presolveTolerance,
971                                         true,preSolve,false,false);
972                  if (model2) {
973                    printf("Saving presolved model on %s\n",
974                           fileName.c_str());
975                    deleteModel2=true;
976                  } else {
977                    printf("Presolved model looks infeasible - saving original on %s\n",
978                           fileName.c_str());
979                    deleteModel2=false;
980                    model2 = models+iModel;
981
982                  }
983                } else {
984                  printf("Saving model on %s\n",
985                           fileName.c_str());
986                }
987#if 0
988                // Convert names
989                int iRow;
990                int numberRows=model2->numberRows();
991                int iColumn;
992                int numberColumns=model2->numberColumns();
993
994                char ** rowNames = NULL;
995                char ** columnNames = NULL;
996                if (model2->lengthNames()) {
997                  rowNames = new char * [numberRows];
998                  for (iRow=0;iRow<numberRows;iRow++) {
999                    rowNames[iRow] =
1000                      strdup(model2->rowName(iRow).c_str());
1001#ifdef STRIPBLANKS
1002                    char * xx = rowNames[iRow];
1003                    int i;
1004                    int length = strlen(xx);
1005                    int n=0;
1006                    for (i=0;i<length;i++) {
1007                      if (xx[i]!=' ')
1008                        xx[n++]=xx[i];
1009                    }
1010                    xx[n]='\0';
1011#endif
1012                  }
1013                 
1014                  columnNames = new char * [numberColumns];
1015                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1016                    columnNames[iColumn] =
1017                      strdup(model2->columnName(iColumn).c_str());
1018#ifdef STRIPBLANKS
1019                    char * xx = columnNames[iColumn];
1020                    int i;
1021                    int length = strlen(xx);
1022                    int n=0;
1023                    for (i=0;i<length;i++) {
1024                      if (xx[i]!=' ')
1025                        xx[n++]=xx[i];
1026                    }
1027                    xx[n]='\0';
1028#endif
1029                  }
1030                }
1031                CoinMpsIO writer;
1032                writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
1033                                  model2->getColLower(), model2->getColUpper(),
1034                                  model2->getObjCoefficients(),
1035                                  (const char*) 0 /*integrality*/,
1036                                  model2->getRowLower(), model2->getRowUpper(),
1037                                  columnNames, rowNames);
1038                // Pass in array saying if each variable integer
1039                writer.copyInIntegerInformation(model2->integerInformation());
1040                writer.setObjectiveOffset(model2->objectiveOffset());
1041                writer.writeMps(fileName.c_str(),0,1,1);
1042                if (rowNames) {
1043                  for (iRow=0;iRow<numberRows;iRow++) {
1044                    free(rowNames[iRow]);
1045                  }
1046                  delete [] rowNames;
1047                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1048                    free(columnNames[iColumn]);
1049                  }
1050                  delete [] columnNames;
1051                }
1052#else
1053                if (dualize) {
1054                  ClpSimplex * model3 = ((ClpSimplexOther *) model2)->dualOfModel();
1055                  printf("Dual of model has %d rows and %d columns\n",
1056                         model3->numberRows(),model3->numberColumns());
1057                  model3->writeMps(fileName.c_str(),(outputFormat-1)/2,1+((outputFormat-1)&1));
1058                  delete model3;
1059                } else {
1060                  model2->writeMps(fileName.c_str(),(outputFormat-1)/2,1+((outputFormat-1)&1));
1061                }
1062#endif
1063                if (deleteModel2)
1064                  delete model2;
1065                time2 = CoinCpuTime();
1066                totalTime += time2-time1;
1067                time1=time2;
1068              }
1069            } else {
1070              std::cout<<"** Current model not valid"<<std::endl;
1071            }
1072            break;
1073          case BASISIN:
1074            if (goodModels[iModel]) {
1075              // get next field
1076              field = CoinReadGetString(argc,argv);
1077              if (field=="$") {
1078                field = parameters[iParam].stringValue();
1079              } else if (field=="EOL") {
1080                parameters[iParam].printString();
1081                break;
1082              } else {
1083                parameters[iParam].setStringValue(field);
1084              }
1085              std::string fileName;
1086              bool canOpen=false;
1087              if (field=="-") {
1088                // stdin
1089                canOpen=true;
1090                fileName = "-";
1091              } else {
1092                if (field[0]=='/'||field[0]=='\\') {
1093                  fileName = field;
1094                } else if (field[0]=='~') {
1095                  char * environVar = getenv("HOME");
1096                  if (environVar) {
1097                    std::string home(environVar);
1098                    field=field.erase(0,1);
1099                    fileName = home+field;
1100                  } else {
1101                    fileName=field;
1102                  }
1103                } else {
1104                  fileName = directory+field;
1105                }
1106                FILE *fp=fopen(fileName.c_str(),"r");
1107                if (fp) {
1108                  // can open - lets go for it
1109                  fclose(fp);
1110                  canOpen=true;
1111                } else {
1112                  std::cout<<"Unable to open file "<<fileName<<std::endl;
1113                }
1114              }
1115              if (canOpen) {
1116                int values = models[iModel].readBasis(fileName.c_str());
1117                if (values==0)
1118                  basisHasValues=-1;
1119                else
1120                  basisHasValues=1;
1121              }
1122            } else {
1123              std::cout<<"** Current model not valid"<<std::endl;
1124            }
1125            break;
1126          case PRINTMASK:
1127            // get next field
1128            {
1129              std::string name = CoinReadGetString(argc,argv);
1130              if (name!="EOL") {
1131                parameters[iParam].setStringValue(name);
1132                printMask = name;
1133              } else {
1134                parameters[iParam].printString();
1135              }
1136            }
1137            break;
1138          case BASISOUT:
1139            if (goodModels[iModel]) {
1140              // get next field
1141              field = CoinReadGetString(argc,argv);
1142              if (field=="$") {
1143                field = parameters[iParam].stringValue();
1144              } else if (field=="EOL") {
1145                parameters[iParam].printString();
1146                break;
1147              } else {
1148                parameters[iParam].setStringValue(field);
1149              }
1150              std::string fileName;
1151              bool canOpen=false;
1152              if (field[0]=='/'||field[0]=='\\') {
1153                fileName = field;
1154              } else if (field[0]=='~') {
1155                char * environVar = getenv("HOME");
1156                if (environVar) {
1157                  std::string home(environVar);
1158                  field=field.erase(0,1);
1159                  fileName = home+field;
1160                } else {
1161                  fileName=field;
1162                }
1163              } else {
1164                fileName = directory+field;
1165              }
1166              FILE *fp=fopen(fileName.c_str(),"w");
1167              if (fp) {
1168                // can open - lets go for it
1169                fclose(fp);
1170                canOpen=true;
1171              } else {
1172                std::cout<<"Unable to open file "<<fileName<<std::endl;
1173              }
1174              if (canOpen) {
1175                ClpSimplex * model2 = models+iModel;
1176                model2->writeBasis(fileName.c_str(),outputFormat>1,outputFormat-2);
1177                time2 = CoinCpuTime();
1178                totalTime += time2-time1;
1179                time1=time2;
1180              }
1181            } else {
1182              std::cout<<"** Current model not valid"<<std::endl;
1183            }
1184            break;
1185          case SAVE:
1186            {
1187              // get next field
1188              field = CoinReadGetString(argc,argv);
1189              if (field=="$") {
1190                field = parameters[iParam].stringValue();
1191              } else if (field=="EOL") {
1192                parameters[iParam].printString();
1193                break;
1194              } else {
1195                parameters[iParam].setStringValue(field);
1196              }
1197              std::string fileName;
1198              bool canOpen=false;
1199              if (field[0]=='/'||field[0]=='\\') {
1200                fileName = field;
1201              } else if (field[0]=='~') {
1202                char * environVar = getenv("HOME");
1203                if (environVar) {
1204                  std::string home(environVar);
1205                  field=field.erase(0,1);
1206                  fileName = home+field;
1207                } else {
1208                  fileName=field;
1209                }
1210              } else {
1211                fileName = directory+field;
1212              }
1213              FILE *fp=fopen(fileName.c_str(),"wb");
1214              if (fp) {
1215                // can open - lets go for it
1216                fclose(fp);
1217                canOpen=true;
1218              } else {
1219                std::cout<<"Unable to open file "<<fileName<<std::endl;
1220              }
1221              if (canOpen) {
1222                int status;
1223                // If presolve on then save presolved
1224                bool deleteModel2=false;
1225                ClpSimplex * model2 = models+iModel;
1226                if (preSolve) {
1227                  ClpPresolve pinfo;
1228                  double presolveTolerance = 
1229                    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
1230                  model2 = 
1231                    pinfo.presolvedModel(models[iModel],presolveTolerance,
1232                                         false,preSolve);
1233                  if (model2) {
1234                    printf("Saving presolved model on %s\n",
1235                           fileName.c_str());
1236                    deleteModel2=true;
1237                  } else {
1238                    printf("Presolved model looks infeasible - saving original on %s\n",
1239                           fileName.c_str());
1240                    deleteModel2=false;
1241                    model2 = models+iModel;
1242
1243                  }
1244                } else {
1245                  printf("Saving model on %s\n",
1246                           fileName.c_str());
1247                }
1248                status =model2->saveModel(fileName.c_str());
1249                if (deleteModel2)
1250                  delete model2;
1251                if (!status) {
1252                  goodModels[iModel]=true;
1253                  time2 = CoinCpuTime();
1254                  totalTime += time2-time1;
1255                  time1=time2;
1256                } else {
1257                  // errors
1258                  std::cout<<"There were errors on output"<<std::endl;
1259                }
1260              }
1261            }
1262            break;
1263          case RESTORE:
1264            {
1265              // get next field
1266              field = CoinReadGetString(argc,argv);
1267              if (field=="$") {
1268                field = parameters[iParam].stringValue();
1269              } else if (field=="EOL") {
1270                parameters[iParam].printString();
1271                break;
1272              } else {
1273                parameters[iParam].setStringValue(field);
1274              }
1275              std::string fileName;
1276              bool canOpen=false;
1277              if (field[0]=='/'||field[0]=='\\') {
1278                fileName = field;
1279              } else if (field[0]=='~') {
1280                char * environVar = getenv("HOME");
1281                if (environVar) {
1282                  std::string home(environVar);
1283                  field=field.erase(0,1);
1284                  fileName = home+field;
1285                } else {
1286                  fileName=field;
1287                }
1288              } else {
1289                fileName = directory+field;
1290              }
1291              FILE *fp=fopen(fileName.c_str(),"rb");
1292              if (fp) {
1293                // can open - lets go for it
1294                fclose(fp);
1295                canOpen=true;
1296              } else {
1297                std::cout<<"Unable to open file "<<fileName<<std::endl;
1298              }
1299              if (canOpen) {
1300                int status =models[iModel].restoreModel(fileName.c_str());
1301                if (!status) {
1302                  goodModels[iModel]=true;
1303                  time2 = CoinCpuTime();
1304                  totalTime += time2-time1;
1305                  time1=time2;
1306                } else {
1307                  // errors
1308                  std::cout<<"There were errors on input"<<std::endl;
1309                }
1310              }
1311            }
1312            break;
1313          case MAXIMIZE:
1314            models[iModel].setOptimizationDirection(-1);
1315            break;
1316          case MINIMIZE:
1317            models[iModel].setOptimizationDirection(1);
1318            break;
1319          case ALLSLACK:
1320            models[iModel].allSlackBasis(true);
1321            break;
1322          case REVERSE:
1323            if (goodModels[iModel]) {
1324              int iColumn;
1325              int numberColumns=models[iModel].numberColumns();
1326              double * dualColumnSolution = 
1327                models[iModel].dualColumnSolution();
1328              ClpObjective * obj = models[iModel].objectiveAsObject();
1329              assert(dynamic_cast<ClpLinearObjective *> (obj));
1330              double offset;
1331              double * objective = obj->gradient(NULL,NULL,offset,true);
1332              for (iColumn=0;iColumn<numberColumns;iColumn++) {
1333                dualColumnSolution[iColumn] = -dualColumnSolution[iColumn];
1334                objective[iColumn] = -objective[iColumn];
1335              }
1336              int iRow;
1337              int numberRows=models[iModel].numberRows();
1338              double * dualRowSolution = 
1339                models[iModel].dualRowSolution();
1340              for (iRow=0;iRow<numberRows;iRow++) 
1341                dualRowSolution[iRow] = -dualRowSolution[iRow];
1342              models[iModel].setObjectiveOffset(-models[iModel].objectiveOffset());
1343            }
1344            break;
1345          case DIRECTORY:
1346            {
1347              std::string name = CoinReadGetString(argc,argv);
1348              if (name!="EOL") {
1349                int length=name.length();
1350                if (name[length-1]=='/'||name[length-1]=='\\')
1351                  directory=name;
1352                else
1353                  directory = name+"/";
1354                parameters[iParam].setStringValue(directory);
1355              } else {
1356                parameters[iParam].printString();
1357              }
1358            }
1359            break;
1360          case STDIN:
1361            CbcOrClpRead_mode=-1;
1362            break;
1363          case NETLIB_DUAL:
1364          case NETLIB_EITHER:
1365          case NETLIB_BARRIER:
1366          case NETLIB_PRIMAL:
1367          case NETLIB_TUNE:
1368            {
1369              // create fields for unitTest
1370              const char * fields[4];
1371              int nFields=2;
1372              fields[0]="fake main from unitTest";
1373              fields[1]="-netlib";
1374              if (directory!=defaultDirectory) {
1375                fields[2]="-netlibDir";
1376                fields[3]=directory.c_str();
1377                nFields=4;
1378              }
1379              int algorithm;
1380              if (type==NETLIB_DUAL) {
1381                std::cerr<<"Doing netlib with dual algorithm"<<std::endl;
1382                algorithm =0;
1383              } else if (type==NETLIB_BARRIER) {
1384                std::cerr<<"Doing netlib with barrier algorithm"<<std::endl;
1385                algorithm =2;
1386              } else if (type==NETLIB_EITHER) {
1387                std::cerr<<"Doing netlib with dual or primal algorithm"<<std::endl;
1388                algorithm =3;
1389              } else if (type==NETLIB_TUNE) {
1390                std::cerr<<"Doing netlib with best algorithm!"<<std::endl;
1391                algorithm =5;
1392                // uncomment next to get active tuning
1393                // algorithm=6;
1394              } else {
1395                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
1396                algorithm=1;
1397              }
1398              int specialOptions = models[iModel].specialOptions();
1399              models[iModel].setSpecialOptions(0);
1400              mainTest(nFields,fields,algorithm,models[iModel],
1401                       (preSolve!=0),specialOptions,doVector!=0);
1402            }
1403            break;
1404          case UNITTEST:
1405            {
1406              // create fields for unitTest
1407              const char * fields[3];
1408              int nFields=1;
1409              fields[0]="fake main from unitTest";
1410              if (directory!=defaultDirectory) {
1411                fields[1]="-mpsDir";
1412                fields[2]=directory.c_str();
1413                nFields=3;
1414              }
1415              int specialOptions = models[iModel].specialOptions();
1416              models[iModel].setSpecialOptions(0);
1417              int algorithm=-1;
1418              if (models[iModel].numberRows())
1419                algorithm=7;
1420              mainTest(nFields,fields,algorithm,models[iModel],(preSolve!=0),specialOptions,doVector!=0);
1421            }
1422            break;
1423          case FAKEBOUND:
1424            if (goodModels[iModel]) {
1425              // get bound
1426              double value = CoinReadGetDoubleField(argc,argv,&valid);
1427              if (!valid) {
1428                std::cout<<"Setting "<<parameters[iParam].name()<<
1429                  " to DEBUG "<<value<<std::endl;
1430                int iRow;
1431                int numberRows=models[iModel].numberRows();
1432                double * rowLower = models[iModel].rowLower();
1433                double * rowUpper = models[iModel].rowUpper();
1434                for (iRow=0;iRow<numberRows;iRow++) {
1435                  // leave free ones for now
1436                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
1437                    rowLower[iRow]=CoinMax(rowLower[iRow],-value);
1438                    rowUpper[iRow]=CoinMin(rowUpper[iRow],value);
1439                  }
1440                }
1441                int iColumn;
1442                int numberColumns=models[iModel].numberColumns();
1443                double * columnLower = models[iModel].columnLower();
1444                double * columnUpper = models[iModel].columnUpper();
1445                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1446                  // leave free ones for now
1447                  if (columnLower[iColumn]>-1.0e20||
1448                      columnUpper[iColumn]<1.0e20) {
1449                    columnLower[iColumn]=CoinMax(columnLower[iColumn],-value);
1450                    columnUpper[iColumn]=CoinMin(columnUpper[iColumn],value);
1451                  }
1452                }
1453              } else if (valid==1) {
1454                abort();
1455              } else {
1456                std::cout<<"enter value for "<<parameters[iParam].name()<<
1457                  std::endl;
1458              }
1459            }
1460            break;
1461          case REALLY_SCALE:
1462            if (goodModels[iModel]) {
1463              ClpSimplex newModel(models[iModel],
1464                                  models[iModel].scalingFlag());
1465              printf("model really really scaled\n");
1466              models[iModel]=newModel;
1467            }
1468            break;
1469          case USERCLP:
1470            // Replace the sample code by whatever you want
1471            if (goodModels[iModel]) {
1472              ClpSimplex * thisModel = &models[iModel];
1473              printf("Dummy user code - model has %d rows and %d columns\n",
1474                     thisModel->numberRows(),thisModel->numberColumns());
1475            }
1476            break;
1477          case HELP:
1478            std::cout<<"Coin LP version "<<CLPVERSION
1479                     <<", build "<<__DATE__<<std::endl;
1480            std::cout<<"Non default values:-"<<std::endl;
1481            std::cout<<"Perturbation "<<models[0].perturbation()<<" (default 100)"
1482                     <<std::endl;
1483            CoinReadPrintit(
1484                    "Presolve being done with 5 passes\n\
1485Dual steepest edge steep/partial on matrix shape and factorization density\n\
1486Clpnnnn taken out of messages\n\
1487If Factorization frequency default then done on size of matrix\n\n\
1488(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
1489You can switch to interactive mode at any time so\n\
1490clp watson.mps -scaling off -primalsimplex\nis the same as\n\
1491clp watson.mps -\nscaling off\nprimalsimplex"
1492                    );
1493            break;
1494          case SOLUTION:
1495            if (goodModels[iModel]) {
1496              // get next field
1497              field = CoinReadGetString(argc,argv);
1498              if (field=="$") {
1499                field = parameters[iParam].stringValue();
1500              } else if (field=="EOL") {
1501                parameters[iParam].printString();
1502                break;
1503              } else {
1504                parameters[iParam].setStringValue(field);
1505              }
1506              std::string fileName;
1507              FILE *fp=NULL;
1508              if (field=="-"||field=="EOL"||field=="stdout") {
1509                // stdout
1510                fp=stdout;
1511                fprintf(fp,"\n");
1512              } else if (field=="stderr") {
1513                // stderr
1514                fp=stderr;
1515                fprintf(fp,"\n");
1516              } else {
1517                if (field[0]=='/'||field[0]=='\\') {
1518                  fileName = field;
1519                } else if (field[0]=='~') {
1520                  char * environVar = getenv("HOME");
1521                  if (environVar) {
1522                    std::string home(environVar);
1523                    field=field.erase(0,1);
1524                    fileName = home+field;
1525                  } else {
1526                    fileName=field;
1527                  }
1528                } else {
1529                  fileName = directory+field;
1530                }
1531                fp=fopen(fileName.c_str(),"w");
1532              }
1533              if (fp) {
1534                // make fancy later on
1535                int iRow;
1536                int numberRows=models[iModel].numberRows();
1537                int lengthName = models[iModel].lengthNames(); // 0 if no names
1538                // in general I don't want to pass around massive
1539                // amounts of data but seems simpler here
1540                std::vector<std::string> rowNames =
1541                  *(models[iModel].rowNames());
1542                std::vector<std::string> columnNames =
1543                  *(models[iModel].columnNames());
1544
1545                double * dualRowSolution = models[iModel].dualRowSolution();
1546                double * primalRowSolution = 
1547                  models[iModel].primalRowSolution();
1548                double * rowLower = models[iModel].rowLower();
1549                double * rowUpper = models[iModel].rowUpper();
1550                double primalTolerance = models[iModel].primalTolerance();
1551                char format[6];
1552                sprintf(format,"%%-%ds",CoinMax(lengthName,8));
1553                bool doMask = (printMask!=""&&lengthName);
1554                int * maskStarts=NULL;
1555                int maxMasks=0;
1556                char ** masks =NULL;
1557                if (doMask) {
1558                  int nAst =0;
1559                  const char * pMask2 = printMask.c_str();
1560                  char pMask[100];
1561                  int iChar;
1562                  int lengthMask = strlen(pMask2);
1563                  assert (lengthMask<100);
1564                  if (*pMask2=='"') {
1565                    if (pMask2[lengthMask-1]!='"') {
1566                      printf("mismatched \" in mask %s\n",pMask2);
1567                      break;
1568                    } else {
1569                      strcpy(pMask,pMask2+1);
1570                      *strchr(pMask,'"')='\0';
1571                    }
1572                  } else if (*pMask2=='\'') {
1573                    if (pMask2[lengthMask-1]!='\'') {
1574                      printf("mismatched ' in mask %s\n",pMask2);
1575                      break;
1576                    } else {
1577                      strcpy(pMask,pMask2+1);
1578                      *strchr(pMask,'\'')='\0';
1579                    }
1580                  } else {
1581                    strcpy(pMask,pMask2);
1582                  }
1583                  if (lengthMask>lengthName) {
1584                    printf("mask %s too long - skipping\n",pMask);
1585                    break;
1586                  }
1587                  maxMasks = 1;
1588                  for (iChar=0;iChar<lengthMask;iChar++) {
1589                    if (pMask[iChar]=='*') {
1590                      nAst++;
1591                      maxMasks *= (lengthName+1);
1592                    }
1593                  }
1594                  int nEntries = 1;
1595                  maskStarts = new int[lengthName+2];
1596                  masks = new char * [maxMasks];
1597                  char ** newMasks = new char * [maxMasks];
1598                  int i;
1599                  for (i=0;i<maxMasks;i++) {
1600                    masks[i] = new char[lengthName+1];
1601                    newMasks[i] = new char[lengthName+1];
1602                  }
1603                  strcpy(masks[0],pMask);
1604                  for (int iAst=0;iAst<nAst;iAst++) {
1605                    int nOldEntries = nEntries;
1606                    nEntries=0;
1607                    for (int iEntry = 0;iEntry<nOldEntries;iEntry++) {
1608                      char * oldMask = masks[iEntry];
1609                      char * ast = strchr(oldMask,'*');
1610                      assert (ast);
1611                      int length = strlen(oldMask)-1;
1612                      int nBefore = ast-oldMask;
1613                      int nAfter = length-nBefore;
1614                      // and add null
1615                      nAfter++;
1616                      for (int i=0;i<=lengthName-length;i++) {
1617                        char * maskOut = newMasks[nEntries];
1618                        memcpy(maskOut,oldMask,nBefore);
1619                        for (int k=0;k<i;k++) 
1620                          maskOut[k+nBefore]='?';
1621                        memcpy(maskOut+nBefore+i,ast+1,nAfter);
1622                        nEntries++;
1623                        assert (nEntries<=maxMasks);
1624                      }
1625                    }
1626                    char ** temp = masks;
1627                    masks = newMasks;
1628                    newMasks = temp;
1629                  }
1630                  // Now extend and sort
1631                  int * sort = new int[nEntries];
1632                  for (i=0;i<nEntries;i++) {
1633                    char * maskThis = masks[i];
1634                    int length = strlen(maskThis);
1635                    while (maskThis[length-1]==' ')
1636                      length--;
1637                    maskThis[length]='\0';
1638                    sort[i]=length;
1639                  }
1640                  CoinSort_2(sort,sort+nEntries,masks);
1641                  int lastLength=-1;
1642                  for (i=0;i<nEntries;i++) {
1643                    int length = sort[i];
1644                    while (length>lastLength) 
1645                      maskStarts[++lastLength] = i;
1646                  }
1647                  maskStarts[++lastLength]=nEntries;
1648                  delete [] sort;
1649                  for (i=0;i<maxMasks;i++)
1650                    delete [] newMasks[i];
1651                  delete [] newMasks;
1652                }
1653                if (printMode>2) {
1654                  for (iRow=0;iRow<numberRows;iRow++) {
1655                    int type=printMode-3;
1656                    if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
1657                        primalRowSolution[iRow]<rowLower[iRow]-primalTolerance) {
1658                      fprintf(fp,"** ");
1659                      type=2;
1660                    } else if (fabs(primalRowSolution[iRow])>1.0e-8) {
1661                      type=1;
1662                    } else if (numberRows<50) {
1663                      type=3;
1664                    } 
1665                    if (doMask&&!maskMatches(maskStarts,masks,rowNames[iRow]))
1666                      type=0;
1667                    if (type) {
1668                      fprintf(fp,"%7d ",iRow);
1669                      if (lengthName)
1670                        fprintf(fp,format,rowNames[iRow].c_str());
1671                      fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
1672                              dualRowSolution[iRow]);
1673                    }
1674                  }
1675                }
1676                int iColumn;
1677                int numberColumns=models[iModel].numberColumns();
1678                double * dualColumnSolution = 
1679  models[iModel].dualColumnSolution();
1680                double * primalColumnSolution = 
1681  models[iModel].primalColumnSolution();
1682                double * columnLower = models[iModel].columnLower();
1683                double * columnUpper = models[iModel].columnUpper();
1684                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1685                  int type=(printMode>3) ? 1 : 0;
1686                  if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
1687                      primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance) {
1688                    fprintf(fp,"** ");
1689                    type=2;
1690                  } else if (fabs(primalColumnSolution[iColumn])>1.0e-8) {
1691                    type=1;
1692                  } else if (numberColumns<50) {
1693                    type=3;
1694                  }
1695                  if (doMask&&!maskMatches(maskStarts,masks,
1696                                           columnNames[iColumn]))
1697                    type =0;
1698                  if (type) {
1699                    fprintf(fp,"%7d ",iColumn);
1700                    if (lengthName)
1701                      fprintf(fp,format,columnNames[iColumn].c_str());
1702                    fprintf(fp,"%15.8g        %15.8g\n",
1703                            primalColumnSolution[iColumn],
1704                            dualColumnSolution[iColumn]);
1705                  }
1706                }
1707                if (fp!=stdout)
1708                  fclose(fp);
1709                if (masks) {
1710                  delete [] maskStarts;
1711                  for (int i=0;i<maxMasks;i++)
1712                    delete [] masks[i];
1713                  delete [] masks;
1714                }
1715              } else {
1716                std::cout<<"Unable to open file "<<fileName<<std::endl;
1717              }
1718            } else {
1719              std::cout<<"** Current model not valid"<<std::endl;
1720             
1721            }
1722         
1723            break;
1724          case SAVESOL:
1725            if (goodModels[iModel]) {
1726              // get next field
1727              field = CoinReadGetString(argc,argv);
1728              if (field=="$") {
1729                field = parameters[iParam].stringValue();
1730              } else if (field=="EOL") {
1731                parameters[iParam].printString();
1732                break;
1733              } else {
1734                parameters[iParam].setStringValue(field);
1735              }
1736              std::string fileName;
1737              if (field[0]=='/'||field[0]=='\\') {
1738                fileName = field;
1739              } else if (field[0]=='~') {
1740                char * environVar = getenv("HOME");
1741                if (environVar) {
1742                  std::string home(environVar);
1743                  field=field.erase(0,1);
1744                  fileName = home+field;
1745                } else {
1746                  fileName=field;
1747                }
1748              } else {
1749                fileName = directory+field;
1750              }
1751              saveSolution(models+iModel,fileName);
1752            } else {
1753              std::cout<<"** Current model not valid"<<std::endl;
1754             
1755            }
1756            break;
1757          default:
1758            abort();
1759          }
1760        } 
1761      } else if (!numberMatches) {
1762        std::cout<<"No match for "<<field<<" - ? for list of commands"
1763                 <<std::endl;
1764      } else if (numberMatches==1) {
1765        if (!numberQuery) {
1766          std::cout<<"Short match for "<<field<<" - completion: ";
1767          std::cout<<parameters[firstMatch].matchName()<<std::endl;
1768        } else if (numberQuery) {
1769          std::cout<<parameters[firstMatch].matchName()<<" : ";
1770          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
1771          if (numberQuery>=2) 
1772            parameters[firstMatch].printLongHelp();
1773        }
1774      } else {
1775        if (!numberQuery) 
1776          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
1777                   <<std::endl;
1778        else
1779          std::cout<<"Completions of "<<field<<":"<<std::endl;
1780        for ( iParam=0; iParam<numberParameters; iParam++ ) {
1781          int match = parameters[iParam].matches(field);
1782          if (match&&parameters[iParam].displayThis()) {
1783            std::cout<<parameters[iParam].matchName();
1784            if (numberQuery>=2) 
1785              std::cout<<" : "<<parameters[iParam].shortHelp();
1786            std::cout<<std::endl;
1787          }
1788        }
1789      }
1790    }
1791    delete [] models;
1792    delete [] goodModels;
1793  }
1794  // By now all memory should be freed
1795#ifdef DMALLOC
1796  dmalloc_log_unfreed();
1797  dmalloc_shutdown();
1798#endif
1799  return 0;
1800}   
1801static void breakdown(const char * name, int numberLook, const double * region)
1802{
1803  double range[] = {
1804    -COIN_DBL_MAX,
1805    -1.0e15,-1.0e11,-1.0e8,-1.0e5,-1.0e4,-1.0e3,-1.0e2,-1.0e1,
1806    -1.0,
1807    -1.0e-1,-1.0e-2,-1.0e-3,-1.0e-4,-1.0e-5,-1.0e-8,-1.0e-11,-1.0e-15,
1808    0.0,
1809    1.0e-15,1.0e-11,1.0e-8,1.0e-5,1.0e-4,1.0e-3,1.0e-2,1.0e-1,
1810    1.0,
1811    1.0e1,1.0e2,1.0e3,1.0e4,1.0e5,1.0e8,1.0e11,1.0e15,
1812    COIN_DBL_MAX};
1813  int nRanges = (int) (sizeof(range)/sizeof(double));
1814  int * number = new int[nRanges];
1815  memset(number,0,nRanges*sizeof(int));
1816  int * numberExact = new int[nRanges];
1817  memset(numberExact,0,nRanges*sizeof(int));
1818  int i;
1819  for ( i=0;i<numberLook;i++) {
1820    double value = region[i];
1821    for (int j=0;j<nRanges;j++) {
1822      if (value==range[j]) {
1823        numberExact[j]++;
1824        break;
1825      } else if (value<range[j]) {
1826        number[j]++;
1827        break;
1828      }
1829    }
1830  }
1831  printf("\n%s has %d entries\n",name,numberLook);
1832  for (i=0;i<nRanges;i++) {
1833    if (number[i]) 
1834      printf("%d between %g and %g",number[i],range[i-1],range[i]);
1835    if (numberExact[i]) {
1836      if (number[i])
1837        printf(", ");
1838      printf("%d exactly at %g",numberExact[i],range[i]);
1839    }
1840    if (number[i]+numberExact[i])
1841      printf("\n");
1842  }
1843  delete [] number;
1844  delete [] numberExact;
1845}
1846static void statistics(ClpSimplex * originalModel, ClpSimplex * model)
1847{
1848  int numberColumns = originalModel->numberColumns();
1849  const char * integerInformation  = originalModel->integerInformation(); 
1850  const double * columnLower = originalModel->columnLower();
1851  const double * columnUpper = originalModel->columnUpper();
1852  int numberIntegers=0;
1853  int numberBinary=0;
1854  int iRow,iColumn;
1855  if (integerInformation) {
1856    for (iColumn=0;iColumn<numberColumns;iColumn++) {
1857      if (integerInformation[iColumn]) {
1858        if (columnUpper[iColumn]>columnLower[iColumn]) {
1859          numberIntegers++;
1860          if (columnUpper[iColumn]==0.0&&columnLower[iColumn]==1) 
1861            numberBinary++;
1862        }
1863      }
1864    }
1865  }
1866  numberColumns = model->numberColumns();
1867  int numberRows = model->numberRows();
1868  columnLower = model->columnLower();
1869  columnUpper = model->columnUpper();
1870  const double * rowLower = model->rowLower();
1871  const double * rowUpper = model->rowUpper();
1872  const double * objective = model->objective();
1873  CoinPackedMatrix * matrix = model->matrix();
1874  CoinBigIndex numberElements = matrix->getNumElements();
1875  const int * columnLength = matrix->getVectorLengths();
1876  //const CoinBigIndex * columnStart = matrix->getVectorStarts();
1877  const double * elementByColumn = matrix->getElements();
1878  int * number = new int[numberRows+1];
1879  memset(number,0,(numberRows+1)*sizeof(int));
1880  int numberObjSingletons=0;
1881  /* cType
1882     0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up,
1883     8 0/1
1884  */ 
1885  int cType[9];
1886  std::string cName[]={"0.0->inf,","0.0->up,","lo->inf,","lo->up,","free,","fixed,","-inf->0.0,",
1887                       "-inf->up,","0.0->1.0"};
1888  int nObjective=0;
1889  memset(cType,0,sizeof(cType));
1890  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1891    int length=columnLength[iColumn];
1892    if (length==1&&objective[iColumn])
1893      numberObjSingletons++;
1894    number[length]++;
1895    if (objective[iColumn])
1896      nObjective++;
1897    if (columnLower[iColumn]>-1.0e20) {
1898      if (columnLower[iColumn]==0.0) {
1899        if (columnUpper[iColumn]>1.0e20)
1900          cType[0]++;
1901        else if (columnUpper[iColumn]==1.0)
1902          cType[8]++;
1903        else if (columnUpper[iColumn]==0.0)
1904          cType[5]++;
1905        else
1906          cType[1]++;
1907      } else {
1908        if (columnUpper[iColumn]>1.0e20) 
1909          cType[2]++;
1910        else if (columnUpper[iColumn]==columnLower[iColumn])
1911          cType[5]++;
1912        else
1913          cType[3]++;
1914      }
1915    } else {
1916      if (columnUpper[iColumn]>1.0e20) 
1917        cType[4]++;
1918      else if (columnUpper[iColumn]==0.0) 
1919        cType[6]++;
1920      else
1921        cType[7]++;
1922    }
1923  }
1924  /* rType
1925     0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other,
1926     7 L 0,  8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free
1927  */ 
1928  int rType[13];
1929  std::string rName[]={"E 0.0,","E 1.0,","E -1.0,","E other,","G 0.0,","G 1.0,","G other,",
1930                       "L 0.0,","L 1.0,","L other,","Range 0.0->1.0,","Range other,","Free"};
1931  memset(rType,0,sizeof(rType));
1932  for (iRow=0;iRow<numberRows;iRow++) {
1933    if (rowLower[iRow]>-1.0e20) {
1934      if (rowLower[iRow]==0.0) {
1935        if (rowUpper[iRow]>1.0e20)
1936          rType[4]++;
1937        else if (rowUpper[iRow]==1.0)
1938          rType[10]++;
1939        else if (rowUpper[iRow]==0.0)
1940          rType[0]++;
1941        else
1942          rType[11]++;
1943      } else if (rowLower[iRow]==1.0) {
1944        if (rowUpper[iRow]>1.0e20) 
1945          rType[5]++;
1946        else if (rowUpper[iRow]==rowLower[iRow])
1947          rType[1]++;
1948        else
1949          rType[11]++;
1950      } else if (rowLower[iRow]==-1.0) {
1951        if (rowUpper[iRow]>1.0e20) 
1952          rType[6]++;
1953        else if (rowUpper[iRow]==rowLower[iRow])
1954          rType[2]++;
1955        else
1956          rType[11]++;
1957      } else {
1958        if (rowUpper[iRow]>1.0e20) 
1959          rType[6]++;
1960        else if (rowUpper[iRow]==rowLower[iRow])
1961          rType[3]++;
1962        else
1963          rType[11]++;
1964      }
1965    } else {
1966      if (rowUpper[iRow]>1.0e20) 
1967        rType[12]++;
1968      else if (rowUpper[iRow]==0.0) 
1969        rType[7]++;
1970      else if (rowUpper[iRow]==1.0) 
1971        rType[8]++;
1972      else
1973        rType[9]++;
1974    }
1975  }
1976  // Basic statistics
1977  printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n",
1978         numberRows,numberColumns,nObjective,numberElements);
1979  if (number[0]+number[1]) {
1980    printf("There are ");
1981    if (numberObjSingletons)
1982      printf("%d singletons with objective ",numberObjSingletons);
1983    int numberNoObj = number[1]-numberObjSingletons;
1984    if (numberNoObj)
1985      printf("%d singletons with no objective ",numberNoObj);
1986    if (number[0])
1987      printf("** %d columns have no entries",number[0]);
1988    printf("\n");
1989  }
1990  printf("Column breakdown:\n");
1991  int k;
1992  for (k=0;k<(int) (sizeof(cType)/sizeof(int));k++) {
1993    printf("%d of type %s ",cType[k],cName[k].c_str());
1994    if (((k+1)%3)==0)
1995      printf("\n");
1996  }
1997  if ((k%3)!=0)
1998    printf("\n");
1999  printf("Row breakdown:\n");
2000  for (k=0;k<(int) (sizeof(rType)/sizeof(int));k++) {
2001    printf("%d of type %s ",rType[k],rName[k].c_str());
2002    if (((k+1)%3)==0)
2003      printf("\n");
2004  }
2005  if ((k%3)!=0)
2006    printf("\n");
2007  if (model->logLevel()<2)
2008    return ;
2009  int kMax = model->logLevel()>3 ? 1000000 : 10;
2010  k=0;
2011  for (iRow=1;iRow<=numberRows;iRow++) {
2012    if (number[iRow]) {
2013      k++;
2014      printf("%d columns have %d entries\n",number[iRow],iRow);
2015      if (k==kMax)
2016        break;
2017    }
2018  }
2019  if (k<numberRows) {
2020    int kk=k;
2021    k=0;
2022    for (iRow=numberRows;iRow>=1;iRow--) {
2023      if (number[iRow]) {
2024        k++;
2025        if (k==kMax)
2026          break;
2027      }
2028    }
2029    if (k>kk) {
2030      printf("\n    .........\n\n");
2031      iRow=k;
2032      k=0;
2033      for (;iRow<numberRows;iRow++) {
2034        if (number[iRow]) {
2035          k++;
2036          printf("%d columns have %d entries\n",number[iRow],iRow);
2037          if (k==kMax)
2038            break;
2039        }
2040      }
2041    }
2042  }
2043  delete [] number;
2044  printf("\n\n");
2045  // get row copy
2046  CoinPackedMatrix rowCopy = *matrix;
2047  rowCopy.reverseOrdering();
2048  //const int * column = rowCopy.getIndices();
2049  const int * rowLength = rowCopy.getVectorLengths();
2050  //const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
2051  //const double * element = rowCopy.getElements();
2052  number = new int[numberColumns+1];
2053  memset(number,0,(numberColumns+1)*sizeof(int));
2054  for (iRow=0;iRow<numberRows;iRow++) {
2055    int length=rowLength[iRow];
2056    number[length]++;
2057  }
2058  if (number[0])
2059    printf("** %d rows have no entries\n",number[0]);
2060  k=0;
2061  for (iColumn=1;iColumn<=numberColumns;iColumn++) {
2062    if (number[iColumn]) {
2063      k++;
2064      printf("%d rows have %d entries\n",number[iColumn],iColumn);
2065      if (k==kMax)
2066        break;
2067    }
2068  }
2069  if (k<numberColumns) {
2070    int kk=k;
2071    k=0;
2072    for (iColumn=numberColumns;iColumn>=1;iColumn--) {
2073      if (number[iColumn]) {
2074        k++;
2075        if (k==kMax)
2076          break;
2077      }
2078    }
2079    if (k>kk) {
2080      printf("\n    .........\n\n");
2081      iColumn=k;
2082      k=0;
2083      for (;iColumn<numberColumns;iColumn++) {
2084        if (number[iColumn]) {
2085          k++;
2086          printf("%d rows have %d entries\n",number[iColumn],iColumn);
2087          if (k==kMax)
2088            break;
2089        }
2090      }
2091    }
2092  }
2093  delete [] number;
2094  // Now do breakdown of ranges
2095  breakdown("Elements",numberElements,elementByColumn);
2096  breakdown("RowLower",numberRows,rowLower);
2097  breakdown("RowUpper",numberRows,rowUpper);
2098  breakdown("ColumnLower",numberColumns,columnLower);
2099  breakdown("ColumnUpper",numberColumns,columnUpper);
2100  breakdown("Objective",numberColumns,objective);
2101}
2102static bool maskMatches(const int * starts, char ** masks,
2103                        std::string & check)
2104{
2105  // back to char as I am old fashioned
2106  const char * checkC = check.c_str();
2107  int length = strlen(checkC);
2108  while (checkC[length-1]==' ')
2109    length--;
2110  for (int i=starts[length];i<starts[length+1];i++) {
2111    char * thisMask = masks[i];
2112    int k;
2113    for ( k=0;k<length;k++) {
2114      if (thisMask[k]!='?'&&thisMask[k]!=checkC[k]) 
2115        break;
2116    }
2117    if (k==length)
2118      return true;
2119  }
2120  return false;
2121}
2122static void clean(char * temp)
2123{
2124  char * put = temp;
2125  while (*put>=' ')
2126    put++;
2127  *put='\0';
2128}
2129static void generateCode(const char * fileName,int type)
2130{
2131  FILE * fp = fopen(fileName,"r");
2132  assert (fp);
2133  int numberLines=0;
2134#define MAXLINES 500
2135#define MAXONELINE 200
2136  char line[MAXLINES][MAXONELINE];
2137  while (fgets(line[numberLines],MAXONELINE,fp)) {
2138    assert (numberLines<MAXLINES);
2139    clean(line[numberLines]);
2140    numberLines++;
2141  }
2142  fclose(fp);
2143  // add in actual solve
2144  strcpy(line[numberLines],"5  clpModel->initialSolve(clpSolve);");
2145  numberLines++;
2146  fp = fopen(fileName,"w");
2147  assert (fp);
2148  char apo='"';   
2149  char backslash = '\\';
2150
2151  fprintf(fp,"#include %cClpSimplex.hpp%c\n",apo,apo);
2152  fprintf(fp,"#include %cClpSolve.hpp%c\n",apo,apo);
2153
2154  fprintf(fp,"\nint main (int argc, const char *argv[])\n{\n");
2155  fprintf(fp,"  ClpSimplex  model;\n");
2156  fprintf(fp,"  int status=1;\n");
2157  fprintf(fp,"  if (argc<2)\n");
2158  fprintf(fp,"    fprintf(stderr,%cPlease give file name%cn%c);\n",
2159          apo,backslash,apo);
2160  fprintf(fp,"  else\n");
2161  fprintf(fp,"    status=model.readMps(argv[1],true);\n");
2162  fprintf(fp,"  if (status) {\n");
2163  fprintf(fp,"    fprintf(stderr,%cBad readMps %%s%cn%c,argv[1]);\n",
2164                apo,backslash,apo);
2165  fprintf(fp,"    exit(1);\n");
2166  fprintf(fp,"  }\n\n");
2167  fprintf(fp,"  // Now do requested saves and modifications\n");
2168  fprintf(fp,"  ClpSimplex * clpModel = & model;\n");
2169  int wanted[9];
2170  memset(wanted,0,sizeof(wanted));
2171  wanted[0]=wanted[3]=wanted[5]=wanted[8]=1;
2172  if (type>0) 
2173    wanted[1]=wanted[6]=1;
2174  if (type>1) 
2175    wanted[2]=wanted[4]=wanted[7]=1;
2176  std::string header[9]=
2177  { "","Save values","Redundant save of default values","Set changed values",
2178    "Redundant set default values","Solve","Restore values","Redundant restore values","Add to model"};
2179  for (int iType=0;iType<9;iType++) {
2180    if (!wanted[iType])
2181      continue;
2182    int n=0;
2183    int iLine;
2184    for (iLine=0;iLine<numberLines;iLine++) {
2185      if (line[iLine][0]=='0'+iType) {
2186        if (!n)
2187          fprintf(fp,"\n  // %s\n\n",header[iType].c_str());
2188        n++;
2189        fprintf(fp,"%s\n",line[iLine]+1);
2190      }
2191    }
2192  }
2193  fprintf(fp,"\n  // Now you would use solution etc etc\n\n");
2194  fprintf(fp,"  return 0;\n}\n");
2195  fclose(fp);
2196  printf("C++ file written to %s\n",fileName);
2197}
2198/*
2199  Version 1.00.00 October 13 2004.
2200  1.00.01 October 18.  Added basis handling helped/prodded by Thorsten Koch.
2201  Also modifications to make faster with sbb (I hope I haven't broken anything).
2202  1.00.02 March 21 2005.  Redid ClpNonLinearCost to save memory also redid
2203  createRim to try and improve cache characteristics.
2204  1.00.03 April 8 2005.  Added Volume algorithm as crash and made code more
2205  robust on testing.  Also added "either" and "tune" algorithm.
2206  1.01.01 April 12 2005.  Decided to go to different numbering.  Backups will
2207  be last 2 digits while middle 2 are for improvements.  Still take a long
2208  time to get to 2.00.01
2209  1.01.02 May 4 2005.  Will be putting in many changes - so saving stable version
2210  1.02.01 May 6 2005.  Lots of changes to try and make faster and more stable in
2211  branch and cut.
2212  1.02.02 May 19 2005.  Stuff for strong branching and some improvements to simplex
2213  1.03.01 May 24 2006.  Lots done but I can't remember what!
2214  1.03.03 June 13 2006.  For clean up after dual perturbation
2215 */
Note: See TracBrowser for help on using the repository browser.