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

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

add numeric checking to main programs and modify tightenPrimalbounds

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