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

Last change on this file since 798 was 798, checked in by ladanyi, 14 years ago

finished switch to subversion

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