source: trunk/Test/CoinSolve.cpp @ 216

Last change on this file since 216 was 216, checked in by forrest, 16 years ago

add branching stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 89.5 KB
Line 
1// Copyright (C) 2004, 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// Same version as CBC
17#define CBCVERSION "1.00.01"
18
19#include "CoinMpsIO.hpp"
20
21#include "ClpFactorization.hpp"
22#include "CoinTime.hpp"
23#include "ClpSimplex.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#include "OsiRowCutDebugger.hpp"
36#ifdef DMALLOC
37#include "dmalloc.h"
38#endif
39#ifdef WSSMP_BARRIER
40#define FOREIGN_BARRIER
41#endif
42#ifdef UFL_BARRIER
43#define FOREIGN_BARRIER
44#endif
45#ifdef TAUCS_BARRIER
46#define FOREIGN_BARRIER
47#endif
48#include "CoinWarmStartBasis.hpp"
49
50#include "OsiSolverInterface.hpp"
51#include "OsiCuts.hpp"
52#include "OsiRowCut.hpp"
53#include "OsiColCut.hpp"
54
55#include "CglPreProcess.hpp"
56#include "CglCutGenerator.hpp"
57#include "CglGomory.hpp"
58#include "CglProbing.hpp"
59#include "CglKnapsackCover.hpp"
60#include "CglRedSplit.hpp"
61#include "CglClique.hpp"
62#include "CglFlowCover.hpp"
63#include "CglMixedIntegerRounding2.hpp"
64#include "CglTwomir.hpp"
65
66#include "CbcModel.hpp"
67#include "CbcHeuristic.hpp"
68#include "CbcHeuristicLocal.hpp"
69#include "CbcHeuristicGreedy.hpp"
70#include "CbcHeuristicFPump.hpp"
71#include "CbcTreeLocal.hpp"
72#include "CbcCompareActual.hpp"
73#include "CbcBranchActual.hpp"
74#include  "CbcOrClpParam.hpp"
75#include  "CbcCutGenerator.hpp"
76
77#include "OsiClpSolverInterface.hpp"
78
79static double totalTime=0.0;
80
81//#############################################################################
82
83#ifdef NDEBUG
84#undef NDEBUG
85#endif
86// Allow for interrupts
87// But is this threadsafe ? (so switched off by option)
88
89#include "CoinSignal.hpp"
90static CbcModel * currentBranchModel = NULL;
91
92extern "C" {
93   static void signal_handler(int whichSignal)
94   {
95      if (currentBranchModel!=NULL) 
96         currentBranchModel->setMaximumNodes(0); // stop at next node
97      return;
98   }
99}
100
101int mainTest (int argc, const char *argv[],int algorithm,
102              ClpSimplex empty, bool doPresolve,int switchOff);
103int CbcOrClpRead_mode=1;
104FILE * CbcOrClpReadCommand=stdin;
105static int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment,
106                     bool changeInt)
107{
108  OsiSolverInterface * solver = solverMod->clone();
109  if (0) {
110    // just get increment
111    CbcModel model(*solver);
112    model.analyzeObjective();
113    double increment2=model.getCutoffIncrement();
114    printf("initial cutoff increment %g\n",increment2);
115  }
116  const double *objective = solver->getObjCoefficients() ;
117  const double *lower = solver->getColLower() ;
118  const double *upper = solver->getColUpper() ;
119  int numberColumns = solver->getNumCols() ;
120  int numberRows = solver->getNumRows();
121  double direction = solver->getObjSense();
122  int iRow,iColumn;
123
124  // Row copy
125  CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
126  const double * elementByRow = matrixByRow.getElements();
127  const int * column = matrixByRow.getIndices();
128  const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
129  const int * rowLength = matrixByRow.getVectorLengths();
130
131  // Column copy
132  CoinPackedMatrix  matrixByCol(*solver->getMatrixByCol());
133  const double * element = matrixByCol.getElements();
134  const int * row = matrixByCol.getIndices();
135  const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
136  const int * columnLength = matrixByCol.getVectorLengths();
137
138  const double * rowLower = solver->getRowLower();
139  const double * rowUpper = solver->getRowUpper();
140
141  char * ignore = new char [numberRows];
142  int * changed = new int[numberColumns];
143  int * which = new int[numberRows];
144  double * changeRhs = new double[numberRows];
145  memset(changeRhs,0,numberRows*sizeof(double));
146  memset(ignore,0,numberRows);
147  numberChanged=0;
148  int numberInteger=0;
149  for (iColumn=0;iColumn<numberColumns;iColumn++) {
150    if (upper[iColumn] > lower[iColumn]+1.0e-8&&solver->isInteger(iColumn)) 
151      numberInteger++;
152  }
153  bool finished=false;
154  while (!finished) {
155    int saveNumberChanged = numberChanged;
156    for (iRow=0;iRow<numberRows;iRow++) {
157      int numberContinuous=0;
158      double value1=0.0,value2=0.0;
159      bool allIntegerCoeff=true;
160      double sumFixed=0.0;
161      int jColumn1=-1,jColumn2=-1;
162      for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
163        int jColumn = column[j];
164        double value = elementByRow[j];
165        if (upper[jColumn] > lower[jColumn]+1.0e-8) {
166          if (!solver->isInteger(jColumn)) {
167            if (numberContinuous==0) {
168              jColumn1=jColumn;
169              value1=value;
170            } else {
171              jColumn2=jColumn;
172              value2=value;
173            }
174            numberContinuous++;
175          } else {
176            if (fabs(value-floor(value+0.5))>1.0e-12)
177              allIntegerCoeff=false;
178          }
179        } else {
180          sumFixed += lower[jColumn]*value;
181        }
182      }
183      double low = rowLower[iRow];
184      if (low>-1.0e20) {
185        low -= sumFixed;
186        if (fabs(low-floor(low+0.5))>1.0e-12)
187          allIntegerCoeff=false;
188      }
189      double up = rowUpper[iRow];
190      if (up<1.0e20) {
191        up -= sumFixed;
192        if (fabs(up-floor(up+0.5))>1.0e-12)
193          allIntegerCoeff=false;
194      }
195      if (numberContinuous==1) {
196        // see if really integer
197        // This does not allow for complicated cases
198        if (low==up) {
199          if (fabs(value1)>1.0e-3) {
200            value1 = 1.0/value1;
201            if (fabs(value1-floor(value1+0.5))<1.0e-12) {
202              // integer
203              changed[numberChanged++]=jColumn1;
204              solver->setInteger(jColumn1);
205              if (upper[jColumn1]>1.0e20)
206                solver->setColUpper(jColumn1,1.0e20);
207              if (lower[jColumn1]<-1.0e20)
208                solver->setColLower(jColumn1,-1.0e20);
209            }
210          }
211        } else {
212          if (fabs(value1)>1.0e-3) {
213            value1 = 1.0/value1;
214            if (fabs(value1-floor(value1+0.5))<1.0e-12) {
215              // This constraint will not stop it being integer
216              ignore[iRow]=1;
217            }
218          }
219        }
220      } else if (numberContinuous==2) {
221        if (low==up) {
222          /* need general theory - for now just look at 2 cases -
223             1 - +- 1 one in column and just costs i.e. matching objective
224             2 - +- 1 two in column but feeds into G/L row which will try and minimize
225          */
226          if (fabs(value1)==1.0&&value1*value2==-1.0&&!lower[jColumn1]
227              &&!lower[jColumn2]) {
228            int n=0;
229            int i;
230            double objChange=direction*(objective[jColumn1]+objective[jColumn2]);
231            double bound = CoinMin(upper[jColumn1],upper[jColumn2]);
232            bound = CoinMin(bound,1.0e20);
233            for ( i=columnStart[jColumn1];i<columnStart[jColumn1]+columnLength[jColumn1];i++) {
234              int jRow = row[i];
235              double value = element[i];
236              if (jRow!=iRow) {
237                which[n++]=jRow;
238                changeRhs[jRow]=value;
239              }
240            }
241            for ( i=columnStart[jColumn1];i<columnStart[jColumn1]+columnLength[jColumn1];i++) {
242              int jRow = row[i];
243              double value = element[i];
244              if (jRow!=iRow) {
245                if (!changeRhs[jRow]) {
246                  which[n++]=jRow;
247                  changeRhs[jRow]=value;
248                } else {
249                  changeRhs[jRow]+=value;
250                }
251              }
252            }
253            if (objChange>=0.0) {
254              // see if all rows OK
255              bool good=true;
256              for (i=0;i<n;i++) {
257                int jRow = which[i];
258                double value = changeRhs[jRow];
259                if (value) {
260                  value *= bound;
261                  if (rowLength[jRow]==1) {
262                    if (value>0.0) {
263                      double rhs = rowLower[jRow];
264                      if (rhs>0.0) {
265                        double ratio =rhs/value;
266                        if (fabs(ratio-floor(ratio+0.5))>1.0e-12)
267                          good=false;
268                      }
269                    } else {
270                      double rhs = rowUpper[jRow];
271                      if (rhs<0.0) {
272                        double ratio =rhs/value;
273                        if (fabs(ratio-floor(ratio+0.5))>1.0e-12)
274                          good=false;
275                      }
276                    }
277                  } else if (rowLength[jRow]==2) {
278                    if (value>0.0) {
279                      if (rowLower[jRow]>-1.0e20)
280                        good=false;
281                    } else {
282                      if (rowUpper[jRow]<1.0e20)
283                        good=false;
284                    }
285                  } else {
286                    good=false;
287                  }
288                }
289              }
290              if (good) {
291                // both can be integer
292                changed[numberChanged++]=jColumn1;
293                solver->setInteger(jColumn1);
294                if (upper[jColumn1]>1.0e20)
295                  solver->setColUpper(jColumn1,1.0e20);
296                if (lower[jColumn1]<-1.0e20)
297                  solver->setColLower(jColumn1,-1.0e20);
298                changed[numberChanged++]=jColumn2;
299                solver->setInteger(jColumn2);
300                if (upper[jColumn2]>1.0e20)
301                  solver->setColUpper(jColumn2,1.0e20);
302                if (lower[jColumn2]<-1.0e20)
303                  solver->setColLower(jColumn2,-1.0e20);
304              }
305            }
306            // clear
307            for (i=0;i<n;i++) {
308              changeRhs[which[i]]=0.0;
309            }
310          }
311        }
312      }
313    }
314    for (iColumn=0;iColumn<numberColumns;iColumn++) {
315      if (upper[iColumn] > lower[iColumn]+1.0e-8&&!solver->isInteger(iColumn)) {
316        double value;
317        value = upper[iColumn];
318        if (value<1.0e20&&fabs(value-floor(value+0.5))>1.0e-12) 
319          continue;
320        value = lower[iColumn];
321        if (value>-1.0e20&&fabs(value-floor(value+0.5))>1.0e-12) 
322          continue;
323        bool integer=true;
324        for (CoinBigIndex j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) {
325          int iRow = row[j];
326          if (!ignore[iRow]) {
327            integer=false;
328            break;
329          }
330        }
331        if (integer) {
332          // integer
333          changed[numberChanged++]=iColumn;
334          solver->setInteger(iColumn);
335          if (upper[iColumn]>1.0e20)
336            solver->setColUpper(iColumn,1.0e20);
337          if (lower[iColumn]<-1.0e20)
338            solver->setColLower(iColumn,-1.0e20);
339        }
340      }
341    }
342    finished = numberChanged==saveNumberChanged;
343  }
344  delete [] which;
345  delete [] changeRhs;
346  delete [] ignore;
347  if (numberInteger)
348    printf("%d integer variables",numberInteger);
349  if (changeInt) {
350    if (numberChanged)
351      printf(" and %d variables made integer\n",numberChanged);
352    else
353      printf("\n");
354    delete [] ignore;
355    //increment=0.0;
356    if (!numberChanged) {
357      delete [] changed;
358      delete solver;
359      return NULL;
360    } else {
361      for (iColumn=0;iColumn<numberColumns;iColumn++) {
362        if (solver->isInteger(iColumn))
363          solverMod->setInteger(iColumn);
364      }
365      delete solver;
366      return changed;
367    }
368  } else {
369    if (numberChanged)
370      printf(" and %d variables could be made integer\n",numberChanged);
371    else
372      printf("\n");
373    // just get increment
374    CbcModel model(*solver);
375    model.analyzeObjective();
376    double increment2=model.getCutoffIncrement();
377    if (increment2>increment) {
378      printf("cutoff increment increased from %g to %g\n",increment,increment2);
379      increment=increment2;
380    }
381    delete solver;
382    numberChanged=0;
383    return NULL;
384  }
385}
386int main (int argc, const char *argv[])
387{
388  /* Note
389     This is meant as a stand-alone executable to do as much of coin as possible.
390     It should only have one solver known to it.
391  */
392  {
393    double time1 = CoinCpuTime(),time2;
394    CoinSighandler_t saveSignal=SIG_DFL;
395    // register signal handler
396    saveSignal = signal(SIGINT,signal_handler);
397    // Set up all non-standard stuff
398    OsiClpSolverInterface solver1;
399    CbcModel model(solver1);
400    CbcModel * babModel = NULL;
401    model.setNumberBeforeTrust(21);
402    int cutPass=-1234567;
403    OsiSolverInterface * solver = model.solver();
404    OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
405    ClpSimplex * lpSolver = clpSolver->getModelPtr();
406    clpSolver->messageHandler()->setLogLevel(0) ;
407    model.messageHandler()->setLogLevel(1);
408   
409   
410    // default action on import
411    int allowImportErrors=0;
412    int keepImportNames=1;
413    int doIdiot=-1;
414    int outputFormat=2;
415    int slpValue=-1;
416    int printOptions=0;
417    int printMode=0;
418    int presolveOptions=0;
419    int doCrash=0;
420    int doSprint=-1;
421    int doScaling=1;
422    // set reasonable defaults
423    int preSolve=5;
424    int preProcess=4;
425    bool preSolveFile=false;
426   
427    double djFix=1.0e100;
428    double gapRatio=1.0e100;
429    double tightenFactor=0.0;
430    lpSolver->setPerturbation(50);
431    lpSolver->messageHandler()->setPrefix(false);
432    const char dirsep =  CoinFindDirSeparator();
433    std::string directory = (dirsep == '/' ? "./" : ".\\");
434    std::string defaultDirectory = directory;
435    std::string importFile ="";
436    std::string exportFile ="default.mps";
437    std::string importBasisFile ="";
438    std::string debugFile="";
439    double * debugValues = NULL;
440    int numberDebugValues = -1;
441    int basisHasValues=0;
442    std::string exportBasisFile ="default.bas";
443    std::string saveFile ="default.prob";
444    std::string restoreFile ="default.prob";
445    std::string solutionFile ="stdout";
446    std::string solutionSaveFile ="solution.file";
447#define CBCMAXPARAMETERS 200
448    CbcOrClpParam parameters[CBCMAXPARAMETERS];
449    int numberParameters ;
450    establishParams(numberParameters,parameters) ;
451    parameters[whichParam(BASISIN,numberParameters,parameters)].setStringValue(importBasisFile);
452    parameters[whichParam(BASISOUT,numberParameters,parameters)].setStringValue(exportBasisFile);
453    parameters[whichParam(DEBUG,numberParameters,parameters)].setStringValue(debugFile);
454    parameters[whichParam(DIRECTORY,numberParameters,parameters)].setStringValue(directory);
455    parameters[whichParam(DUALBOUND,numberParameters,parameters)].setDoubleValue(lpSolver->dualBound());
456    parameters[whichParam(DUALTOLERANCE,numberParameters,parameters)].setDoubleValue(lpSolver->dualTolerance());
457    parameters[whichParam(EXPORT,numberParameters,parameters)].setStringValue(exportFile);
458    parameters[whichParam(IDIOT,numberParameters,parameters)].setIntValue(doIdiot);
459    parameters[whichParam(IMPORT,numberParameters,parameters)].setStringValue(importFile);
460    int slog = whichParam(SOLVERLOGLEVEL,numberParameters,parameters);
461    int log = whichParam(LOGLEVEL,numberParameters,parameters);
462    parameters[slog].setIntValue(0);
463    parameters[log].setIntValue(1);
464    parameters[whichParam(MAXFACTOR,numberParameters,parameters)].setIntValue(lpSolver->factorizationFrequency());
465    parameters[whichParam(MAXITERATION,numberParameters,parameters)].setIntValue(lpSolver->maximumIterations());
466    parameters[whichParam(OUTPUTFORMAT,numberParameters,parameters)].setIntValue(outputFormat);
467    parameters[whichParam(PRESOLVEPASS,numberParameters,parameters)].setIntValue(preSolve);
468    parameters[whichParam(PERTVALUE,numberParameters,parameters)].setIntValue(lpSolver->perturbation());
469    parameters[whichParam(PRIMALTOLERANCE,numberParameters,parameters)].setDoubleValue(lpSolver->primalTolerance());
470    parameters[whichParam(PRIMALWEIGHT,numberParameters,parameters)].setDoubleValue(lpSolver->infeasibilityCost());
471    parameters[whichParam(RESTORE,numberParameters,parameters)].setStringValue(restoreFile);
472    parameters[whichParam(SAVE,numberParameters,parameters)].setStringValue(saveFile);
473    //parameters[whichParam(TIMELIMIT,numberParameters,parameters)].setDoubleValue(1.0e8);
474    parameters[whichParam(TIMELIMIT_BAB,numberParameters,parameters)].setDoubleValue(1.0e8);
475    parameters[whichParam(SOLUTION,numberParameters,parameters)].setStringValue(solutionFile);
476    parameters[whichParam(SAVESOL,numberParameters,parameters)].setStringValue(solutionSaveFile);
477    parameters[whichParam(SPRINT,numberParameters,parameters)].setIntValue(doSprint);
478    model.setNumberBeforeTrust(5);
479    parameters[whichParam(NUMBERBEFORE,numberParameters,parameters)].setIntValue(5);
480    parameters[whichParam(MAXNODES,numberParameters,parameters)].setIntValue(model.getMaximumNodes());
481    model.setNumberStrong(5);
482    parameters[whichParam(STRONGBRANCHING,numberParameters,parameters)].setIntValue(model.numberStrong());
483    parameters[whichParam(INFEASIBILITYWEIGHT,numberParameters,parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcInfeasibilityWeight));
484    parameters[whichParam(INTEGERTOLERANCE,numberParameters,parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcIntegerTolerance));
485    parameters[whichParam(INCREMENT,numberParameters,parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcCutoffIncrement));
486    // Set up likely cut generators and defaults
487    parameters[whichParam(PREPROCESS,numberParameters,parameters)].setCurrentOption("sos");
488
489    CglGomory gomoryGen;
490    // try larger limit
491    gomoryGen.setLimitAtRoot(512);
492    gomoryGen.setLimit(50);
493    // set default action (0=off,1=on,2=root)
494    int gomoryAction=3;
495    parameters[whichParam(GOMORYCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
496
497    CglProbing probingGen;
498    probingGen.setUsingObjective(true);
499    probingGen.setMaxPass(3);
500    probingGen.setMaxPassRoot(3);
501    // Number of unsatisfied variables to look at
502    probingGen.setMaxProbe(10);
503    probingGen.setMaxProbeRoot(50);
504    // How far to follow the consequences
505    probingGen.setMaxLook(10);
506    probingGen.setMaxLookRoot(50);
507    probingGen.setMaxLookRoot(10);
508    // Only look at rows with fewer than this number of elements
509    probingGen.setMaxElements(200);
510    probingGen.setRowCuts(3);
511    // set default action (0=off,1=on,2=root)
512    int probingAction=3;
513    parameters[whichParam(PROBINGCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
514
515    CglKnapsackCover knapsackGen;
516    // set default action (0=off,1=on,2=root)
517    int knapsackAction=3;
518    parameters[whichParam(KNAPSACKCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
519
520    CglRedSplit redsplitGen;
521    //redsplitGen.setLimit(100);
522    // set default action (0=off,1=on,2=root)
523    // Off as seems to give some bad cuts
524    int redsplitAction=2;
525    parameters[whichParam(REDSPLITCUTS,numberParameters,parameters)].setCurrentOption("root");
526
527    CglClique cliqueGen(false,true);
528    cliqueGen.setStarCliqueReport(false);
529    cliqueGen.setRowCliqueReport(false);
530    cliqueGen.setMinViolation(0.1);
531    // set default action (0=off,1=on,2=root)
532    int cliqueAction=3;
533    parameters[whichParam(CLIQUECUTS,numberParameters,parameters)].setCurrentOption("ifmove");
534
535    CglMixedIntegerRounding2 mixedGen;
536    // set default action (0=off,1=on,2=root)
537    int mixedAction=3;
538    parameters[whichParam(MIXEDCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
539
540    CglFlowCover flowGen;
541    // set default action (0=off,1=on,2=root)
542    int flowAction=3;
543    parameters[whichParam(FLOWCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
544
545    CglTwomir twomirGen;
546    twomirGen.setMaxElements(250);
547    // set default action (0=off,1=on,2=root)
548    int twomirAction=2;
549    parameters[whichParam(TWOMIRCUTS,numberParameters,parameters)].setCurrentOption("root");
550
551    bool useRounding=true;
552    parameters[whichParam(ROUNDING,numberParameters,parameters)].setCurrentOption("on");
553    bool useFpump=true;
554    bool useGreedy=true;
555    parameters[whichParam(GREEDY,numberParameters,parameters)].setCurrentOption("on");
556    bool useCombine=true;
557    parameters[whichParam(COMBINE,numberParameters,parameters)].setCurrentOption("on");
558    bool useLocalTree=false;
559    parameters[whichParam(COSTSTRATEGY,numberParameters,parameters)].setCurrentOption("off");
560    bool useCosts=false;
561   
562    // total number of commands read
563    int numberGoodCommands=0;
564    bool goodModel=false;
565    // Set false if user does anything advanced
566    bool defaultSettings=true;
567
568    // Hidden stuff for barrier
569    int choleskyType = 0;
570    int gamma=0;
571    int scaleBarrier=0;
572    int doKKT=0;
573    int crossover=2; // do crossover unless quadratic
574    // For names
575    int lengthName = 0;
576    std::vector<std::string> rowNames;
577    std::vector<std::string> columnNames;
578   
579    std::string field;
580    std::cout<<"Coin Cbc and Clp Solver version "<<CBCVERSION
581             <<", build "<<__DATE__<<std::endl;
582   
583    while (1) {
584      // next command
585      field=CoinReadGetCommand(argc,argv);
586     
587      // exit if null or similar
588      if (!field.length()) {
589        if (numberGoodCommands==1&&goodModel) {
590          // we just had file name - do branch and bound
591          field="branch";
592        } else if (!numberGoodCommands) {
593          // let's give the sucker a hint
594          std::cout
595            <<"CoinSolver takes input from arguments ( - switches to stdin)"
596            <<std::endl
597            <<"Enter ? for list of commands or help"<<std::endl;
598          field="-";
599        } else {
600          break;
601        }
602      }
603     
604      // see if ? at end
605      int numberQuery=0;
606      if (field!="?"&&field!="???") {
607        int length = field.length();
608        int i;
609        for (i=length-1;i>0;i--) {
610          if (field[i]=='?') 
611            numberQuery++;
612          else
613            break;
614        }
615        field=field.substr(0,length-numberQuery);
616      }
617      // find out if valid command
618      int iParam;
619      int numberMatches=0;
620      int firstMatch=-1;
621      for ( iParam=0; iParam<numberParameters; iParam++ ) {
622        int match = parameters[iParam].matches(field);
623        if (match==1) {
624          numberMatches = 1;
625          firstMatch=iParam;
626          break;
627        } else {
628          if (match&&firstMatch<0)
629            firstMatch=iParam;
630          numberMatches += match>>1;
631        }
632      }
633      if (iParam<numberParameters&&!numberQuery) {
634        // found
635        CbcOrClpParam found = parameters[iParam];
636        CbcOrClpParameterType type = found.type();
637        int valid;
638        numberGoodCommands++;
639        if (type==BAB&&goodModel) {
640          // check if any integers
641          if (!lpSolver->integerInformation())
642            type=DUALSIMPLEX;
643        }
644        if (type==GENERALQUERY) {
645          std::cout<<"In argument list keywords have leading - "
646            ", -stdin or just - switches to stdin"<<std::endl;
647          std::cout<<"One command per line (and no -)"<<std::endl;
648          std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
649          std::cout<<"abcd?? adds explanation, if only one fuller help"<<std::endl;
650          std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
651          std::cout<<"abcd value sets value"<<std::endl;
652          std::cout<<"Commands are:"<<std::endl;
653          int maxAcross=5;
654          int limits[]={1,51,101,151,201,251,301,351,401};
655          std::vector<std::string> types;
656          types.push_back("Double parameters:");
657          types.push_back("Branch and Cut double parameters:");
658          types.push_back("Integer parameters:");
659          types.push_back("Branch and Cut integer parameters:");
660          types.push_back("Keyword parameters and others:");
661          types.push_back("Branch and Cut keyword parameters and others:");
662          types.push_back("Actions:");
663          types.push_back("Branch and Cut actions:");
664          int iType;
665          for (iType=0;iType<8;iType++) {
666            int across=0;
667            std::cout<<types[iType]<<"   ";
668            for ( iParam=0; iParam<numberParameters; iParam++ ) {
669              int type = parameters[iParam].type();
670              if (parameters[iParam].displayThis()&&type>=limits[iType]
671                  &&type<limits[iType+1]) {
672                if (!across)
673                  std::cout<<"  ";
674                std::cout<<parameters[iParam].matchName()<<"  ";
675                across++;
676                if (across==maxAcross) {
677                  std::cout<<std::endl;
678                  across=0;
679                }
680              }
681            }
682            if (across)
683              std::cout<<std::endl;
684          }
685        } else if (type==FULLGENERALQUERY) {
686          std::cout<<"Full list of commands is:"<<std::endl;
687          int maxAcross=5;
688          int limits[]={1,51,101,151,201,251,301,351,401};
689          std::vector<std::string> types;
690          types.push_back("Double parameters:");
691          types.push_back("Branch and Cut double parameters:");
692          types.push_back("Integer parameters:");
693          types.push_back("Branch and Cut integer parameters:");
694          types.push_back("Keyword parameters and others:");
695          types.push_back("Branch and Cut keyword parameters and others:");
696          types.push_back("Actions:");
697          types.push_back("Branch and Cut actions:");
698          int iType;
699          for (iType=0;iType<8;iType++) {
700            int across=0;
701            std::cout<<types[iType]<<"  ";
702            for ( iParam=0; iParam<numberParameters; iParam++ ) {
703              int type = parameters[iParam].type();
704              if (type>=limits[iType]
705                  &&type<limits[iType+1]) {
706                if (!across)
707                  std::cout<<"  ";
708                std::cout<<parameters[iParam].matchName()<<"  ";
709                across++;
710                if (across==maxAcross) {
711                  std::cout<<std::endl;
712                  across=0;
713                }
714              }
715            }
716            if (across)
717              std::cout<<std::endl;
718          }
719        } else if (type<101) {
720          // get next field as double
721          double value = CoinReadGetDoubleField(argc,argv,&valid);
722          if (!valid) {
723            parameters[iParam].setDoubleValue(value);
724            if (type<51) {
725              parameters[iParam].setDoubleParameter(lpSolver,value);
726            } else if (type<81) {
727              parameters[iParam].setDoubleParameter(model,value);
728            } else {
729              switch(type) {
730              case DJFIX:
731                djFix=value;
732                preSolve=5;
733                defaultSettings=false; // user knows what she is doing
734                break;
735              case GAPRATIO:
736                gapRatio=value;
737                break;
738              case TIGHTENFACTOR:
739                tightenFactor=value;
740                defaultSettings=false; // user knows what she is doing
741                break;
742              default:
743                abort();
744              }
745            }
746          } else if (valid==1) {
747            abort();
748          } else {
749            std::cout<<parameters[iParam].name()<<" has value "<<
750              parameters[iParam].doubleValue()<<std::endl;
751          }
752        } else if (type<201) {
753          // get next field as int
754          int value = CoinReadGetIntField(argc,argv,&valid);
755          if (!valid) {
756            parameters[iParam].setIntValue(value);
757            if (type<151) {
758              if (parameters[iParam].type()==PRESOLVEPASS)
759                preSolve = value;
760              else if (parameters[iParam].type()==IDIOT)
761                doIdiot = value;
762              else if (parameters[iParam].type()==SPRINT)
763                doSprint = value;
764              else if (parameters[iParam].type()==OUTPUTFORMAT)
765                outputFormat = value;
766              else if (parameters[iParam].type()==SLPVALUE)
767                slpValue = value;
768              else if (parameters[iParam].type()==PRESOLVEOPTIONS)
769                presolveOptions = value;
770              else if (parameters[iParam].type()==PRINTOPTIONS)
771                printOptions = value;
772              else if (parameters[iParam].type()==CUTPASS)
773                cutPass = value;
774              else if (parameters[iParam].type()==FPUMPITS)
775                { useFpump = true;parameters[iParam].setIntValue(value);}
776              else
777                parameters[iParam].setIntParameter(lpSolver,value);
778            } else {
779              parameters[iParam].setIntParameter(model,value);
780            }
781          } else if (valid==1) {
782            abort();
783          } else {
784            std::cout<<parameters[iParam].name()<<" has value "<<
785              parameters[iParam].intValue()<<std::endl;
786          }
787        } else if (type<301) {
788          // one of several strings
789          std::string value = CoinReadGetString(argc,argv);
790          int action = parameters[iParam].parameterOption(value);
791          if (action<0) {
792            if (value!="EOL") {
793              // no match
794              parameters[iParam].printOptions();
795            } else {
796              // print current value
797              std::cout<<parameters[iParam].name()<<" has value "<<
798                parameters[iParam].currentOption()<<std::endl;
799            }
800          } else {
801            parameters[iParam].setCurrentOption(action);
802            // for now hard wired
803            switch (type) {
804            case DIRECTION:
805              if (action==0)
806                lpSolver->setOptimizationDirection(1);
807              else if (action==1)
808                lpSolver->setOptimizationDirection(-1);
809              else
810                lpSolver->setOptimizationDirection(0);
811              break;
812            case DUALPIVOT:
813              if (action==0) {
814                ClpDualRowSteepest steep(3);
815                lpSolver->setDualRowPivotAlgorithm(steep);
816              } else if (action==1) {
817                //ClpDualRowDantzig dantzig;
818                ClpDualRowSteepest dantzig(5);
819                lpSolver->setDualRowPivotAlgorithm(dantzig);
820              } else if (action==2) {
821                // partial steep
822                ClpDualRowSteepest steep(2);
823                lpSolver->setDualRowPivotAlgorithm(steep);
824              } else {
825                ClpDualRowSteepest steep;
826                lpSolver->setDualRowPivotAlgorithm(steep);
827              }
828              break;
829            case PRIMALPIVOT:
830              if (action==0) {
831                ClpPrimalColumnSteepest steep(3);
832                lpSolver->setPrimalColumnPivotAlgorithm(steep);
833              } else if (action==1) {
834                ClpPrimalColumnSteepest steep(0);
835                lpSolver->setPrimalColumnPivotAlgorithm(steep);
836              } else if (action==2) {
837                ClpPrimalColumnDantzig dantzig;
838                lpSolver->setPrimalColumnPivotAlgorithm(dantzig);
839              } else if (action==3) {
840                ClpPrimalColumnSteepest steep(2);
841                lpSolver->setPrimalColumnPivotAlgorithm(steep);
842              } else if (action==4) {
843                ClpPrimalColumnSteepest steep(1);
844                lpSolver->setPrimalColumnPivotAlgorithm(steep);
845              } else if (action==5) {
846                ClpPrimalColumnSteepest steep(4);
847                lpSolver->setPrimalColumnPivotAlgorithm(steep);
848              } else if (action==6) {
849                ClpPrimalColumnSteepest steep(10);
850                lpSolver->setPrimalColumnPivotAlgorithm(steep);
851              }
852              break;
853            case SCALING:
854              lpSolver->scaling(action);
855              solver->setHintParam(OsiDoScale,action!=0,OsiHintTry);
856              doScaling = 1-action;
857              break;
858            case AUTOSCALE:
859              lpSolver->setAutomaticScaling(action!=0);
860              break;
861            case SPARSEFACTOR:
862              lpSolver->setSparseFactorization((1-action)!=0);
863              break;
864            case BIASLU:
865              lpSolver->factorization()->setBiasLU(action);
866              break;
867            case PERTURBATION:
868              if (action==0)
869                lpSolver->setPerturbation(50);
870              else
871                lpSolver->setPerturbation(100);
872              break;
873            case ERRORSALLOWED:
874              allowImportErrors = action;
875              break;
876            case INTPRINT:
877              printMode=action;
878              break;
879              //case ALGORITHM:
880              //algorithm  = action;
881              //defaultSettings=false; // user knows what she is doing
882              //abort();
883              //break;
884            case KEEPNAMES:
885              keepImportNames = 1-action;
886              break;
887            case PRESOLVE:
888              if (action==0)
889                preSolve = 5;
890              else if (action==1)
891                preSolve=0;
892              else if (action==2)
893                preSolve=10;
894              else
895                preSolveFile=true;
896              break;
897            case PFI:
898              lpSolver->factorization()->setForrestTomlin(action==0);
899              break;
900            case CRASH:
901              doCrash=action;
902              break;
903            case MESSAGES:
904              lpSolver->messageHandler()->setPrefix(action!=0);
905              break;
906            case CHOLESKY:
907              choleskyType = action;
908              break;
909            case GAMMA:
910              gamma=action;
911              break;
912            case BARRIERSCALE:
913              scaleBarrier=action;
914              break;
915            case KKT:
916              doKKT=action;
917              break;
918            case CROSSOVER:
919              crossover=action;
920              break;
921            case GOMORYCUTS:
922              defaultSettings=false; // user knows what she is doing
923              gomoryAction = action;
924              break;
925            case PROBINGCUTS:
926              defaultSettings=false; // user knows what she is doing
927              probingAction = action;
928              break;
929            case KNAPSACKCUTS:
930              defaultSettings=false; // user knows what she is doing
931              knapsackAction = action;
932              break;
933            case REDSPLITCUTS:
934              defaultSettings=false; // user knows what she is doing
935              redsplitAction = action;
936              break;
937            case CLIQUECUTS:
938              defaultSettings=false; // user knows what she is doing
939              cliqueAction = action;
940              break;
941            case FLOWCUTS:
942              defaultSettings=false; // user knows what she is doing
943              flowAction = action;
944              break;
945            case MIXEDCUTS:
946              defaultSettings=false; // user knows what she is doing
947              mixedAction = action;
948              break;
949            case TWOMIRCUTS:
950              defaultSettings=false; // user knows what she is doing
951              twomirAction = action;
952              break;
953            case ROUNDING:
954              defaultSettings=false; // user knows what she is doing
955              useRounding = action;
956              break;
957            case FPUMP:
958              defaultSettings=false; // user knows what she is doing
959              useFpump=action;
960              break;
961            case CUTSSTRATEGY:
962              gomoryAction = action;
963              probingAction = action;
964              knapsackAction = action;
965              cliqueAction = action;
966              flowAction = action;
967              mixedAction = action;
968              twomirAction = action;
969              parameters[whichParam(GOMORYCUTS,numberParameters,parameters)].setCurrentOption(action);
970              parameters[whichParam(PROBINGCUTS,numberParameters,parameters)].setCurrentOption(action);
971              parameters[whichParam(KNAPSACKCUTS,numberParameters,parameters)].setCurrentOption(action);
972              if (!action) {
973                redsplitAction = action;
974                parameters[whichParam(REDSPLITCUTS,numberParameters,parameters)].setCurrentOption(action);
975              }
976              parameters[whichParam(CLIQUECUTS,numberParameters,parameters)].setCurrentOption(action);
977              parameters[whichParam(FLOWCUTS,numberParameters,parameters)].setCurrentOption(action);
978              parameters[whichParam(MIXEDCUTS,numberParameters,parameters)].setCurrentOption(action);
979              parameters[whichParam(TWOMIRCUTS,numberParameters,parameters)].setCurrentOption(action);
980              break;
981            case HEURISTICSTRATEGY:
982              useRounding = action;
983              useGreedy = action;
984              useCombine = action;
985              //useLocalTree = action;
986              useFpump=action;
987              parameters[whichParam(ROUNDING,numberParameters,parameters)].setCurrentOption(action);
988              parameters[whichParam(GREEDY,numberParameters,parameters)].setCurrentOption(action);
989              parameters[whichParam(COMBINE,numberParameters,parameters)].setCurrentOption(action);
990              //parameters[whichParam(LOCALTREE,numberParameters,parameters)].setCurrentOption(action);
991              parameters[whichParam(FPUMP,numberParameters,parameters)].setCurrentOption(action);
992              break;
993            case GREEDY:
994              defaultSettings=false; // user knows what she is doing
995              useGreedy = action;
996              break;
997            case COMBINE:
998              defaultSettings=false; // user knows what she is doing
999              useCombine = action;
1000              break;
1001            case LOCALTREE:
1002              defaultSettings=false; // user knows what she is doing
1003              useLocalTree = action;
1004              break;
1005            case COSTSTRATEGY:
1006              if (action!=1&&action!=0) {
1007                printf("Pseudo costs not implemented yet\n");
1008              } else {
1009                useCosts=action;
1010              }
1011              break;
1012            case PREPROCESS:
1013              preProcess = action;
1014              break;
1015            default:
1016              abort();
1017            }
1018          }
1019        } else {
1020          // action
1021          if (type==EXIT)
1022            break; // stop all
1023          switch (type) {
1024          case DUALSIMPLEX:
1025          case PRIMALSIMPLEX:
1026          case SOLVECONTINUOUS:
1027          case BARRIER:
1028            if (goodModel) {
1029              ClpSolve::SolveType method;
1030              ClpSolve::PresolveType presolveType;
1031              ClpSimplex * model2 = lpSolver;
1032              ClpSolve solveOptions;
1033              if (preSolve!=5&&preSolve)
1034                presolveType=ClpSolve::presolveNumber;
1035              else if (preSolve)
1036                presolveType=ClpSolve::presolveOn;
1037              else
1038                presolveType=ClpSolve::presolveOff;
1039              solveOptions.setPresolveType(presolveType,preSolve);
1040              if (type==DUALSIMPLEX||SOLVECONTINUOUS) {
1041                method=ClpSolve::useDual;
1042              } else if (type==PRIMALSIMPLEX) {
1043                method=ClpSolve::usePrimalorSprint;
1044              } else {
1045                method = ClpSolve::useBarrier;
1046                if (crossover==1) {
1047                  method=ClpSolve::useBarrierNoCross;
1048                } else if (crossover==2) {
1049                  ClpObjective * obj = lpSolver->objectiveAsObject();
1050                  if (obj->type()>1) {
1051                    method=ClpSolve::useBarrierNoCross;
1052                    presolveType=ClpSolve::presolveOff;
1053                    solveOptions.setPresolveType(presolveType,preSolve);
1054                  } 
1055                }
1056              }
1057              solveOptions.setSolveType(method);
1058              if(preSolveFile)
1059                presolveOptions |= 0x40000000;
1060              solveOptions.setSpecialOption(4,presolveOptions);
1061              solveOptions.setSpecialOption(5,printOptions);
1062              if (method==ClpSolve::useDual) {
1063                // dual
1064                if (doCrash)
1065                  solveOptions.setSpecialOption(0,1,doCrash); // crash
1066                else if (doIdiot)
1067                  solveOptions.setSpecialOption(0,2,doIdiot); // possible idiot
1068              } else if (method==ClpSolve::usePrimalorSprint) {
1069                // primal
1070                // if slp turn everything off
1071                if (slpValue>0) {
1072                  doCrash=false;
1073                  doSprint=0;
1074                  doIdiot=-1;
1075                  solveOptions.setSpecialOption(1,10,slpValue); // slp
1076                  method=ClpSolve::usePrimal;
1077                }
1078                if (doCrash) {
1079                  solveOptions.setSpecialOption(1,1,doCrash); // crash
1080                } else if (doSprint>0) {
1081                  // sprint overrides idiot
1082                  solveOptions.setSpecialOption(1,3,doSprint); // sprint
1083                } else if (doIdiot>0) {
1084                  solveOptions.setSpecialOption(1,2,doIdiot); // idiot
1085                } else if (slpValue<=0) {
1086                  if (doIdiot==0) {
1087                    if (doSprint==0)
1088                      solveOptions.setSpecialOption(1,4); // all slack
1089                    else
1090                      solveOptions.setSpecialOption(1,9); // all slack or sprint
1091                  } else {
1092                    if (doSprint==0)
1093                      solveOptions.setSpecialOption(1,8); // all slack or idiot
1094                    else
1095                      solveOptions.setSpecialOption(1,7); // initiative
1096                  }
1097                }
1098                if (basisHasValues==-1)
1099                  solveOptions.setSpecialOption(1,11); // switch off values
1100              } else if (method==ClpSolve::useBarrier||method==ClpSolve::useBarrierNoCross) {
1101                int barrierOptions = choleskyType;
1102                if (scaleBarrier)
1103                  barrierOptions |= 8;
1104                if (gamma)
1105                  barrierOptions |= 16;
1106                if (doKKT)
1107                  barrierOptions |= 32;
1108                solveOptions.setSpecialOption(4,barrierOptions);
1109              }
1110              model2->initialSolve(solveOptions);
1111              basisHasValues=1;
1112            } else {
1113              std::cout<<"** Current model not valid"<<std::endl;
1114            }
1115            break;
1116          case TIGHTEN:
1117            if (goodModel) {
1118              int numberInfeasibilities = lpSolver->tightenPrimalBounds();
1119              if (numberInfeasibilities)
1120                std::cout<<"** Analysis indicates model infeasible"<<std::endl;
1121            } else {
1122              std::cout<<"** Current model not valid"<<std::endl;
1123            }
1124            break;
1125          case PLUSMINUS:
1126            if (goodModel) {
1127              ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
1128              ClpPackedMatrix* clpMatrix =
1129                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1130              if (clpMatrix) {
1131                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
1132                if (newMatrix->getIndices()) {
1133                  lpSolver->replaceMatrix(newMatrix);
1134                  delete saveMatrix;
1135                  std::cout<<"Matrix converted to +- one matrix"<<std::endl;
1136                } else {
1137                  std::cout<<"Matrix can not be converted to +- 1 matrix"<<std::endl;
1138                }
1139              } else {
1140                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1141              }
1142            } else {
1143              std::cout<<"** Current model not valid"<<std::endl;
1144            }
1145            break;
1146          case NETWORK:
1147            if (goodModel) {
1148              ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
1149              ClpPackedMatrix* clpMatrix =
1150                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1151              if (clpMatrix) {
1152                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
1153                if (newMatrix->getIndices()) {
1154                  lpSolver->replaceMatrix(newMatrix);
1155                  delete saveMatrix;
1156                  std::cout<<"Matrix converted to network matrix"<<std::endl;
1157                } else {
1158                  std::cout<<"Matrix can not be converted to network matrix"<<std::endl;
1159                }
1160              } else {
1161                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1162              }
1163            } else {
1164              std::cout<<"** Current model not valid"<<std::endl;
1165            }
1166            break;
1167/*
1168  Run branch-and-cut. First set a few options -- node comparison, scaling. If
1169  the solver is Clp, consider running some presolve code (not yet converted
1170  this to generic OSI) with branch-and-cut. If presolve is disabled, or the
1171  solver is not Clp, simply run branch-and-cut. Print elapsed time at the end.
1172*/
1173          case BAB: // branchAndBound
1174          case STRENGTHEN:
1175            if (goodModel) {
1176              model.initialSolve();
1177              // If user made settings then use them
1178              if (!defaultSettings) {
1179                OsiSolverInterface * solver = model.solver();
1180                if (!doScaling)
1181                  solver->setHintParam(OsiDoScale,false,OsiHintTry);
1182                OsiClpSolverInterface * si =
1183                  dynamic_cast<OsiClpSolverInterface *>(solver) ;
1184                assert (si != NULL);
1185                // get clp itself
1186                ClpSimplex * modelC = si->getModelPtr();
1187                //if (modelC->tightenPrimalBounds()!=0) {
1188                //std::cout<<"Problem is infeasible!"<<std::endl;
1189                //break;
1190                //}
1191                // bounds based on continuous
1192                if (tightenFactor) {
1193                  if (modelC->tightenPrimalBounds(tightenFactor)!=0) {
1194                    std::cout<<"Problem is infeasible!"<<std::endl;
1195                    break;
1196                  }
1197                }
1198                if (djFix<1.0e20) {
1199                  // do some fixing
1200                  int numberColumns = modelC->numberColumns();
1201                  int i;
1202                  const char * type = modelC->integerInformation();
1203                  double * lower = modelC->columnLower();
1204                  double * upper = modelC->columnUpper();
1205                  double * solution = modelC->primalColumnSolution();
1206                  double * dj = modelC->dualColumnSolution();
1207                  int numberFixed=0;
1208                  for (i=0;i<numberColumns;i++) {
1209                    if (type[i]) {
1210                      double value = solution[i];
1211                      if (value<lower[i]+1.0e-5&&dj[i]>djFix) {
1212                        solution[i]=lower[i];
1213                        upper[i]=lower[i];
1214                        numberFixed++;
1215                      } else if (value>upper[i]-1.0e-5&&dj[i]<-djFix) {
1216                        solution[i]=upper[i];
1217                        lower[i]=upper[i];
1218                        numberFixed++;
1219                      }
1220                    }
1221                  }
1222                  printf("%d columns fixed\n",numberFixed);
1223                }
1224              }
1225              // See if we want preprocessing
1226              OsiSolverInterface * saveSolver=NULL;
1227              CglPreProcess process;
1228              delete babModel;
1229              babModel = new CbcModel(model);
1230              OsiSolverInterface * solver3 = clpSolver->clone();
1231              babModel->assignSolver(solver3);
1232              OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
1233              int numberChanged=0;
1234              if (clpSolver2->messageHandler()->logLevel())
1235                clpSolver2->messageHandler()->setLogLevel(1);
1236              int logLevel = parameters[slog].intValue();
1237              if (logLevel)
1238                clpSolver2->messageHandler()->setLogLevel(logLevel);
1239              lpSolver = clpSolver2->getModelPtr();
1240              if (lpSolver->factorizationFrequency()==200) {
1241                // User did not touch preset
1242                int numberRows = lpSolver->numberRows();
1243                const int cutoff1=10000;
1244                const int cutoff2=100000;
1245                const int base=75;
1246                const int freq0 = 50;
1247                const int freq1=200;
1248                const int freq2=400;
1249                const int maximum=1000;
1250                int frequency;
1251                if (numberRows<cutoff1)
1252                  frequency=base+numberRows/freq0;
1253                else if (numberRows<cutoff2)
1254                  frequency=base+cutoff1/freq0 + (numberRows-cutoff1)/freq1;
1255                else
1256                  frequency=base+cutoff1/freq0 + (cutoff2-cutoff1)/freq1 + (numberRows-cutoff2)/freq2;
1257                lpSolver->setFactorizationFrequency(CoinMin(maximum,frequency));
1258              }
1259              time2 = CoinCpuTime();
1260              totalTime += time2-time1;
1261              time1 = time2;
1262              double timeLeft = babModel->getMaximumSeconds();
1263              if (preProcess&&type==BAB) {
1264                saveSolver=babModel->solver()->clone();
1265                /* Do not try and produce equality cliques and
1266                   do up to 10 passes */
1267                OsiSolverInterface * solver2;
1268                {
1269                  // Tell solver we are in Branch and Cut
1270                  saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;
1271                  // Default set of cut generators
1272                  CglProbing generator1;
1273                  generator1.setUsingObjective(true);
1274                  generator1.setMaxPass(3);
1275                  generator1.setMaxProbeRoot(saveSolver->getNumCols());
1276                  generator1.setMaxElements(100);
1277                  generator1.setMaxLookRoot(50);
1278                  generator1.setRowCuts(3);
1279                  // Add in generators
1280                  process.addCutGenerator(&generator1);
1281                  int translate[]={9999,0,0,-1,2};
1282                  solver2 = process.preProcessNonDefault(*saveSolver,translate[preProcess],10);
1283                  // Tell solver we are not in Branch and Cut
1284                  saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
1285                  if (solver2)
1286                    solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
1287                }
1288                if (!solver2) {
1289                  printf("Pre-processing says infeasible\n");
1290                  break;
1291                } else {
1292                  printf("processed model has %d rows, %d columns and %d elements\n",
1293                         solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements());
1294                }
1295                //solver2->resolve();
1296                if (preProcess==2) {
1297                  OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (solver2);
1298                  ClpSimplex * lpSolver = clpSolver2->getModelPtr();
1299                  lpSolver->writeMps("presolved.mps",0,1,lpSolver->optimizationDirection());
1300                  printf("Preprocessed model (minimization) on presolved.mps\n");
1301                }
1302                // we have to keep solver2 so pass clone
1303                solver2 = solver2->clone();
1304                babModel->assignSolver(solver2);
1305                babModel->initialSolve();
1306                babModel->setMaximumSeconds(timeLeft-(CoinCpuTime()-time1));
1307              }
1308              // now tighten bounds
1309              {
1310                OsiClpSolverInterface * si =
1311                  dynamic_cast<OsiClpSolverInterface *>(babModel->solver()) ;
1312                assert (si != NULL);
1313                // get clp itself
1314                ClpSimplex * modelC = si->getModelPtr();
1315                if (modelC->tightenPrimalBounds()!=0) {
1316                  std::cout<<"Problem is infeasible!"<<std::endl;
1317                  break;
1318                }
1319                modelC->dual();
1320              }
1321              if (debugValues) {
1322                // for debug
1323                std::string problemName ;
1324                babModel->solver()->getStrParam(OsiProbName,problemName) ;
1325                //babModel->solver()->activateRowCutDebugger(problemName.c_str()) ;
1326                twomirGen.probname_=strdup(problemName.c_str());
1327                // checking seems odd
1328                //redsplitGen.set_given_optsol(babModel->solver()->getRowCutDebuggerAlways()->optimalSolution(),
1329                //                         babModel->getNumCols());
1330              }
1331              if (useCosts) {
1332                int numberColumns = babModel->getNumCols();
1333                int * sort = new int[numberColumns];
1334                double * dsort = new double[numberColumns];
1335                int * priority = new int [numberColumns];
1336                const double * objective = babModel->getObjCoefficients();
1337                int iColumn;
1338                int n=0;
1339                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1340                  if (babModel->isInteger(iColumn)) {
1341                    sort[n]=n;
1342                    dsort[n++]=-objective[iColumn];
1343                  }
1344                }
1345                CoinSort_2(dsort,dsort+n,sort);
1346                int level=0;
1347                double last = -1.0e100;
1348                for (int i=0;i<n;i++) {
1349                  int iPut=sort[i];
1350                  if (dsort[i]!=last) {
1351                    level++;
1352                    last=dsort[i];
1353                  }
1354                  priority[iPut]=level;
1355                }
1356                babModel->passInPriorities( priority,false);
1357                delete [] priority;
1358                delete [] sort;
1359                delete [] dsort;
1360              }
1361              // FPump done first as it only works if no solution
1362              CbcHeuristicFPump heuristic4(*babModel);
1363              if (useFpump) {
1364                heuristic4.setMaximumPasses(parameters[whichParam(FPUMPITS,numberParameters,parameters)].intValue());
1365                babModel->addHeuristic(&heuristic4);
1366              }
1367              CbcRounding heuristic1(*babModel);
1368              if (useRounding)
1369                babModel->addHeuristic(&heuristic1) ;
1370              CbcHeuristicLocal heuristic2(*babModel);
1371              heuristic2.setSearchType(1);
1372              if (useCombine)
1373                babModel->addHeuristic(&heuristic2);
1374              CbcHeuristicGreedyCover heuristic3(*babModel);
1375              CbcHeuristicGreedyEquality heuristic3a(*babModel);
1376              if (useGreedy) {
1377                babModel->addHeuristic(&heuristic3);
1378                babModel->addHeuristic(&heuristic3a);
1379              }
1380              if (useLocalTree) {
1381                CbcTreeLocal localTree(babModel,NULL,10,0,0,10000,2000);
1382                babModel->passInTreeHandler(localTree);
1383              }
1384              // add cut generators if wanted
1385              int switches[20];
1386              int numberGenerators=0;
1387              if (probingAction==1) {
1388                babModel->addCutGenerator(&probingGen,-1,"Probing");
1389                switches[numberGenerators++]=0;
1390              } else if (probingAction>=2) {
1391                babModel->addCutGenerator(&probingGen,-101+probingAction,"Probing");
1392                switches[numberGenerators++]=0;
1393              }
1394              if (gomoryAction==1) {
1395                babModel->addCutGenerator(&gomoryGen,-1,"Gomory");
1396                switches[numberGenerators++]=1;
1397              } else if (gomoryAction>=2) {
1398                babModel->addCutGenerator(&gomoryGen,-101+gomoryAction,"Gomory");
1399                switches[numberGenerators++]=-1;
1400              }
1401              if (knapsackAction==1) {
1402                babModel->addCutGenerator(&knapsackGen,-1,"Knapsack");
1403                switches[numberGenerators++]=0;
1404              } else if (knapsackAction>=2) {
1405                babModel->addCutGenerator(&knapsackGen,-101+knapsackAction,"Knapsack");
1406                switches[numberGenerators++]=0;
1407              }
1408              if (redsplitAction==1) {
1409                babModel->addCutGenerator(&redsplitGen,-1,"Reduce-and-split");
1410                switches[numberGenerators++]=1;
1411              } else if (redsplitAction>=2) {
1412                babModel->addCutGenerator(&redsplitGen,-101+redsplitAction,"Reduce-and-split");
1413                switches[numberGenerators++]=1;
1414              }
1415              if (cliqueAction==1) {
1416                babModel->addCutGenerator(&cliqueGen,-1,"Clique");
1417                switches[numberGenerators++]=1;
1418              } else if (cliqueAction>=2) {
1419                babModel->addCutGenerator(&cliqueGen,-101+cliqueAction,"Clique");
1420                switches[numberGenerators++]=-1;
1421              }
1422              if (mixedAction==1) {
1423                babModel->addCutGenerator(&mixedGen,-1,"MixedIntegerRounding2");
1424                switches[numberGenerators++]=1;
1425              } else if (mixedAction>=2) {
1426                babModel->addCutGenerator(&mixedGen,-101+mixedAction,"MixedIntegerRounding2");
1427                switches[numberGenerators++]=-1;
1428              }
1429              if (flowAction==1) {
1430                babModel->addCutGenerator(&flowGen,-1,"FlowCover");
1431                switches[numberGenerators++]=1;
1432              } else if (flowAction>=2) {
1433                babModel->addCutGenerator(&flowGen,-101+flowAction,"FlowCover");
1434                switches[numberGenerators++]=1;
1435              }
1436              if (twomirAction==1) {
1437                babModel->addCutGenerator(&twomirGen,-1,"TwoMirCuts");
1438                switches[numberGenerators++]=1;
1439              } else if (twomirAction>=2) {
1440                babModel->addCutGenerator(&twomirGen,-101+twomirAction,"TwoMirCuts");
1441                switches[numberGenerators++]=1;
1442              }
1443              // Say we want timings
1444              numberGenerators = babModel->numberCutGenerators();
1445              int iGenerator;
1446              int cutDepth=
1447                parameters[whichParam(CUTDEPTH,numberParameters,parameters)].intValue();
1448              for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
1449                CbcCutGenerator * generator = babModel->cutGenerator(iGenerator);
1450                int howOften = generator->howOften();
1451                if (howOften==-98||howOften==-99) 
1452                  generator->setSwitchOffIfLessThan(switches[iGenerator]);
1453                generator->setTiming(true);
1454                if (cutDepth>=0)
1455                  generator->setWhatDepth(cutDepth) ;
1456              }
1457              // Could tune more
1458              babModel->setMinimumDrop(min(5.0e-2,
1459                                        fabs(babModel->getMinimizationObjValue())*1.0e-3+1.0e-4));
1460              if (cutPass==-1234567) {
1461                if (babModel->getNumCols()<500)
1462                  babModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible
1463                else if (babModel->getNumCols()<5000)
1464                  babModel->setMaximumCutPassesAtRoot(100); // use minimum drop
1465                else
1466                  babModel->setMaximumCutPassesAtRoot(20);
1467              } else {
1468                babModel->setMaximumCutPassesAtRoot(cutPass);
1469              }
1470              babModel->setMaximumCutPasses(1);
1471             
1472              // Do more strong branching if small
1473              //if (babModel->getNumCols()<5000)
1474              //babModel->setNumberStrong(20);
1475              // Switch off strong branching if wanted
1476              //if (babModel->getNumCols()>10*babModel->getNumRows())
1477              //babModel->setNumberStrong(0);
1478              babModel->messageHandler()->setLogLevel(parameters[log].intValue());
1479              if (babModel->getNumCols()>2000||babModel->getNumRows()>1500||
1480                  babModel->messageHandler()->logLevel()>1)
1481                babModel->setPrintFrequency(100);
1482             
1483              babModel->solver()->setIntParam(OsiMaxNumIterationHotStart,100);
1484              OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
1485              // go faster stripes
1486              if (osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
1487                osiclp->setupForRepeatedUse(2,0);
1488              } else {
1489                osiclp->setupForRepeatedUse(0,0);
1490              }
1491              double increment=babModel->getCutoffIncrement();;
1492              int * changed = analyze( osiclp,numberChanged,increment,false);
1493              if (debugValues) {
1494                if (numberDebugValues==babModel->getNumCols()) {
1495                  // for debug
1496                  babModel->solver()->activateRowCutDebugger(debugValues) ;
1497                } else {
1498                  printf("debug file has incorrect number of columns\n");
1499                }
1500              }
1501              babModel->setCutoffIncrement(CoinMax(babModel->getCutoffIncrement(),increment));
1502              // Turn this off if you get problems
1503              // Used to be automatically set
1504              osiclp->setSpecialOptions(osiclp->specialOptions()|(128+64)|1);
1505              if (gapRatio < 1.0e100) {
1506                double value = babModel->solver()->getObjValue() ;
1507                double value2 = gapRatio*(1.0e-5+fabs(value)) ;
1508                babModel->setAllowableGap(value2) ;
1509                std::cout << "Continuous " << value
1510                          << ", so allowable gap set to "
1511                          << value2 << std::endl ;
1512              }
1513              // probably faster to use a basis to get integer solutions
1514              babModel->setSpecialOptions(2);
1515              currentBranchModel = babModel;
1516              OsiSolverInterface * strengthenedModel=NULL;
1517              if (type==BAB) {
1518                if (preProcess&&process.numberSOS()) {
1519                  int numberSOS = process.numberSOS();
1520                  int numberIntegers = babModel->numberIntegers();
1521                  /* model may not have created objects
1522                     If none then create
1523                  */
1524                  if (!numberIntegers||!babModel->numberObjects()) {
1525                    babModel->findIntegers(true);
1526                    numberIntegers = babModel->numberIntegers();
1527                  }
1528                  CbcObject ** oldObjects = babModel->objects();
1529                  // Do sets and priorities
1530                  CbcObject ** objects = new CbcObject * [numberSOS];
1531                  // set old objects to have low priority
1532                  int numberOldObjects = babModel->numberObjects();
1533                  int numberColumns = babModel->getNumCols();
1534                  for (int iObj = 0;iObj<numberOldObjects;iObj++)
1535                    oldObjects[iObj]->setPriority(numberColumns+1);
1536                  const int * starts = process.startSOS();
1537                  const int * which = process.whichSOS();
1538                  const int * type = process.typeSOS();
1539                  const double * weight = process.weightSOS();
1540                  int iSOS;
1541                  for (iSOS =0;iSOS<numberSOS;iSOS++) {
1542                    int iStart = starts[iSOS];
1543                    int n=starts[iSOS+1]-iStart;
1544                    objects[iSOS] = new CbcSOS(babModel,n,which+iStart,weight+iStart,
1545                                               iSOS,type[iSOS]);
1546                    // branch on long sets first
1547                    objects[iSOS]->setPriority(numberColumns-n);
1548                  }
1549                  babModel->addObjects(numberSOS,objects);
1550                  for (iSOS=0;iSOS<numberSOS;iSOS++)
1551                    delete objects[iSOS];
1552                  delete [] objects;
1553                }
1554                babModel->branchAndBound();
1555              } else {
1556                strengthenedModel = babModel->strengthenedModel();
1557              }
1558              currentBranchModel = NULL;
1559              osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
1560              if (debugFile=="createAfterPre"&&babModel->bestSolution()) {
1561                lpSolver = osiclp->getModelPtr();
1562                //move best solution (should be there -- but ..)
1563                int n = lpSolver->getNumCols();
1564                memcpy(lpSolver->primalColumnSolution(),babModel->bestSolution(),n*sizeof(double));
1565                saveSolution(osiclp->getModelPtr(),"debug.file");
1566              }
1567              // Print more statistics
1568              std::cout<<"Cuts at root node changed objective from "<<babModel->getContinuousObjective()
1569                       <<" to "<<babModel->rootObjectiveAfterCuts()<<std::endl;
1570             
1571              for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
1572                CbcCutGenerator * generator = babModel->cutGenerator(iGenerator);
1573                std::cout<<generator->cutGeneratorName()<<" was tried "
1574                         <<generator->numberTimesEntered()<<" times and created "
1575                         <<generator->numberCutsInTotal()<<" cuts of which "
1576                         <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
1577                if (generator->timing())
1578                  std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
1579                else
1580                  std::cout<<std::endl;
1581              }
1582              time2 = CoinCpuTime();
1583              totalTime += time2-time1;
1584              // For best solution
1585              double * bestSolution = NULL;
1586              if (babModel->getMinimizationObjValue()<1.0e50&&type==BAB) {
1587                // post process
1588                if (preProcess) {
1589                  int n = saveSolver->getNumCols();
1590                  bestSolution = new double [n];
1591                  process.postProcess(*babModel->solver());
1592                  // Solution now back in saveSolver
1593                  babModel->assignSolver(saveSolver);
1594                  memcpy(bestSolution,babModel->solver()->getColSolution(),n*sizeof(double));
1595                } else {
1596                  int n = babModel->solver()->getNumCols();
1597                  bestSolution = new double [n];
1598                  memcpy(bestSolution,babModel->solver()->getColSolution(),n*sizeof(double));
1599                }
1600              }
1601              if (type==STRENGTHEN&&strengthenedModel)
1602                clpSolver = dynamic_cast< OsiClpSolverInterface*> (strengthenedModel);
1603              lpSolver = clpSolver->getModelPtr();
1604              if (debugFile=="create"&&bestSolution) {
1605                saveSolution(lpSolver,"debug.file");
1606              }
1607              if (numberChanged) {
1608                for (int i=0;i<numberChanged;i++) {
1609                  int iColumn=changed[i];
1610                  clpSolver->setContinuous(iColumn);
1611                }
1612                delete [] changed;
1613              }
1614              if (type==BAB) {
1615                //move best solution (should be there -- but ..)
1616                int n = lpSolver->getNumCols();
1617                if (bestSolution)
1618                  memcpy(lpSolver->primalColumnSolution(),bestSolution,n*sizeof(double));
1619                delete [] bestSolution;
1620                std::string statusName[]={"Finished","Stopped on ","Difficulties",
1621                                          "","","User ctrl-c"};
1622                std::string minor[]={"","","gap","nodes","time","","solutions"};
1623                int iStat = babModel->status();
1624                int iStat2 = babModel->secondaryStatus();
1625                std::cout<<"Result - "<<statusName[iStat]<<minor[iStat2]
1626                         <<" objective "<<babModel->getObjValue()<<
1627                  " after "<<babModel->getNodeCount()<<" nodes and "
1628                         <<babModel->getIterationCount()<<
1629                  " iterations - took "<<time2-time1<<" seconds"<<std::endl;
1630              } else {
1631                std::cout<<"Model strengthend - now has "<<clpSolver->getNumRows()
1632                         <<" rows"<<std::endl;
1633              }
1634              time1 = time2;
1635              delete babModel;
1636              babModel=NULL;
1637            } else {
1638              std::cout << "** Current model not valid" << std::endl ; 
1639            }
1640            break ;
1641          case IMPORT:
1642            {
1643              delete babModel;
1644              babModel=NULL;
1645              // get next field
1646              field = CoinReadGetString(argc,argv);
1647              if (field=="$") {
1648                field = parameters[iParam].stringValue();
1649              } else if (field=="EOL") {
1650                parameters[iParam].printString();
1651                break;
1652              } else {
1653                parameters[iParam].setStringValue(field);
1654              }
1655              std::string fileName;
1656              bool canOpen=false;
1657              if (field=="-") {
1658                // stdin
1659                canOpen=true;
1660                fileName = "-";
1661              } else {
1662                bool absolutePath;
1663                if (dirsep=='/') {
1664                  // non Windows (or cygwin)
1665                  absolutePath=(field[0]=='/');
1666                } else {
1667                  //Windows (non cycgwin)
1668                  absolutePath=(field[0]=='\\');
1669                  // but allow for :
1670                  if (strchr(field.c_str(),':'))
1671                    absolutePath=true;
1672                }
1673                if (absolutePath) {
1674                  fileName = field;
1675                } else if (field[0]=='~') {
1676                  char * environ = getenv("HOME");
1677                  if (environ) {
1678                    std::string home(environ);
1679                    field=field.erase(0,1);
1680                    fileName = home+field;
1681                  } else {
1682                    fileName=field;
1683                  }
1684                } else {
1685                  fileName = directory+field;
1686                }
1687                FILE *fp=fopen(fileName.c_str(),"r");
1688                if (fp) {
1689                  // can open - lets go for it
1690                  fclose(fp);
1691                  canOpen=true;
1692                } else {
1693                  std::cout<<"Unable to open file "<<fileName<<std::endl;
1694                }
1695              }
1696              if (canOpen) {
1697                int status =lpSolver->readMps(fileName.c_str(),
1698                                                   keepImportNames!=0,
1699                                                   allowImportErrors!=0);
1700                if (!status||(status>0&&allowImportErrors)) {
1701                  if (keepImportNames) {
1702                    lengthName = lpSolver->lengthNames();
1703                    rowNames = *(lpSolver->rowNames());
1704                    columnNames = *(lpSolver->columnNames());
1705                  } else {
1706                    lengthName=0;
1707                  }
1708                  goodModel=true;
1709                  //Set integers in clpsolver
1710                  const char * info = lpSolver->integerInformation();
1711                  if (info) {
1712                    int numberColumns = lpSolver->numberColumns();
1713                    int i;
1714                    for (i=0;i<numberColumns;i++) {
1715                      if (info[i]) 
1716                        clpSolver->setInteger(i);
1717                    }
1718                  }
1719                  // sets to all slack (not necessary?)
1720                  lpSolver->createStatus();
1721                  time2 = CoinCpuTime();
1722                  totalTime += time2-time1;
1723                  time1=time2;
1724                  // Go to canned file if just input file
1725                  if (CbcOrClpRead_mode==2&&argc==2) {
1726                    // only if ends .mps
1727                    char * find = strstr(fileName.c_str(),".mps");
1728                    if (find&&find[4]=='\0') {
1729                      find[1]='p'; find[2]='a';find[3]='r';
1730                      FILE *fp=fopen(fileName.c_str(),"r");
1731                      if (fp) {
1732                        CbcOrClpReadCommand=fp; // Read from that file
1733                        CbcOrClpRead_mode=-1;
1734                      }
1735                    }
1736                  }
1737                } else {
1738                  // errors
1739                  std::cout<<"There were "<<status<<
1740                    " errors on input"<<std::endl;
1741                }
1742              }
1743            }
1744            break;
1745          case EXPORT:
1746            if (goodModel) {
1747              // get next field
1748              field = CoinReadGetString(argc,argv);
1749              if (field=="$") {
1750                field = parameters[iParam].stringValue();
1751              } else if (field=="EOL") {
1752                parameters[iParam].printString();
1753                break;
1754              } else {
1755                parameters[iParam].setStringValue(field);
1756              }
1757              std::string fileName;
1758              bool canOpen=false;
1759              if (field[0]=='/'||field[0]=='\\') {
1760                fileName = field;
1761              } else if (field[0]=='~') {
1762                char * environ = getenv("HOME");
1763                if (environ) {
1764                  std::string home(environ);
1765                  field=field.erase(0,1);
1766                  fileName = home+field;
1767                } else {
1768                  fileName=field;
1769                }
1770              } else {
1771                fileName = directory+field;
1772              }
1773              FILE *fp=fopen(fileName.c_str(),"w");
1774              if (fp) {
1775                // can open - lets go for it
1776                fclose(fp);
1777                canOpen=true;
1778              } else {
1779                std::cout<<"Unable to open file "<<fileName<<std::endl;
1780              }
1781              if (canOpen) {
1782                // If presolve on then save presolved
1783                bool deleteModel2=false;
1784                ClpSimplex * model2 = lpSolver;
1785                if (preSolve) {
1786                  ClpPresolve pinfo;
1787                  int presolveOptions2 = presolveOptions&~0x40000000;
1788                  if ((presolveOptions2&0xffff)!=0)
1789                    pinfo.setPresolveActions(presolveOptions2);
1790                  if ((printOptions&1)!=0)
1791                    pinfo.statistics();
1792                  model2 = 
1793                    pinfo.presolvedModel(*lpSolver,1.0e-8,
1794                                         true,preSolve);
1795                  if (model2) {
1796                    printf("Saving presolved model on %s\n",
1797                           fileName.c_str());
1798                    deleteModel2=true;
1799                  } else {
1800                    printf("Presolved model looks infeasible - saving original on %s\n",
1801                           fileName.c_str());
1802                    deleteModel2=false;
1803                    model2 = lpSolver;
1804
1805                  }
1806                } else {
1807                  printf("Saving model on %s\n",
1808                           fileName.c_str());
1809                }
1810#if 0
1811                // Convert names
1812                int iRow;
1813                int numberRows=model2->numberRows();
1814                int iColumn;
1815                int numberColumns=model2->numberColumns();
1816
1817                char ** rowNames = NULL;
1818                char ** columnNames = NULL;
1819                if (model2->lengthNames()) {
1820                  rowNames = new char * [numberRows];
1821                  for (iRow=0;iRow<numberRows;iRow++) {
1822                    rowNames[iRow] =
1823                      strdup(model2->rowName(iRow).c_str());
1824#ifdef STRIPBLANKS
1825                    char * xx = rowNames[iRow];
1826                    int i;
1827                    int length = strlen(xx);
1828                    int n=0;
1829                    for (i=0;i<length;i++) {
1830                      if (xx[i]!=' ')
1831                        xx[n++]=xx[i];
1832                    }
1833                    xx[n]='\0';
1834#endif
1835                  }
1836                 
1837                  columnNames = new char * [numberColumns];
1838                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1839                    columnNames[iColumn] =
1840                      strdup(model2->columnName(iColumn).c_str());
1841#ifdef STRIPBLANKS
1842                    char * xx = columnNames[iColumn];
1843                    int i;
1844                    int length = strlen(xx);
1845                    int n=0;
1846                    for (i=0;i<length;i++) {
1847                      if (xx[i]!=' ')
1848                        xx[n++]=xx[i];
1849                    }
1850                    xx[n]='\0';
1851#endif
1852                  }
1853                }
1854                CoinMpsIO writer;
1855                writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
1856                                  model2->getColLower(), model2->getColUpper(),
1857                                  model2->getObjCoefficients(),
1858                                  (const char*) 0 /*integrality*/,
1859                                  model2->getRowLower(), model2->getRowUpper(),
1860                                  columnNames, rowNames);
1861                // Pass in array saying if each variable integer
1862                writer.copyInIntegerInformation(model2->integerInformation());
1863                writer.setObjectiveOffset(model2->objectiveOffset());
1864                writer.writeMps(fileName.c_str(),0,1,1);
1865                if (rowNames) {
1866                  for (iRow=0;iRow<numberRows;iRow++) {
1867                    free(rowNames[iRow]);
1868                  }
1869                  delete [] rowNames;
1870                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1871                    free(columnNames[iColumn]);
1872                  }
1873                  delete [] columnNames;
1874                }
1875#else
1876                model2->writeMps(fileName.c_str(),(outputFormat-1)/2,1+((outputFormat-1)&1));
1877#endif
1878                if (deleteModel2)
1879                  delete model2;
1880                time2 = CoinCpuTime();
1881                totalTime += time2-time1;
1882                time1=time2;
1883              }
1884            } else {
1885              std::cout<<"** Current model not valid"<<std::endl;
1886            }
1887            break;
1888          case BASISIN:
1889            if (goodModel) {
1890              // get next field
1891              field = CoinReadGetString(argc,argv);
1892              if (field=="$") {
1893                field = parameters[iParam].stringValue();
1894              } else if (field=="EOL") {
1895                parameters[iParam].printString();
1896                break;
1897              } else {
1898                parameters[iParam].setStringValue(field);
1899              }
1900              std::string fileName;
1901              bool canOpen=false;
1902              if (field=="-") {
1903                // stdin
1904                canOpen=true;
1905                fileName = "-";
1906              } else {
1907                if (field[0]=='/'||field[0]=='\\') {
1908                  fileName = field;
1909                } else if (field[0]=='~') {
1910                  char * environ = getenv("HOME");
1911                  if (environ) {
1912                    std::string home(environ);
1913                    field=field.erase(0,1);
1914                    fileName = home+field;
1915                  } else {
1916                    fileName=field;
1917                  }
1918                } else {
1919                  fileName = directory+field;
1920                }
1921                FILE *fp=fopen(fileName.c_str(),"r");
1922                if (fp) {
1923                  // can open - lets go for it
1924                  fclose(fp);
1925                  canOpen=true;
1926                } else {
1927                  std::cout<<"Unable to open file "<<fileName<<std::endl;
1928                }
1929              }
1930              if (canOpen) {
1931                int values = lpSolver->readBasis(fileName.c_str());
1932                if (values==0)
1933                  basisHasValues=-1;
1934                else
1935                  basisHasValues=1;
1936              }
1937            } else {
1938              std::cout<<"** Current model not valid"<<std::endl;
1939            }
1940            break;
1941          case DEBUG:
1942            if (goodModel) {
1943              delete [] debugValues;
1944              debugValues=NULL;
1945              // get next field
1946              field = CoinReadGetString(argc,argv);
1947              if (field=="$") {
1948                field = parameters[iParam].stringValue();
1949              } else if (field=="EOL") {
1950                parameters[iParam].printString();
1951                break;
1952              } else {
1953                parameters[iParam].setStringValue(field);
1954                debugFile=field;
1955                if (debugFile=="create"||
1956                    debugFile=="createAfterPre") {
1957                  printf("Will create a debug file so this run should be a good one\n");
1958                  break;
1959                }
1960              }
1961              std::string fileName;
1962              if (field[0]=='/'||field[0]=='\\') {
1963                fileName = field;
1964              } else if (field[0]=='~') {
1965                char * environ = getenv("HOME");
1966                if (environ) {
1967                  std::string home(environ);
1968                  field=field.erase(0,1);
1969                  fileName = home+field;
1970                } else {
1971                  fileName=field;
1972                }
1973              } else {
1974                fileName = directory+field;
1975              }
1976              FILE *fp=fopen(fileName.c_str(),"rb");
1977              if (fp) {
1978                // can open - lets go for it
1979                int numRows;
1980                double obj;
1981                fread(&numRows,sizeof(int),1,fp);
1982                fread(&numberDebugValues,sizeof(int),1,fp);
1983                fread(&obj,sizeof(double),1,fp);
1984                debugValues = new double[numberDebugValues+numRows];
1985                fread(debugValues,sizeof(double),numRows,fp);
1986                fread(debugValues,sizeof(double),numRows,fp);
1987                fread(debugValues,sizeof(double),numberDebugValues,fp);
1988                printf("%d doubles read into debugValues\n",numberDebugValues);
1989                fclose(fp);
1990              } else {
1991                std::cout<<"Unable to open file "<<fileName<<std::endl;
1992              }
1993            } else {
1994              std::cout<<"** Current model not valid"<<std::endl;
1995            }
1996            break;
1997          case BASISOUT:
1998            if (goodModel) {
1999              // get next field
2000              field = CoinReadGetString(argc,argv);
2001              if (field=="$") {
2002                field = parameters[iParam].stringValue();
2003              } else if (field=="EOL") {
2004                parameters[iParam].printString();
2005                break;
2006              } else {
2007                parameters[iParam].setStringValue(field);
2008              }
2009              std::string fileName;
2010              bool canOpen=false;
2011              if (field[0]=='/'||field[0]=='\\') {
2012                fileName = field;
2013              } else if (field[0]=='~') {
2014                char * environ = getenv("HOME");
2015                if (environ) {
2016                  std::string home(environ);
2017                  field=field.erase(0,1);
2018                  fileName = home+field;
2019                } else {
2020                  fileName=field;
2021                }
2022              } else {
2023                fileName = directory+field;
2024              }
2025              FILE *fp=fopen(fileName.c_str(),"w");
2026              if (fp) {
2027                // can open - lets go for it
2028                fclose(fp);
2029                canOpen=true;
2030              } else {
2031                std::cout<<"Unable to open file "<<fileName<<std::endl;
2032              }
2033              if (canOpen) {
2034                ClpSimplex * model2 = lpSolver;
2035                model2->writeBasis(fileName.c_str(),outputFormat>1,outputFormat-2);
2036                time2 = CoinCpuTime();
2037                totalTime += time2-time1;
2038                time1=time2;
2039              }
2040            } else {
2041              std::cout<<"** Current model not valid"<<std::endl;
2042            }
2043            break;
2044          case SAVE:
2045            {
2046              // get next field
2047              field = CoinReadGetString(argc,argv);
2048              if (field=="$") {
2049                field = parameters[iParam].stringValue();
2050              } else if (field=="EOL") {
2051                parameters[iParam].printString();
2052                break;
2053              } else {
2054                parameters[iParam].setStringValue(field);
2055              }
2056              std::string fileName;
2057              bool canOpen=false;
2058              if (field[0]=='/'||field[0]=='\\') {
2059                fileName = field;
2060              } else if (field[0]=='~') {
2061                char * environ = getenv("HOME");
2062                if (environ) {
2063                  std::string home(environ);
2064                  field=field.erase(0,1);
2065                  fileName = home+field;
2066                } else {
2067                  fileName=field;
2068                }
2069              } else {
2070                fileName = directory+field;
2071              }
2072              FILE *fp=fopen(fileName.c_str(),"wb");
2073              if (fp) {
2074                // can open - lets go for it
2075                fclose(fp);
2076                canOpen=true;
2077              } else {
2078                std::cout<<"Unable to open file "<<fileName<<std::endl;
2079              }
2080              if (canOpen) {
2081                int status;
2082                // If presolve on then save presolved
2083                bool deleteModel2=false;
2084                ClpSimplex * model2 = lpSolver;
2085                if (preSolve) {
2086                  ClpPresolve pinfo;
2087                  model2 = 
2088                    pinfo.presolvedModel(*lpSolver,1.0e-8,
2089                                         false,preSolve);
2090                  if (model2) {
2091                    printf("Saving presolved model on %s\n",
2092                           fileName.c_str());
2093                    deleteModel2=true;
2094                  } else {
2095                    printf("Presolved model looks infeasible - saving original on %s\n",
2096                           fileName.c_str());
2097                    deleteModel2=false;
2098                    model2 = lpSolver;
2099
2100                  }
2101                } else {
2102                  printf("Saving model on %s\n",
2103                           fileName.c_str());
2104                }
2105                status =model2->saveModel(fileName.c_str());
2106                if (deleteModel2)
2107                  delete model2;
2108                if (!status) {
2109                  goodModel=true;
2110                  time2 = CoinCpuTime();
2111                  totalTime += time2-time1;
2112                  time1=time2;
2113                } else {
2114                  // errors
2115                  std::cout<<"There were errors on output"<<std::endl;
2116                }
2117              }
2118            }
2119            break;
2120          case RESTORE:
2121            {
2122              // get next field
2123              field = CoinReadGetString(argc,argv);
2124              if (field=="$") {
2125                field = parameters[iParam].stringValue();
2126              } else if (field=="EOL") {
2127                parameters[iParam].printString();
2128                break;
2129              } else {
2130                parameters[iParam].setStringValue(field);
2131              }
2132              std::string fileName;
2133              bool canOpen=false;
2134              if (field[0]=='/'||field[0]=='\\') {
2135                fileName = field;
2136              } else if (field[0]=='~') {
2137                char * environ = getenv("HOME");
2138                if (environ) {
2139                  std::string home(environ);
2140                  field=field.erase(0,1);
2141                  fileName = home+field;
2142                } else {
2143                  fileName=field;
2144                }
2145              } else {
2146                fileName = directory+field;
2147              }
2148              FILE *fp=fopen(fileName.c_str(),"rb");
2149              if (fp) {
2150                // can open - lets go for it
2151                fclose(fp);
2152                canOpen=true;
2153              } else {
2154                std::cout<<"Unable to open file "<<fileName<<std::endl;
2155              }
2156              if (canOpen) {
2157                int status =lpSolver->restoreModel(fileName.c_str());
2158                if (!status) {
2159                  goodModel=true;
2160                  time2 = CoinCpuTime();
2161                  totalTime += time2-time1;
2162                  time1=time2;
2163                } else {
2164                  // errors
2165                  std::cout<<"There were errors on input"<<std::endl;
2166                }
2167              }
2168            }
2169            break;
2170          case MAXIMIZE:
2171            lpSolver->setOptimizationDirection(-1);
2172            break;
2173          case MINIMIZE:
2174            lpSolver->setOptimizationDirection(1);
2175            break;
2176          case ALLSLACK:
2177            lpSolver->allSlackBasis(true);
2178            break;
2179          case REVERSE:
2180            if (goodModel) {
2181              int iColumn;
2182              int numberColumns=lpSolver->numberColumns();
2183              double * dualColumnSolution = 
2184                lpSolver->dualColumnSolution();
2185              ClpObjective * obj = lpSolver->objectiveAsObject();
2186              assert(dynamic_cast<ClpLinearObjective *> (obj));
2187              double offset;
2188              double * objective = obj->gradient(NULL,NULL,offset,true);
2189              for (iColumn=0;iColumn<numberColumns;iColumn++) {
2190                dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
2191                objective[iColumn] = -objective[iColumn];
2192              }
2193              int iRow;
2194              int numberRows=lpSolver->numberRows();
2195              double * dualRowSolution = 
2196                lpSolver->dualRowSolution();
2197              for (iRow=0;iRow<numberRows;iRow++) 
2198                dualRowSolution[iRow] = dualRowSolution[iRow];
2199            }
2200            break;
2201          case DIRECTORY:
2202            {
2203              std::string name = CoinReadGetString(argc,argv);
2204              if (name!="EOL") {
2205                int length=name.length();
2206                if (name[length-1]=='/'||name[length-1]=='\\')
2207                  directory=name;
2208                else
2209                  directory = name+"/";
2210                parameters[iParam].setStringValue(directory);
2211              } else {
2212                parameters[iParam].printString();
2213              }
2214            }
2215            break;
2216          case STDIN:
2217            CbcOrClpRead_mode=-1;
2218            break;
2219          case NETLIB_DUAL:
2220          case NETLIB_EITHER:
2221          case NETLIB_BARRIER:
2222          case NETLIB_PRIMAL:
2223          case NETLIB_TUNE:
2224            {
2225              // create fields for unitTest
2226              const char * fields[4];
2227              int nFields=2;
2228              fields[0]="fake main from unitTest";
2229              fields[1]="-netlib";
2230              if (directory!=defaultDirectory) {
2231                fields[2]="-netlibDir";
2232                fields[3]=directory.c_str();
2233                nFields=4;
2234              }
2235              int algorithm;
2236              if (type==NETLIB_DUAL) {
2237                std::cerr<<"Doing netlib with dual algorithm"<<std::endl;
2238                algorithm =0;
2239              } else if (type==NETLIB_BARRIER) {
2240                std::cerr<<"Doing netlib with barrier algorithm"<<std::endl;
2241                algorithm =2;
2242              } else if (type==NETLIB_EITHER) {
2243                std::cerr<<"Doing netlib with dual or primal algorithm"<<std::endl;
2244                algorithm =3;
2245              } else if (type==NETLIB_TUNE) {
2246                std::cerr<<"Doing netlib with best algorithm!"<<std::endl;
2247                algorithm =5;
2248                // uncomment next to get active tuning
2249                // algorithm=6;
2250              } else {
2251                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
2252                algorithm=1;
2253              }
2254              int specialOptions = lpSolver->specialOptions();
2255              lpSolver->setSpecialOptions(0);
2256              mainTest(nFields,fields,algorithm,*lpSolver,
2257                       (preSolve!=0),specialOptions);
2258            }
2259            break;
2260          case UNITTEST:
2261            {
2262              // create fields for unitTest
2263              const char * fields[3];
2264              int nFields=1;
2265              fields[0]="fake main from unitTest";
2266              if (directory!=defaultDirectory) {
2267                fields[1]="-mpsDir";
2268                fields[2]=directory.c_str();
2269                nFields=3;
2270              }
2271              mainTest(nFields,fields,false,*lpSolver,(preSolve!=0),
2272                       false);
2273            }
2274            break;
2275          case FAKEBOUND:
2276            if (goodModel) {
2277              // get bound
2278              double value = CoinReadGetDoubleField(argc,argv,&valid);
2279              if (!valid) {
2280                std::cout<<"Setting "<<parameters[iParam].name()<<
2281                  " to DEBUG "<<value<<std::endl;
2282                int iRow;
2283                int numberRows=lpSolver->numberRows();
2284                double * rowLower = lpSolver->rowLower();
2285                double * rowUpper = lpSolver->rowUpper();
2286                for (iRow=0;iRow<numberRows;iRow++) {
2287                  // leave free ones for now
2288                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
2289                    rowLower[iRow]=CoinMax(rowLower[iRow],-value);
2290                    rowUpper[iRow]=CoinMin(rowUpper[iRow],value);
2291                  }
2292                }
2293                int iColumn;
2294                int numberColumns=lpSolver->numberColumns();
2295                double * columnLower = lpSolver->columnLower();
2296                double * columnUpper = lpSolver->columnUpper();
2297                for (iColumn=0;iColumn<numberColumns;iColumn++) {
2298                  // leave free ones for now
2299                  if (columnLower[iColumn]>-1.0e20||
2300                      columnUpper[iColumn]<1.0e20) {
2301                    columnLower[iColumn]=CoinMax(columnLower[iColumn],-value);
2302                    columnUpper[iColumn]=CoinMin(columnUpper[iColumn],value);
2303                  }
2304                }
2305              } else if (valid==1) {
2306                abort();
2307              } else {
2308                std::cout<<"enter value for "<<parameters[iParam].name()<<
2309                  std::endl;
2310              }
2311            }
2312            break;
2313          case REALLY_SCALE:
2314            if (goodModel) {
2315              ClpSimplex newModel(*lpSolver,
2316                                  lpSolver->scalingFlag());
2317              printf("model really really scaled\n");
2318              *lpSolver=newModel;
2319            }
2320            break;
2321          case HELP:
2322            std::cout<<"Coin Solver version "<<CBCVERSION
2323                     <<", build "<<__DATE__<<std::endl;
2324            std::cout<<"Non default values:-"<<std::endl;
2325            std::cout<<"Perturbation "<<lpSolver->perturbation()<<" (default 100)"
2326                     <<std::endl;
2327            CoinReadPrintit(
2328                    "Presolve being done with 5 passes\n\
2329Dual steepest edge steep/partial on matrix shape and factorization density\n\
2330Clpnnnn taken out of messages\n\
2331If Factorization frequency default then done on size of matrix\n\n\
2332(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
2333You can switch to interactive mode at any time so\n\
2334clp watson.mps -scaling off -primalsimplex\nis the same as\n\
2335clp watson.mps -\nscaling off\nprimalsimplex"
2336                    );
2337            break;
2338          case SOLUTION:
2339            if (goodModel) {
2340              // get next field
2341              field = CoinReadGetString(argc,argv);
2342              if (field=="$") {
2343                field = parameters[iParam].stringValue();
2344              } else if (field=="EOL") {
2345                parameters[iParam].printString();
2346                break;
2347              } else {
2348                parameters[iParam].setStringValue(field);
2349              }
2350              std::string fileName;
2351              FILE *fp=NULL;
2352              if (field=="-"||field=="EOL"||field=="stdout") {
2353                // stdout
2354                fp=stdout;
2355              } else if (field=="stderr") {
2356                // stderr
2357                fp=stderr;
2358              } else {
2359                if (field[0]=='/'||field[0]=='\\') {
2360                  fileName = field;
2361                } else if (field[0]=='~') {
2362                  char * environ = getenv("HOME");
2363                  if (environ) {
2364                    std::string home(environ);
2365                    field=field.erase(0,1);
2366                    fileName = home+field;
2367                  } else {
2368                    fileName=field;
2369                  }
2370                } else {
2371                  fileName = directory+field;
2372                }
2373                fp=fopen(fileName.c_str(),"w");
2374              }
2375              if (fp) {
2376                // make fancy later on
2377                int iRow;
2378                int numberRows=lpSolver->numberRows();
2379                double * dualRowSolution = lpSolver->dualRowSolution();
2380                double * primalRowSolution = 
2381                  lpSolver->primalRowSolution();
2382                double * rowLower = lpSolver->rowLower();
2383                double * rowUpper = lpSolver->rowUpper();
2384                double primalTolerance = lpSolver->primalTolerance();
2385                char format[6];
2386                sprintf(format,"%%-%ds",CoinMax(lengthName,8));
2387                if (printMode>2) {
2388                  for (iRow=0;iRow<numberRows;iRow++) {
2389                    int type=printMode-3;
2390                    if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
2391                        primalRowSolution[iRow]<rowLower[iRow]-primalTolerance) {
2392                      fprintf(fp,"** ");
2393                      type=2;
2394                    } else if (fabs(primalRowSolution[iRow])>1.0e-8) {
2395                      type=1;
2396                    } else if (numberRows<50) {
2397                      type=3;
2398                    }
2399                    if (type) {
2400                      fprintf(fp,"%7d ",iRow);
2401                      if (lengthName)
2402                        fprintf(fp,format,rowNames[iRow].c_str());
2403                      fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
2404                              dualRowSolution[iRow]);
2405                    }
2406                  }
2407                }
2408                int iColumn;
2409                int numberColumns=lpSolver->numberColumns();
2410                double * dualColumnSolution = 
2411                  lpSolver->dualColumnSolution();
2412                double * primalColumnSolution = 
2413                  lpSolver->primalColumnSolution();
2414                double * columnLower = lpSolver->columnLower();
2415                double * columnUpper = lpSolver->columnUpper();
2416                if (printMode!=2) {
2417                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
2418                    int type=0;
2419                    if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
2420                        primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance) {
2421                      fprintf(fp,"** ");
2422                      type=2;
2423                    } else if (fabs(primalColumnSolution[iColumn])>1.0e-8) {
2424                      type=1;
2425                    } else if (numberColumns<50) {
2426                      type=3;
2427                    }
2428                    // see if integer
2429                    if ((!lpSolver->isInteger(iColumn)||fabs(primalColumnSolution[iColumn])<1.0e-8)
2430                         &&printMode==1)
2431                      type=0;
2432                    if (type) {
2433                      fprintf(fp,"%7d ",iColumn);
2434                      if (lengthName)
2435                        fprintf(fp,format,columnNames[iColumn].c_str());
2436                      fprintf(fp,"%15.8g        %15.8g\n",
2437                              primalColumnSolution[iColumn],
2438                              dualColumnSolution[iColumn]);
2439                    }
2440                  }
2441                } else {
2442                  // special format suitable for OsiRowCutDebugger
2443                  int n=0;
2444                  bool comma=false;
2445                  bool newLine=false;
2446                  fprintf(fp,"\tint intIndicesV[]={\n");
2447                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
2448                    if(primalColumnSolution[iColumn]>0.5&&model.solver()->isInteger(iColumn)) {
2449                      if (comma)
2450                        fprintf(fp,",");
2451                      if (newLine)
2452                        fprintf(fp,"\n");
2453                      fprintf(fp,"%d ",iColumn);
2454                      comma=true;
2455                      newLine=false;
2456                      n++;
2457                      if (n==10) {
2458                        n=0;
2459                        newLine=true;
2460                      }
2461                    }
2462                  }
2463                  fprintf(fp,"};\n");
2464                  n=0;
2465                  comma=false;
2466                  newLine=false;
2467                  fprintf(fp,"\tdouble intSolnV[]={\n");
2468                  for ( iColumn=0;iColumn<numberColumns;iColumn++) {
2469                    if(primalColumnSolution[iColumn]>0.5&&model.solver()->isInteger(iColumn)) {
2470                      if (comma)
2471                        fprintf(fp,",");
2472                      if (newLine)
2473                        fprintf(fp,"\n");
2474                      int value = (int) (primalColumnSolution[iColumn]+0.5);
2475                      fprintf(fp,"%d. ",value);
2476                      comma=true;
2477                      newLine=false;
2478                      n++;
2479                      if (n==10) {
2480                        n=0;
2481                        newLine=true;
2482                      }
2483                    }
2484                  }
2485                  fprintf(fp,"};\n");
2486                }
2487                if (fp!=stdout)
2488                  fclose(fp);
2489              } else {
2490                std::cout<<"Unable to open file "<<fileName<<std::endl;
2491              }
2492            } else {
2493              std::cout<<"** Current model not valid"<<std::endl;
2494             
2495            }
2496            break;
2497          case SAVESOL:
2498            if (goodModel) {
2499              // get next field
2500              field = CoinReadGetString(argc,argv);
2501              if (field=="$") {
2502                field = parameters[iParam].stringValue();
2503              } else if (field=="EOL") {
2504                parameters[iParam].printString();
2505                break;
2506              } else {
2507                parameters[iParam].setStringValue(field);
2508              }
2509              std::string fileName;
2510              if (field[0]=='/'||field[0]=='\\') {
2511                fileName = field;
2512              } else if (field[0]=='~') {
2513                char * environ = getenv("HOME");
2514                if (environ) {
2515                  std::string home(environ);
2516                  field=field.erase(0,1);
2517                  fileName = home+field;
2518                } else {
2519                  fileName=field;
2520                }
2521              } else {
2522                fileName = directory+field;
2523              }
2524              saveSolution(lpSolver,fileName);
2525            } else {
2526              std::cout<<"** Current model not valid"<<std::endl;
2527             
2528            }
2529            break;
2530          default:
2531            abort();
2532          }
2533        } 
2534      } else if (!numberMatches) {
2535        std::cout<<"No match for "<<field<<" - ? for list of commands"
2536                 <<std::endl;
2537      } else if (numberMatches==1) {
2538        if (!numberQuery) {
2539          std::cout<<"Short match for "<<field<<" - completion: ";
2540          std::cout<<parameters[firstMatch].matchName()<<std::endl;
2541        } else if (numberQuery) {
2542          std::cout<<parameters[firstMatch].matchName()<<" : ";
2543          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
2544          if (numberQuery>=2) 
2545            parameters[firstMatch].printLongHelp();
2546        }
2547      } else {
2548        if (!numberQuery) 
2549          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
2550                   <<std::endl;
2551        else
2552          std::cout<<"Completions of "<<field<<":"<<std::endl;
2553        for ( iParam=0; iParam<numberParameters; iParam++ ) {
2554          int match = parameters[iParam].matches(field);
2555          if (match&&parameters[iParam].displayThis()) {
2556            std::cout<<parameters[iParam].matchName();
2557            if (numberQuery>=2) 
2558              std::cout<<" : "<<parameters[iParam].shortHelp();
2559            std::cout<<std::endl;
2560          }
2561        }
2562      }
2563    }
2564  }
2565  // By now all memory should be freed
2566#ifdef DMALLOC
2567  dmalloc_log_unfreed();
2568  dmalloc_shutdown();
2569#endif
2570  return 0;
2571}   
2572/*
2573  Version 1.00.00 November 16 2005.
2574  This is to stop me (JJF) messing about too much.
2575  Tuning changes should be noted here.
2576  The testing next version may be activated by CBC_NEXT_VERSION
2577  This applies to OsiClp, Clp etc
2578  Version 1.00.01 November 24 2005
2579  Added several classes for advanced users.  This can't affect code (if you don't use it)
2580  Made some tiny changes (for N way branching) which should not change anything.
2581  CbcNWay object class - for N way branching this also allows use of CbcConsequence class.
2582  CbcBranchAllDifferent object class - for branching on general integer variables
2583  to stop them having same value so branches are x >= y+1 and x <= y-1.
2584  Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly)
2585  and CglStored which just has a list of cuts which can be activated.
2586  Modified preprocess option to SOS
2587*/
Note: See TracBrowser for help on using the repository browser.