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

Last change on this file since 1070 was 1070, checked in by andreasw, 13 years ago

corrected Clp version number that is printed

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