source: branches/BSP/trunk/Clp/src/ClpMain.cpp @ 1073

Last change on this file since 1073 was 1073, checked in by ladanyi, 12 years ago

Got rid of dependency on Data/Netlib?

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