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

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

add lpio and correct tightenbounds

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