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

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

Got rid of dependency on Data/Netlib?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.0 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3   
4#include "CoinPragma.hpp"
5
6#include <cassert>
7#include <cstdio>
8#include <cmath>
9#include <cfloat>
10#include <string>
11#include <iostream>
12
13#include "CoinPragma.hpp"
14#include "CoinHelperFunctions.hpp"
15#include "CoinSort.hpp"
16
17#include "CoinMpsIO.hpp"
18#include "CoinFileIO.hpp"
19
20#include "ClpFactorization.hpp"
21#include "CoinTime.hpp"
22#include "ClpSimplex.hpp"
23#include "ClpSimplexOther.hpp"
24#include "ClpSolve.hpp"
25#include "ClpPackedMatrix.hpp"
26#include "ClpPlusMinusOneMatrix.hpp"
27#include "ClpNetworkMatrix.hpp"
28#include "ClpDualRowSteepest.hpp"
29#include "ClpDualRowDantzig.hpp"
30#include "ClpLinearObjective.hpp"
31#include "ClpPrimalColumnSteepest.hpp"
32#include "ClpPrimalColumnDantzig.hpp"
33#include "ClpPresolve.hpp"
34#include "CbcOrClpParam.hpp"
35#ifdef DMALLOC
36#include "dmalloc.h"
37#endif
38#ifdef WSSMP_BARRIER
39#define FOREIGN_BARRIER
40#endif
41#ifdef UFL_BARRIER
42#define FOREIGN_BARRIER
43#endif
44#ifdef TAUCS_BARRIER
45#define FOREIGN_BARRIER
46#endif
47
48// If HAVE_CONFIG_H is not defined, CLPVERSION is defined in ClpConfig.h
49#ifdef HAVE_CONFIG_H
50# include "config_clp.h"
51# define CLPVERSION PACKAGE_VERSION
52#endif
53
54static double totalTime=0.0;
55static bool maskMatches(const int * starts, char ** masks,
56                        std::string & check);
57
58//#############################################################################
59
60#ifdef NDEBUG
61#undef NDEBUG
62#endif
63
64int mainTest (int argc, const char *argv[],int algorithm,
65              ClpSimplex empty, bool doPresolve,int switchOff,bool doVector);
66static void statistics(ClpSimplex * originalModel, ClpSimplex * model);
67static void generateCode(const char * fileName,int type);
68// Returns next valid field
69int CbcOrClpRead_mode=1;
70FILE * CbcOrClpReadCommand=stdin;
71int main (int argc, const char *argv[])
72{
73  // next {} is just to make sure all memory should be freed - for debug
74  {
75    double time1 = CoinCpuTime(),time2;
76    // Set up all non-standard stuff
77    //int numberModels=1;
78    ClpSimplex * models = new ClpSimplex[1];
79   
80    // default action on import
81    int allowImportErrors=0;
82    int keepImportNames=1;
83    int doIdiot=-1;
84    int outputFormat=2;
85    int slpValue=-1;
86    int cppValue=-1;
87    int printOptions=0;
88    int printMode=0;
89    int presolveOptions=0;
90    int doCrash=0;
91    int doVector=0;
92    int doSprint=-1;
93    // set reasonable defaults
94    int preSolve=5;
95    bool preSolveFile=false;
96    models->setPerturbation(50);
97    models->messageHandler()->setPrefix(false);
98    const char dirsep =  CoinFindDirSeparator();
99    std::string directory = (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[3];
1375              std::string dirfield;
1376              int nFields=2;
1377              fields[0]="fake main from unitTest";
1378              fields[1]="-netlib";
1379              if (directory!=defaultDirectory) {
1380                dirfield = "-netlibDir=";
1381                dirfield += directory.c_str();
1382                fields[2]=dirfield.c_str();
1383                nFields=3;
1384              }
1385              int algorithm;
1386              if (type==NETLIB_DUAL) {
1387                std::cerr<<"Doing netlib with dual algorithm"<<std::endl;
1388                algorithm =0;
1389              } else if (type==NETLIB_BARRIER) {
1390                std::cerr<<"Doing netlib with barrier algorithm"<<std::endl;
1391                algorithm =2;
1392              } else if (type==NETLIB_EITHER) {
1393                std::cerr<<"Doing netlib with dual or primal algorithm"<<std::endl;
1394                algorithm =3;
1395              } else if (type==NETLIB_TUNE) {
1396                std::cerr<<"Doing netlib with best algorithm!"<<std::endl;
1397                algorithm =5;
1398                // uncomment next to get active tuning
1399                // algorithm=6;
1400              } else {
1401                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
1402                algorithm=1;
1403              }
1404              int specialOptions = models[iModel].specialOptions();
1405              models[iModel].setSpecialOptions(0);
1406              mainTest(nFields,fields,algorithm,models[iModel],
1407                       (preSolve!=0),specialOptions,doVector!=0);
1408            }
1409            break;
1410          case UNITTEST:
1411            {
1412              // create fields for unitTest
1413              const char * fields[3];
1414              int nFields=1;
1415              fields[0]="fake main from unitTest";
1416              int specialOptions = models[iModel].specialOptions();
1417              models[iModel].setSpecialOptions(0);
1418              int algorithm=-1;
1419              if (models[iModel].numberRows())
1420                algorithm=7;
1421              mainTest(nFields,fields,algorithm,models[iModel],(preSolve!=0),specialOptions,doVector!=0);
1422            }
1423            break;
1424          case FAKEBOUND:
1425            if (goodModels[iModel]) {
1426              // get bound
1427              double value = CoinReadGetDoubleField(argc,argv,&valid);
1428              if (!valid) {
1429                std::cout<<"Setting "<<parameters[iParam].name()<<
1430                  " to DEBUG "<<value<<std::endl;
1431                int iRow;
1432                int numberRows=models[iModel].numberRows();
1433                double * rowLower = models[iModel].rowLower();
1434                double * rowUpper = models[iModel].rowUpper();
1435                for (iRow=0;iRow<numberRows;iRow++) {
1436                  // leave free ones for now
1437                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
1438                    rowLower[iRow]=CoinMax(rowLower[iRow],-value);
1439                    rowUpper[iRow]=CoinMin(rowUpper[iRow],value);
1440                  }
1441                }
1442                int iColumn;
1443                int numberColumns=models[iModel].numberColumns();
1444                double * columnLower = models[iModel].columnLower();
1445                double * columnUpper = models[iModel].columnUpper();
1446                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1447                  // leave free ones for now
1448                  if (columnLower[iColumn]>-1.0e20||
1449                      columnUpper[iColumn]<1.0e20) {
1450                    columnLower[iColumn]=CoinMax(columnLower[iColumn],-value);
1451                    columnUpper[iColumn]=CoinMin(columnUpper[iColumn],value);
1452                  }
1453                }
1454              } else if (valid==1) {
1455                abort();
1456              } else {
1457                std::cout<<"enter value for "<<parameters[iParam].name()<<
1458                  std::endl;
1459              }
1460            }
1461            break;
1462          case REALLY_SCALE:
1463            if (goodModels[iModel]) {
1464              ClpSimplex newModel(models[iModel],
1465                                  models[iModel].scalingFlag());
1466              printf("model really really scaled\n");
1467              models[iModel]=newModel;
1468            }
1469            break;
1470          case USERCLP:
1471            // Replace the sample code by whatever you want
1472            if (goodModels[iModel]) {
1473              ClpSimplex * thisModel = &models[iModel];
1474              printf("Dummy user code - model has %d rows and %d columns\n",
1475                     thisModel->numberRows(),thisModel->numberColumns());
1476            }
1477            break;
1478          case HELP:
1479            std::cout<<"Coin LP version "<<CLPVERSION
1480                     <<", build "<<__DATE__<<std::endl;
1481            std::cout<<"Non default values:-"<<std::endl;
1482            std::cout<<"Perturbation "<<models[0].perturbation()<<" (default 100)"
1483                     <<std::endl;
1484            CoinReadPrintit(
1485                    "Presolve being done with 5 passes\n\
1486Dual steepest edge steep/partial on matrix shape and factorization density\n\
1487Clpnnnn taken out of messages\n\
1488If Factorization frequency default then done on size of matrix\n\n\
1489(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
1490You can switch to interactive mode at any time so\n\
1491clp watson.mps -scaling off -primalsimplex\nis the same as\n\
1492clp watson.mps -\nscaling off\nprimalsimplex"
1493                    );
1494            break;
1495          case SOLUTION:
1496            if (goodModels[iModel]) {
1497              // get next field
1498              field = CoinReadGetString(argc,argv);
1499              if (field=="$") {
1500                field = parameters[iParam].stringValue();
1501              } else if (field=="EOL") {
1502                parameters[iParam].printString();
1503                break;
1504              } else {
1505                parameters[iParam].setStringValue(field);
1506              }
1507              std::string fileName;
1508              FILE *fp=NULL;
1509              if (field=="-"||field=="EOL"||field=="stdout") {
1510                // stdout
1511                fp=stdout;
1512                fprintf(fp,"\n");
1513              } else if (field=="stderr") {
1514                // stderr
1515                fp=stderr;
1516                fprintf(fp,"\n");
1517              } else {
1518                if (field[0]=='/'||field[0]=='\\') {
1519                  fileName = field;
1520                } else if (field[0]=='~') {
1521                  char * environVar = getenv("HOME");
1522                  if (environVar) {
1523                    std::string home(environVar);
1524                    field=field.erase(0,1);
1525                    fileName = home+field;
1526                  } else {
1527                    fileName=field;
1528                  }
1529                } else {
1530                  fileName = directory+field;
1531                }
1532                fp=fopen(fileName.c_str(),"w");
1533              }
1534              if (fp) {
1535                // make fancy later on
1536                int iRow;
1537                int numberRows=models[iModel].numberRows();
1538                int lengthName = models[iModel].lengthNames(); // 0 if no names
1539                // in general I don't want to pass around massive
1540                // amounts of data but seems simpler here
1541                std::vector<std::string> rowNames =
1542                  *(models[iModel].rowNames());
1543                std::vector<std::string> columnNames =
1544                  *(models[iModel].columnNames());
1545
1546                double * dualRowSolution = models[iModel].dualRowSolution();
1547                double * primalRowSolution = 
1548                  models[iModel].primalRowSolution();
1549                double * rowLower = models[iModel].rowLower();
1550                double * rowUpper = models[iModel].rowUpper();
1551                double primalTolerance = models[iModel].primalTolerance();
1552                char format[6];
1553                sprintf(format,"%%-%ds",CoinMax(lengthName,8));
1554                bool doMask = (printMask!=""&&lengthName);
1555                int * maskStarts=NULL;
1556                int maxMasks=0;
1557                char ** masks =NULL;
1558                if (doMask) {
1559                  int nAst =0;
1560                  const char * pMask2 = printMask.c_str();
1561                  char pMask[100];
1562                  int iChar;
1563                  int lengthMask = strlen(pMask2);
1564                  assert (lengthMask<100);
1565                  if (*pMask2=='"') {
1566                    if (pMask2[lengthMask-1]!='"') {
1567                      printf("mismatched \" in mask %s\n",pMask2);
1568                      break;
1569                    } else {
1570                      strcpy(pMask,pMask2+1);
1571                      *strchr(pMask,'"')='\0';
1572                    }
1573                  } else if (*pMask2=='\'') {
1574                    if (pMask2[lengthMask-1]!='\'') {
1575                      printf("mismatched ' in mask %s\n",pMask2);
1576                      break;
1577                    } else {
1578                      strcpy(pMask,pMask2+1);
1579                      *strchr(pMask,'\'')='\0';
1580                    }
1581                  } else {
1582                    strcpy(pMask,pMask2);
1583                  }
1584                  if (lengthMask>lengthName) {
1585                    printf("mask %s too long - skipping\n",pMask);
1586                    break;
1587                  }
1588                  maxMasks = 1;
1589                  for (iChar=0;iChar<lengthMask;iChar++) {
1590                    if (pMask[iChar]=='*') {
1591                      nAst++;
1592                      maxMasks *= (lengthName+1);
1593                    }
1594                  }
1595                  int nEntries = 1;
1596                  maskStarts = new int[lengthName+2];
1597                  masks = new char * [maxMasks];
1598                  char ** newMasks = new char * [maxMasks];
1599                  int i;
1600                  for (i=0;i<maxMasks;i++) {
1601                    masks[i] = new char[lengthName+1];
1602                    newMasks[i] = new char[lengthName+1];
1603                  }
1604                  strcpy(masks[0],pMask);
1605                  for (int iAst=0;iAst<nAst;iAst++) {
1606                    int nOldEntries = nEntries;
1607                    nEntries=0;
1608                    for (int iEntry = 0;iEntry<nOldEntries;iEntry++) {
1609                      char * oldMask = masks[iEntry];
1610                      char * ast = strchr(oldMask,'*');
1611                      assert (ast);
1612                      int length = strlen(oldMask)-1;
1613                      int nBefore = ast-oldMask;
1614                      int nAfter = length-nBefore;
1615                      // and add null
1616                      nAfter++;
1617                      for (int i=0;i<=lengthName-length;i++) {
1618                        char * maskOut = newMasks[nEntries];
1619                        memcpy(maskOut,oldMask,nBefore);
1620                        for (int k=0;k<i;k++) 
1621                          maskOut[k+nBefore]='?';
1622                        memcpy(maskOut+nBefore+i,ast+1,nAfter);
1623                        nEntries++;
1624                        assert (nEntries<=maxMasks);
1625                      }
1626                    }
1627                    char ** temp = masks;
1628                    masks = newMasks;
1629                    newMasks = temp;
1630                  }
1631                  // Now extend and sort
1632                  int * sort = new int[nEntries];
1633                  for (i=0;i<nEntries;i++) {
1634                    char * maskThis = masks[i];
1635                    int length = strlen(maskThis);
1636                    while (maskThis[length-1]==' ')
1637                      length--;
1638                    maskThis[length]='\0';
1639                    sort[i]=length;
1640                  }
1641                  CoinSort_2(sort,sort+nEntries,masks);
1642                  int lastLength=-1;
1643                  for (i=0;i<nEntries;i++) {
1644                    int length = sort[i];
1645                    while (length>lastLength) 
1646                      maskStarts[++lastLength] = i;
1647                  }
1648                  maskStarts[++lastLength]=nEntries;
1649                  delete [] sort;
1650                  for (i=0;i<maxMasks;i++)
1651                    delete [] newMasks[i];
1652                  delete [] newMasks;
1653                }
1654                if (printMode>2) {
1655                  for (iRow=0;iRow<numberRows;iRow++) {
1656                    int type=printMode-3;
1657                    if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
1658                        primalRowSolution[iRow]<rowLower[iRow]-primalTolerance) {
1659                      fprintf(fp,"** ");
1660                      type=2;
1661                    } else if (fabs(primalRowSolution[iRow])>1.0e-8) {
1662                      type=1;
1663                    } else if (numberRows<50) {
1664                      type=3;
1665                    } 
1666                    if (doMask&&!maskMatches(maskStarts,masks,rowNames[iRow]))
1667                      type=0;
1668                    if (type) {
1669                      fprintf(fp,"%7d ",iRow);
1670                      if (lengthName)
1671                        fprintf(fp,format,rowNames[iRow].c_str());
1672                      fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
1673                              dualRowSolution[iRow]);
1674                    }
1675                  }
1676                }
1677                int iColumn;
1678                int numberColumns=models[iModel].numberColumns();
1679                double * dualColumnSolution = 
1680  models[iModel].dualColumnSolution();
1681                double * primalColumnSolution = 
1682  models[iModel].primalColumnSolution();
1683                double * columnLower = models[iModel].columnLower();
1684                double * columnUpper = models[iModel].columnUpper();
1685                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1686                  int type=(printMode>3) ? 1 : 0;
1687                  if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
1688                      primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance) {
1689                    fprintf(fp,"** ");
1690                    type=2;
1691                  } else if (fabs(primalColumnSolution[iColumn])>1.0e-8) {
1692                    type=1;
1693                  } else if (numberColumns<50) {
1694                    type=3;
1695                  }
1696                  if (doMask&&!maskMatches(maskStarts,masks,
1697                                           columnNames[iColumn]))
1698                    type =0;
1699                  if (type) {
1700                    fprintf(fp,"%7d ",iColumn);
1701                    if (lengthName)
1702                      fprintf(fp,format,columnNames[iColumn].c_str());
1703                    fprintf(fp,"%15.8g        %15.8g\n",
1704                            primalColumnSolution[iColumn],
1705                            dualColumnSolution[iColumn]);
1706                  }
1707                }
1708                if (fp!=stdout)
1709                  fclose(fp);
1710                if (masks) {
1711                  delete [] maskStarts;
1712                  for (int i=0;i<maxMasks;i++)
1713                    delete [] masks[i];
1714                  delete [] masks;
1715                }
1716              } else {
1717                std::cout<<"Unable to open file "<<fileName<<std::endl;
1718              }
1719            } else {
1720              std::cout<<"** Current model not valid"<<std::endl;
1721             
1722            }
1723         
1724            break;
1725          case SAVESOL:
1726            if (goodModels[iModel]) {
1727              // get next field
1728              field = CoinReadGetString(argc,argv);
1729              if (field=="$") {
1730                field = parameters[iParam].stringValue();
1731              } else if (field=="EOL") {
1732                parameters[iParam].printString();
1733                break;
1734              } else {
1735                parameters[iParam].setStringValue(field);
1736              }
1737              std::string fileName;
1738              if (field[0]=='/'||field[0]=='\\') {
1739                fileName = field;
1740              } else if (field[0]=='~') {
1741                char * environVar = getenv("HOME");
1742                if (environVar) {
1743                  std::string home(environVar);
1744                  field=field.erase(0,1);
1745                  fileName = home+field;
1746                } else {
1747                  fileName=field;
1748                }
1749              } else {
1750                fileName = directory+field;
1751              }
1752              saveSolution(models+iModel,fileName);
1753            } else {
1754              std::cout<<"** Current model not valid"<<std::endl;
1755             
1756            }
1757            break;
1758          default:
1759            abort();
1760          }
1761        } 
1762      } else if (!numberMatches) {
1763        std::cout<<"No match for "<<field<<" - ? for list of commands"
1764                 <<std::endl;
1765      } else if (numberMatches==1) {
1766        if (!numberQuery) {
1767          std::cout<<"Short match for "<<field<<" - completion: ";
1768          std::cout<<parameters[firstMatch].matchName()<<std::endl;
1769        } else if (numberQuery) {
1770          std::cout<<parameters[firstMatch].matchName()<<" : ";
1771          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
1772          if (numberQuery>=2) 
1773            parameters[firstMatch].printLongHelp();
1774        }
1775      } else {
1776        if (!numberQuery) 
1777          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
1778                   <<std::endl;
1779        else
1780          std::cout<<"Completions of "<<field<<":"<<std::endl;
1781        for ( iParam=0; iParam<numberParameters; iParam++ ) {
1782          int match = parameters[iParam].matches(field);
1783          if (match&&parameters[iParam].displayThis()) {
1784            std::cout<<parameters[iParam].matchName();
1785            if (numberQuery>=2) 
1786              std::cout<<" : "<<parameters[iParam].shortHelp();
1787            std::cout<<std::endl;
1788          }
1789        }
1790      }
1791    }
1792    delete [] models;
1793    delete [] goodModels;
1794  }
1795  // By now all memory should be freed
1796#ifdef DMALLOC
1797  dmalloc_log_unfreed();
1798  dmalloc_shutdown();
1799#endif
1800  return 0;
1801}   
1802static void breakdown(const char * name, int numberLook, const double * region)
1803{
1804  double range[] = {
1805    -COIN_DBL_MAX,
1806    -1.0e15,-1.0e11,-1.0e8,-1.0e5,-1.0e4,-1.0e3,-1.0e2,-1.0e1,
1807    -1.0,
1808    -1.0e-1,-1.0e-2,-1.0e-3,-1.0e-4,-1.0e-5,-1.0e-8,-1.0e-11,-1.0e-15,
1809    0.0,
1810    1.0e-15,1.0e-11,1.0e-8,1.0e-5,1.0e-4,1.0e-3,1.0e-2,1.0e-1,
1811    1.0,
1812    1.0e1,1.0e2,1.0e3,1.0e4,1.0e5,1.0e8,1.0e11,1.0e15,
1813    COIN_DBL_MAX};
1814  int nRanges = (int) (sizeof(range)/sizeof(double));
1815  int * number = new int[nRanges];
1816  memset(number,0,nRanges*sizeof(int));
1817  int * numberExact = new int[nRanges];
1818  memset(numberExact,0,nRanges*sizeof(int));
1819  int i;
1820  for ( i=0;i<numberLook;i++) {
1821    double value = region[i];
1822    for (int j=0;j<nRanges;j++) {
1823      if (value==range[j]) {
1824        numberExact[j]++;
1825        break;
1826      } else if (value<range[j]) {
1827        number[j]++;
1828        break;
1829      }
1830    }
1831  }
1832  printf("\n%s has %d entries\n",name,numberLook);
1833  for (i=0;i<nRanges;i++) {
1834    if (number[i]) 
1835      printf("%d between %g and %g",number[i],range[i-1],range[i]);
1836    if (numberExact[i]) {
1837      if (number[i])
1838        printf(", ");
1839      printf("%d exactly at %g",numberExact[i],range[i]);
1840    }
1841    if (number[i]+numberExact[i])
1842      printf("\n");
1843  }
1844  delete [] number;
1845  delete [] numberExact;
1846}
1847static void statistics(ClpSimplex * originalModel, ClpSimplex * model)
1848{
1849  int numberColumns = originalModel->numberColumns();
1850  const char * integerInformation  = originalModel->integerInformation(); 
1851  const double * columnLower = originalModel->columnLower();
1852  const double * columnUpper = originalModel->columnUpper();
1853  int numberIntegers=0;
1854  int numberBinary=0;
1855  int iRow,iColumn;
1856  if (integerInformation) {
1857    for (iColumn=0;iColumn<numberColumns;iColumn++) {
1858      if (integerInformation[iColumn]) {
1859        if (columnUpper[iColumn]>columnLower[iColumn]) {
1860          numberIntegers++;
1861          if (columnUpper[iColumn]==0.0&&columnLower[iColumn]==1) 
1862            numberBinary++;
1863        }
1864      }
1865    }
1866  }
1867  numberColumns = model->numberColumns();
1868  int numberRows = model->numberRows();
1869  columnLower = model->columnLower();
1870  columnUpper = model->columnUpper();
1871  const double * rowLower = model->rowLower();
1872  const double * rowUpper = model->rowUpper();
1873  const double * objective = model->objective();
1874  CoinPackedMatrix * matrix = model->matrix();
1875  CoinBigIndex numberElements = matrix->getNumElements();
1876  const int * columnLength = matrix->getVectorLengths();
1877  //const CoinBigIndex * columnStart = matrix->getVectorStarts();
1878  const double * elementByColumn = matrix->getElements();
1879  int * number = new int[numberRows+1];
1880  memset(number,0,(numberRows+1)*sizeof(int));
1881  int numberObjSingletons=0;
1882  /* cType
1883     0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up,
1884     8 0/1
1885  */ 
1886  int cType[9];
1887  std::string cName[]={"0.0->inf,","0.0->up,","lo->inf,","lo->up,","free,","fixed,","-inf->0.0,",
1888                       "-inf->up,","0.0->1.0"};
1889  int nObjective=0;
1890  memset(cType,0,sizeof(cType));
1891  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1892    int length=columnLength[iColumn];
1893    if (length==1&&objective[iColumn])
1894      numberObjSingletons++;
1895    number[length]++;
1896    if (objective[iColumn])
1897      nObjective++;
1898    if (columnLower[iColumn]>-1.0e20) {
1899      if (columnLower[iColumn]==0.0) {
1900        if (columnUpper[iColumn]>1.0e20)
1901          cType[0]++;
1902        else if (columnUpper[iColumn]==1.0)
1903          cType[8]++;
1904        else if (columnUpper[iColumn]==0.0)
1905          cType[5]++;
1906        else
1907          cType[1]++;
1908      } else {
1909        if (columnUpper[iColumn]>1.0e20) 
1910          cType[2]++;
1911        else if (columnUpper[iColumn]==columnLower[iColumn])
1912          cType[5]++;
1913        else
1914          cType[3]++;
1915      }
1916    } else {
1917      if (columnUpper[iColumn]>1.0e20) 
1918        cType[4]++;
1919      else if (columnUpper[iColumn]==0.0) 
1920        cType[6]++;
1921      else
1922        cType[7]++;
1923    }
1924  }
1925  /* rType
1926     0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other,
1927     7 L 0,  8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free
1928  */ 
1929  int rType[13];
1930  std::string rName[]={"E 0.0,","E 1.0,","E -1.0,","E other,","G 0.0,","G 1.0,","G other,",
1931                       "L 0.0,","L 1.0,","L other,","Range 0.0->1.0,","Range other,","Free"};
1932  memset(rType,0,sizeof(rType));
1933  for (iRow=0;iRow<numberRows;iRow++) {
1934    if (rowLower[iRow]>-1.0e20) {
1935      if (rowLower[iRow]==0.0) {
1936        if (rowUpper[iRow]>1.0e20)
1937          rType[4]++;
1938        else if (rowUpper[iRow]==1.0)
1939          rType[10]++;
1940        else if (rowUpper[iRow]==0.0)
1941          rType[0]++;
1942        else
1943          rType[11]++;
1944      } else if (rowLower[iRow]==1.0) {
1945        if (rowUpper[iRow]>1.0e20) 
1946          rType[5]++;
1947        else if (rowUpper[iRow]==rowLower[iRow])
1948          rType[1]++;
1949        else
1950          rType[11]++;
1951      } else if (rowLower[iRow]==-1.0) {
1952        if (rowUpper[iRow]>1.0e20) 
1953          rType[6]++;
1954        else if (rowUpper[iRow]==rowLower[iRow])
1955          rType[2]++;
1956        else
1957          rType[11]++;
1958      } else {
1959        if (rowUpper[iRow]>1.0e20) 
1960          rType[6]++;
1961        else if (rowUpper[iRow]==rowLower[iRow])
1962          rType[3]++;
1963        else
1964          rType[11]++;
1965      }
1966    } else {
1967      if (rowUpper[iRow]>1.0e20) 
1968        rType[12]++;
1969      else if (rowUpper[iRow]==0.0) 
1970        rType[7]++;
1971      else if (rowUpper[iRow]==1.0) 
1972        rType[8]++;
1973      else
1974        rType[9]++;
1975    }
1976  }
1977  // Basic statistics
1978  printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n",
1979         numberRows,numberColumns,nObjective,numberElements);
1980  if (number[0]+number[1]) {
1981    printf("There are ");
1982    if (numberObjSingletons)
1983      printf("%d singletons with objective ",numberObjSingletons);
1984    int numberNoObj = number[1]-numberObjSingletons;
1985    if (numberNoObj)
1986      printf("%d singletons with no objective ",numberNoObj);
1987    if (number[0])
1988      printf("** %d columns have no entries",number[0]);
1989    printf("\n");
1990  }
1991  printf("Column breakdown:\n");
1992  int k;
1993  for (k=0;k<(int) (sizeof(cType)/sizeof(int));k++) {
1994    printf("%d of type %s ",cType[k],cName[k].c_str());
1995    if (((k+1)%3)==0)
1996      printf("\n");
1997  }
1998  if ((k%3)!=0)
1999    printf("\n");
2000  printf("Row breakdown:\n");
2001  for (k=0;k<(int) (sizeof(rType)/sizeof(int));k++) {
2002    printf("%d of type %s ",rType[k],rName[k].c_str());
2003    if (((k+1)%3)==0)
2004      printf("\n");
2005  }
2006  if ((k%3)!=0)
2007    printf("\n");
2008  if (model->logLevel()<2)
2009    return ;
2010  int kMax = model->logLevel()>3 ? 1000000 : 10;
2011  k=0;
2012  for (iRow=1;iRow<=numberRows;iRow++) {
2013    if (number[iRow]) {
2014      k++;
2015      printf("%d columns have %d entries\n",number[iRow],iRow);
2016      if (k==kMax)
2017        break;
2018    }
2019  }
2020  if (k<numberRows) {
2021    int kk=k;
2022    k=0;
2023    for (iRow=numberRows;iRow>=1;iRow--) {
2024      if (number[iRow]) {
2025        k++;
2026        if (k==kMax)
2027          break;
2028      }
2029    }
2030    if (k>kk) {
2031      printf("\n    .........\n\n");
2032      iRow=k;
2033      k=0;
2034      for (;iRow<numberRows;iRow++) {
2035        if (number[iRow]) {
2036          k++;
2037          printf("%d columns have %d entries\n",number[iRow],iRow);
2038          if (k==kMax)
2039            break;
2040        }
2041      }
2042    }
2043  }
2044  delete [] number;
2045  printf("\n\n");
2046  // get row copy
2047  CoinPackedMatrix rowCopy = *matrix;
2048  rowCopy.reverseOrdering();
2049  //const int * column = rowCopy.getIndices();
2050  const int * rowLength = rowCopy.getVectorLengths();
2051  //const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
2052  //const double * element = rowCopy.getElements();
2053  number = new int[numberColumns+1];
2054  memset(number,0,(numberColumns+1)*sizeof(int));
2055  for (iRow=0;iRow<numberRows;iRow++) {
2056    int length=rowLength[iRow];
2057    number[length]++;
2058  }
2059  if (number[0])
2060    printf("** %d rows have no entries\n",number[0]);
2061  k=0;
2062  for (iColumn=1;iColumn<=numberColumns;iColumn++) {
2063    if (number[iColumn]) {
2064      k++;
2065      printf("%d rows have %d entries\n",number[iColumn],iColumn);
2066      if (k==kMax)
2067        break;
2068    }
2069  }
2070  if (k<numberColumns) {
2071    int kk=k;
2072    k=0;
2073    for (iColumn=numberColumns;iColumn>=1;iColumn--) {
2074      if (number[iColumn]) {
2075        k++;
2076        if (k==kMax)
2077          break;
2078      }
2079    }
2080    if (k>kk) {
2081      printf("\n    .........\n\n");
2082      iColumn=k;
2083      k=0;
2084      for (;iColumn<numberColumns;iColumn++) {
2085        if (number[iColumn]) {
2086          k++;
2087          printf("%d rows have %d entries\n",number[iColumn],iColumn);
2088          if (k==kMax)
2089            break;
2090        }
2091      }
2092    }
2093  }
2094  delete [] number;
2095  // Now do breakdown of ranges
2096  breakdown("Elements",numberElements,elementByColumn);
2097  breakdown("RowLower",numberRows,rowLower);
2098  breakdown("RowUpper",numberRows,rowUpper);
2099  breakdown("ColumnLower",numberColumns,columnLower);
2100  breakdown("ColumnUpper",numberColumns,columnUpper);
2101  breakdown("Objective",numberColumns,objective);
2102}
2103static bool maskMatches(const int * starts, char ** masks,
2104                        std::string & check)
2105{
2106  // back to char as I am old fashioned
2107  const char * checkC = check.c_str();
2108  int length = strlen(checkC);
2109  while (checkC[length-1]==' ')
2110    length--;
2111  for (int i=starts[length];i<starts[length+1];i++) {
2112    char * thisMask = masks[i];
2113    int k;
2114    for ( k=0;k<length;k++) {
2115      if (thisMask[k]!='?'&&thisMask[k]!=checkC[k]) 
2116        break;
2117    }
2118    if (k==length)
2119      return true;
2120  }
2121  return false;
2122}
2123static void clean(char * temp)
2124{
2125  char * put = temp;
2126  while (*put>=' ')
2127    put++;
2128  *put='\0';
2129}
2130static void generateCode(const char * fileName,int type)
2131{
2132  FILE * fp = fopen(fileName,"r");
2133  assert (fp);
2134  int numberLines=0;
2135#define MAXLINES 500
2136#define MAXONELINE 200
2137  char line[MAXLINES][MAXONELINE];
2138  while (fgets(line[numberLines],MAXONELINE,fp)) {
2139    assert (numberLines<MAXLINES);
2140    clean(line[numberLines]);
2141    numberLines++;
2142  }
2143  fclose(fp);
2144  // add in actual solve
2145  strcpy(line[numberLines],"5  clpModel->initialSolve(clpSolve);");
2146  numberLines++;
2147  fp = fopen(fileName,"w");
2148  assert (fp);
2149  char apo='"';   
2150  char backslash = '\\';
2151
2152  fprintf(fp,"#include %cClpSimplex.hpp%c\n",apo,apo);
2153  fprintf(fp,"#include %cClpSolve.hpp%c\n",apo,apo);
2154
2155  fprintf(fp,"\nint main (int argc, const char *argv[])\n{\n");
2156  fprintf(fp,"  ClpSimplex  model;\n");
2157  fprintf(fp,"  int status=1;\n");
2158  fprintf(fp,"  if (argc<2)\n");
2159  fprintf(fp,"    fprintf(stderr,%cPlease give file name%cn%c);\n",
2160          apo,backslash,apo);
2161  fprintf(fp,"  else\n");
2162  fprintf(fp,"    status=model.readMps(argv[1],true);\n");
2163  fprintf(fp,"  if (status) {\n");
2164  fprintf(fp,"    fprintf(stderr,%cBad readMps %%s%cn%c,argv[1]);\n",
2165                apo,backslash,apo);
2166  fprintf(fp,"    exit(1);\n");
2167  fprintf(fp,"  }\n\n");
2168  fprintf(fp,"  // Now do requested saves and modifications\n");
2169  fprintf(fp,"  ClpSimplex * clpModel = & model;\n");
2170  int wanted[9];
2171  memset(wanted,0,sizeof(wanted));
2172  wanted[0]=wanted[3]=wanted[5]=wanted[8]=1;
2173  if (type>0) 
2174    wanted[1]=wanted[6]=1;
2175  if (type>1) 
2176    wanted[2]=wanted[4]=wanted[7]=1;
2177  std::string header[9]=
2178  { "","Save values","Redundant save of default values","Set changed values",
2179    "Redundant set default values","Solve","Restore values","Redundant restore values","Add to model"};
2180  for (int iType=0;iType<9;iType++) {
2181    if (!wanted[iType])
2182      continue;
2183    int n=0;
2184    int iLine;
2185    for (iLine=0;iLine<numberLines;iLine++) {
2186      if (line[iLine][0]=='0'+iType) {
2187        if (!n)
2188          fprintf(fp,"\n  // %s\n\n",header[iType].c_str());
2189        n++;
2190        fprintf(fp,"%s\n",line[iLine]+1);
2191      }
2192    }
2193  }
2194  fprintf(fp,"\n  // Now you would use solution etc etc\n\n");
2195  fprintf(fp,"  return 0;\n}\n");
2196  fclose(fp);
2197  printf("C++ file written to %s\n",fileName);
2198}
2199/*
2200  Version 1.00.00 October 13 2004.
2201  1.00.01 October 18.  Added basis handling helped/prodded by Thorsten Koch.
2202  Also modifications to make faster with sbb (I hope I haven't broken anything).
2203  1.00.02 March 21 2005.  Redid ClpNonLinearCost to save memory also redid
2204  createRim to try and improve cache characteristics.
2205  1.00.03 April 8 2005.  Added Volume algorithm as crash and made code more
2206  robust on testing.  Also added "either" and "tune" algorithm.
2207  1.01.01 April 12 2005.  Decided to go to different numbering.  Backups will
2208  be last 2 digits while middle 2 are for improvements.  Still take a long
2209  time to get to 2.00.01
2210  1.01.02 May 4 2005.  Will be putting in many changes - so saving stable version
2211  1.02.01 May 6 2005.  Lots of changes to try and make faster and more stable in
2212  branch and cut.
2213  1.02.02 May 19 2005.  Stuff for strong branching and some improvements to simplex
2214  1.03.01 May 24 2006.  Lots done but I can't remember what!
2215  1.03.03 June 13 2006.  For clean up after dual perturbation
2216  1.04.01 June 26 2007.  Lots of changes but I got lazy
2217  1.05.00 June 27 2007.  This is trunk so when gets to stable will be 1.5
2218 */
Note: See TracBrowser for help on using the repository browser.