source: stable/1.2/Cbc/src/CoinSolve.cpp @ 773

Last change on this file since 773 was 773, checked in by forrest, 13 years ago

version 1.2 in file

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 160.4 KB
Line 
1// Copyright (C) 2004, International Business Machines
2// Corporation and others.  All Rights Reserved.
3   
4#include "CbcConfig.h"
5#include "CoinPragma.hpp"
6
7#include <cassert>
8#include <cstdio>
9#include <cmath>
10#include <cfloat>
11#include <cstring>
12#include <iostream>
13
14
15#include "CoinPragma.hpp"
16#include "CoinHelperFunctions.hpp"
17// Same version as CBC
18#define CBCVERSION "1.02.00"
19
20#include "CoinMpsIO.hpp"
21
22#include "ClpFactorization.hpp"
23#include "CoinTime.hpp"
24#include "ClpSimplex.hpp"
25#include "ClpSimplexOther.hpp"
26#include "ClpSolve.hpp"
27#include "ClpPackedMatrix.hpp"
28#include "ClpPlusMinusOneMatrix.hpp"
29#include "ClpNetworkMatrix.hpp"
30#include "ClpDualRowSteepest.hpp"
31#include "ClpDualRowDantzig.hpp"
32#include "ClpLinearObjective.hpp"
33#include "ClpPrimalColumnSteepest.hpp"
34#include "ClpPrimalColumnDantzig.hpp"
35#include "ClpPresolve.hpp"
36#include "CbcOrClpParam.hpp"
37#include "OsiRowCutDebugger.hpp"
38#ifdef DMALLOC
39#include "dmalloc.h"
40#endif
41#ifdef WSSMP_BARRIER
42#define FOREIGN_BARRIER
43#endif
44#ifdef UFL_BARRIER
45#define FOREIGN_BARRIER
46#endif
47#ifdef TAUCS_BARRIER
48#define FOREIGN_BARRIER
49#endif
50#include "CoinWarmStartBasis.hpp"
51
52#include "OsiSolverInterface.hpp"
53#include "OsiCuts.hpp"
54#include "OsiRowCut.hpp"
55#include "OsiColCut.hpp"
56
57#include "CglPreProcess.hpp"
58#include "CglCutGenerator.hpp"
59#include "CglGomory.hpp"
60#include "CglProbing.hpp"
61#include "CglKnapsackCover.hpp"
62#include "CglRedSplit.hpp"
63#include "CglClique.hpp"
64#include "CglFlowCover.hpp"
65#include "CglMixedIntegerRounding2.hpp"
66#include "CglTwomir.hpp"
67#include "CglDuplicateRow.hpp"
68
69#include "CbcModel.hpp"
70#include "CbcHeuristic.hpp"
71#include "CbcHeuristicLocal.hpp"
72#include "CbcHeuristicGreedy.hpp"
73#include "CbcHeuristicFPump.hpp"
74#include "CbcTreeLocal.hpp"
75#include "CbcCompareActual.hpp"
76#include "CbcBranchActual.hpp"
77#include  "CbcOrClpParam.hpp"
78#include  "CbcCutGenerator.hpp"
79#include  "CbcStrategy.hpp"
80
81#include "OsiClpSolverInterface.hpp"
82#ifdef COIN_HAS_ASL
83#include "Cbc_ampl.h"
84static bool usingAmpl=false;
85#endif
86static double totalTime=0.0;
87static void statistics(ClpSimplex * originalModel, ClpSimplex * model);
88static bool maskMatches(const int * starts, char ** masks,
89                        std::string & check);
90static void generateCode(const char * fileName,int type,int preProcess);
91//#############################################################################
92
93#ifdef NDEBUG
94#undef NDEBUG
95#endif
96// Allow for interrupts
97// But is this threadsafe ? (so switched off by option)
98
99#include "CoinSignal.hpp"
100static CbcModel * currentBranchModel = NULL;
101
102extern "C" {
103   static void signal_handler(int whichSignal)
104   {
105      if (currentBranchModel!=NULL) 
106         currentBranchModel->setMaximumNodes(0); // stop at next node
107      return;
108   }
109}
110
111int mainTest (int argc, const char *argv[],int algorithm,
112              ClpSimplex empty, bool doPresolve,int switchOff);
113void CbcClpUnitTest (const CbcModel & saveModel);
114int CbcOrClpRead_mode=1;
115FILE * CbcOrClpReadCommand=stdin;
116static bool noPrinting=false;
117static int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment,
118                     bool changeInt)
119{
120  OsiSolverInterface * solver = solverMod->clone();
121  if (0) {
122    // just get increment
123    CbcModel model(*solver);
124    model.analyzeObjective();
125    double increment2=model.getCutoffIncrement();
126    printf("initial cutoff increment %g\n",increment2);
127  }
128  const double *objective = solver->getObjCoefficients() ;
129  const double *lower = solver->getColLower() ;
130  const double *upper = solver->getColUpper() ;
131  int numberColumns = solver->getNumCols() ;
132  int numberRows = solver->getNumRows();
133  double direction = solver->getObjSense();
134  int iRow,iColumn;
135
136  // Row copy
137  CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
138  const double * elementByRow = matrixByRow.getElements();
139  const int * column = matrixByRow.getIndices();
140  const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
141  const int * rowLength = matrixByRow.getVectorLengths();
142
143  // Column copy
144  CoinPackedMatrix  matrixByCol(*solver->getMatrixByCol());
145  const double * element = matrixByCol.getElements();
146  const int * row = matrixByCol.getIndices();
147  const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
148  const int * columnLength = matrixByCol.getVectorLengths();
149
150  const double * rowLower = solver->getRowLower();
151  const double * rowUpper = solver->getRowUpper();
152
153  char * ignore = new char [numberRows];
154  int * changed = new int[numberColumns];
155  int * which = new int[numberRows];
156  double * changeRhs = new double[numberRows];
157  memset(changeRhs,0,numberRows*sizeof(double));
158  memset(ignore,0,numberRows);
159  numberChanged=0;
160  int numberInteger=0;
161  for (iColumn=0;iColumn<numberColumns;iColumn++) {
162    if (upper[iColumn] > lower[iColumn]+1.0e-8&&solver->isInteger(iColumn)) 
163      numberInteger++;
164  }
165  bool finished=false;
166  while (!finished) {
167    int saveNumberChanged = numberChanged;
168    for (iRow=0;iRow<numberRows;iRow++) {
169      int numberContinuous=0;
170      double value1=0.0,value2=0.0;
171      bool allIntegerCoeff=true;
172      double sumFixed=0.0;
173      int jColumn1=-1,jColumn2=-1;
174      for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
175        int jColumn = column[j];
176        double value = elementByRow[j];
177        if (upper[jColumn] > lower[jColumn]+1.0e-8) {
178          if (!solver->isInteger(jColumn)) {
179            if (numberContinuous==0) {
180              jColumn1=jColumn;
181              value1=value;
182            } else {
183              jColumn2=jColumn;
184              value2=value;
185            }
186            numberContinuous++;
187          } else {
188            if (fabs(value-floor(value+0.5))>1.0e-12)
189              allIntegerCoeff=false;
190          }
191        } else {
192          sumFixed += lower[jColumn]*value;
193        }
194      }
195      double low = rowLower[iRow];
196      if (low>-1.0e20) {
197        low -= sumFixed;
198        if (fabs(low-floor(low+0.5))>1.0e-12)
199          allIntegerCoeff=false;
200      }
201      double up = rowUpper[iRow];
202      if (up<1.0e20) {
203        up -= sumFixed;
204        if (fabs(up-floor(up+0.5))>1.0e-12)
205          allIntegerCoeff=false;
206      }
207      if (!allIntegerCoeff)
208        continue; // can't do
209      if (numberContinuous==1) {
210        // see if really integer
211        // This does not allow for complicated cases
212        if (low==up) {
213          if (fabs(value1)>1.0e-3) {
214            value1 = 1.0/value1;
215            if (fabs(value1-floor(value1+0.5))<1.0e-12) {
216              // integer
217              changed[numberChanged++]=jColumn1;
218              solver->setInteger(jColumn1);
219              if (upper[jColumn1]>1.0e20)
220                solver->setColUpper(jColumn1,1.0e20);
221              if (lower[jColumn1]<-1.0e20)
222                solver->setColLower(jColumn1,-1.0e20);
223            }
224          }
225        } else {
226          if (fabs(value1)>1.0e-3) {
227            value1 = 1.0/value1;
228            if (fabs(value1-floor(value1+0.5))<1.0e-12) {
229              // This constraint will not stop it being integer
230              ignore[iRow]=1;
231            }
232          }
233        }
234      } else if (numberContinuous==2) {
235        if (low==up) {
236          /* need general theory - for now just look at 2 cases -
237             1 - +- 1 one in column and just costs i.e. matching objective
238             2 - +- 1 two in column but feeds into G/L row which will try and minimize
239          */
240          if (fabs(value1)==1.0&&value1*value2==-1.0&&!lower[jColumn1]
241              &&!lower[jColumn2]) {
242            int n=0;
243            int i;
244            double objChange=direction*(objective[jColumn1]+objective[jColumn2]);
245            double bound = CoinMin(upper[jColumn1],upper[jColumn2]);
246            bound = CoinMin(bound,1.0e20);
247            for ( i=columnStart[jColumn1];i<columnStart[jColumn1]+columnLength[jColumn1];i++) {
248              int jRow = row[i];
249              double value = element[i];
250              if (jRow!=iRow) {
251                which[n++]=jRow;
252                changeRhs[jRow]=value;
253              }
254            }
255            for ( i=columnStart[jColumn1];i<columnStart[jColumn1]+columnLength[jColumn1];i++) {
256              int jRow = row[i];
257              double value = element[i];
258              if (jRow!=iRow) {
259                if (!changeRhs[jRow]) {
260                  which[n++]=jRow;
261                  changeRhs[jRow]=value;
262                } else {
263                  changeRhs[jRow]+=value;
264                }
265              }
266            }
267            if (objChange>=0.0) {
268              // see if all rows OK
269              bool good=true;
270              for (i=0;i<n;i++) {
271                int jRow = which[i];
272                double value = changeRhs[jRow];
273                if (value) {
274                  value *= bound;
275                  if (rowLength[jRow]==1) {
276                    if (value>0.0) {
277                      double rhs = rowLower[jRow];
278                      if (rhs>0.0) {
279                        double ratio =rhs/value;
280                        if (fabs(ratio-floor(ratio+0.5))>1.0e-12)
281                          good=false;
282                      }
283                    } else {
284                      double rhs = rowUpper[jRow];
285                      if (rhs<0.0) {
286                        double ratio =rhs/value;
287                        if (fabs(ratio-floor(ratio+0.5))>1.0e-12)
288                          good=false;
289                      }
290                    }
291                  } else if (rowLength[jRow]==2) {
292                    if (value>0.0) {
293                      if (rowLower[jRow]>-1.0e20)
294                        good=false;
295                    } else {
296                      if (rowUpper[jRow]<1.0e20)
297                        good=false;
298                    }
299                  } else {
300                    good=false;
301                  }
302                }
303              }
304              if (good) {
305                // both can be integer
306                changed[numberChanged++]=jColumn1;
307                solver->setInteger(jColumn1);
308                if (upper[jColumn1]>1.0e20)
309                  solver->setColUpper(jColumn1,1.0e20);
310                if (lower[jColumn1]<-1.0e20)
311                  solver->setColLower(jColumn1,-1.0e20);
312                changed[numberChanged++]=jColumn2;
313                solver->setInteger(jColumn2);
314                if (upper[jColumn2]>1.0e20)
315                  solver->setColUpper(jColumn2,1.0e20);
316                if (lower[jColumn2]<-1.0e20)
317                  solver->setColLower(jColumn2,-1.0e20);
318              }
319            }
320            // clear
321            for (i=0;i<n;i++) {
322              changeRhs[which[i]]=0.0;
323            }
324          }
325        }
326      }
327    }
328    for (iColumn=0;iColumn<numberColumns;iColumn++) {
329      if (upper[iColumn] > lower[iColumn]+1.0e-8&&!solver->isInteger(iColumn)) {
330        double value;
331        value = upper[iColumn];
332        if (value<1.0e20&&fabs(value-floor(value+0.5))>1.0e-12) 
333          continue;
334        value = lower[iColumn];
335        if (value>-1.0e20&&fabs(value-floor(value+0.5))>1.0e-12) 
336          continue;
337        bool integer=true;
338        for (CoinBigIndex j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn];j++) {
339          int iRow = row[j];
340          if (!ignore[iRow]) {
341            integer=false;
342            break;
343          }
344        }
345        if (integer) {
346          // integer
347          changed[numberChanged++]=iColumn;
348          solver->setInteger(iColumn);
349          if (upper[iColumn]>1.0e20)
350            solver->setColUpper(iColumn,1.0e20);
351          if (lower[iColumn]<-1.0e20)
352            solver->setColLower(iColumn,-1.0e20);
353        }
354      }
355    }
356    finished = numberChanged==saveNumberChanged;
357  }
358  delete [] which;
359  delete [] changeRhs;
360  delete [] ignore;
361  if (numberInteger&&!noPrinting)
362    printf("%d integer variables",numberInteger);
363  if (changeInt) {
364    if (!noPrinting) {
365      if (numberChanged)
366        printf(" and %d variables made integer\n",numberChanged);
367      else
368        printf("\n");
369    }
370    delete [] ignore;
371    //increment=0.0;
372    if (!numberChanged) {
373      delete [] changed;
374      delete solver;
375      return NULL;
376    } else {
377      for (iColumn=0;iColumn<numberColumns;iColumn++) {
378        if (solver->isInteger(iColumn))
379          solverMod->setInteger(iColumn);
380      }
381      delete solver;
382      return changed;
383    }
384  } else {
385    if (!noPrinting) {
386      if (numberChanged)
387        printf(" and %d variables could be made integer\n",numberChanged);
388      else
389        printf("\n");
390    }
391    // just get increment
392    CbcModel model(*solver);
393    if (noPrinting)
394      model.setLogLevel(0);
395    model.analyzeObjective();
396    double increment2=model.getCutoffIncrement();
397    if (increment2>increment) {
398      if (!noPrinting)
399        printf("cutoff increment increased from %g to %g\n",increment,increment2);
400      increment=increment2;
401    }
402    delete solver;
403    numberChanged=0;
404    delete [] changed;
405    return NULL;
406  }
407}
408static int outDupRow(OsiSolverInterface * solver) 
409{
410  CglDuplicateRow dupCuts(solver);
411  CglTreeInfo info;
412  info.level = 0;
413  info.pass = 0;
414  int numberRows = solver->getNumRows();
415  info.formulation_rows = numberRows;
416  info.inTree = false;
417  info.strengthenRow= NULL;
418  info.pass = 0;
419  OsiCuts cs;
420  dupCuts.generateCuts(*solver,cs,info);
421  const int * duplicate = dupCuts.duplicate();
422  // Get rid of duplicate rows
423  int * which = new int[numberRows]; 
424  int numberDrop=0;
425  for (int iRow=0;iRow<numberRows;iRow++) {
426    if (duplicate[iRow]==-2||duplicate[iRow]>=0) 
427      which[numberDrop++]=iRow;
428  }
429  if (numberDrop) {
430    solver->deleteRows(numberDrop,which);
431  }
432  delete [] which;
433  // see if we have any column cuts
434  int numberColumnCuts = cs.sizeColCuts() ;
435  const double * columnLower = solver->getColLower();
436  const double * columnUpper = solver->getColUpper();
437  for (int k = 0;k<numberColumnCuts;k++) {
438    OsiColCut * thisCut = cs.colCutPtr(k) ;
439    const CoinPackedVector & lbs = thisCut->lbs() ;
440    const CoinPackedVector & ubs = thisCut->ubs() ;
441    int j ;
442    int n ;
443    const int * which ;
444    const double * values ;
445    n = lbs.getNumElements() ;
446    which = lbs.getIndices() ;
447    values = lbs.getElements() ;
448    for (j = 0;j<n;j++) {
449      int iColumn = which[j] ;
450      if (values[j]>columnLower[iColumn]) 
451        solver->setColLower(iColumn,values[j]) ;
452    }
453    n = ubs.getNumElements() ;
454    which = ubs.getIndices() ;
455    values = ubs.getElements() ;
456    for (j = 0;j<n;j++) {
457      int iColumn = which[j] ;
458      if (values[j]<columnUpper[iColumn]) 
459        solver->setColUpper(iColumn,values[j]) ;
460    }
461  }
462  return numberDrop;
463}
464int main (int argc, const char *argv[])
465{
466  /* Note
467     This is meant as a stand-alone executable to do as much of coin as possible.
468     It should only have one solver known to it.
469  */
470  {
471    double time1 = CoinCpuTime(),time2;
472    bool goodModel=false;
473    CoinSighandler_t saveSignal=SIG_DFL;
474    // register signal handler
475    saveSignal = signal(SIGINT,signal_handler);
476    // Set up all non-standard stuff
477    OsiClpSolverInterface solver1;
478    CbcModel model(solver1);
479    CbcModel * babModel = NULL;
480    model.setNumberBeforeTrust(21);
481    int cutPass=-1234567;
482    OsiSolverInterface * solver = model.solver();
483    OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
484    ClpSimplex * lpSolver = clpSolver->getModelPtr();
485    clpSolver->messageHandler()->setLogLevel(0) ;
486    model.messageHandler()->setLogLevel(1);
487    // For priorities etc
488    int * priorities=NULL;
489    int * branchDirection=NULL;
490    double * pseudoDown=NULL;
491    double * pseudoUp=NULL;
492    double * solutionIn = NULL;
493    int * prioritiesIn = NULL;
494    int numberSOS = 0;
495    int * sosStart = NULL;
496    int * sosIndices = NULL;
497    char * sosType = NULL;
498    double * sosReference = NULL;
499    int * sosPriority=NULL;
500#ifdef COIN_HAS_ASL
501    ampl_info info;
502    if (argc>2&&!strcmp(argv[2],"-AMPL")) {
503      usingAmpl=true;
504      int returnCode = readAmpl(&info,argc,const_cast<char **>(argv));
505      if (returnCode)
506        return returnCode;
507      CbcOrClpRead_mode=2; // so will start with parameters
508      // see if log in list
509      noPrinting=true;
510      for (int i=1;i<info.numberArguments;i++) {
511        if (!strcmp(info.arguments[i],"log")) {
512          if (i<info.numberArguments-1&&atoi(info.arguments[i+1])>0)
513            noPrinting=false;
514          break;
515        }
516      }
517      if (noPrinting) {
518        model.messageHandler()->setLogLevel(0);
519        setCbcOrClpPrinting(false);
520      }
521      if (!noPrinting)
522        printf("%d rows, %d columns and %d elements\n",
523               info.numberRows,info.numberColumns,info.numberElements);
524      solver->loadProblem(info.numberColumns,info.numberRows,info.starts,
525                          info.rows,info.elements,
526                          info.columnLower,info.columnUpper,info.objective,
527                          info.rowLower,info.rowUpper);
528      // If we had a solution use it
529      if (info.primalSolution) {
530        solver->setColSolution(info.primalSolution);
531      }
532      // status
533      if (info.rowStatus) {
534        unsigned char * statusArray = lpSolver->statusArray();
535        int i;
536        for (i=0;i<info.numberColumns;i++)
537          statusArray[i]=(char)info.columnStatus[i];
538        statusArray+=info.numberColumns;
539        for (i=0;i<info.numberRows;i++)
540          statusArray[i]=(char)info.rowStatus[i];
541        CoinWarmStartBasis * basis = lpSolver->getBasis();
542        solver->setWarmStart(basis);
543        delete basis;
544      }
545      freeArrays1(&info);
546      // modify objective if necessary
547      solver->setObjSense(info.direction);
548      solver->setDblParam(OsiObjOffset,info.offset);
549      // Set integer variables
550      for (int i=info.numberColumns-info.numberBinary-info.numberIntegers;
551           i<info.numberColumns;i++)
552        solver->setInteger(i);
553      goodModel=true;
554      // change argc etc
555      argc = info.numberArguments;
556      argv = const_cast<const char **>(info.arguments);
557    }
558#endif   
559    // default action on import
560    int allowImportErrors=0;
561    int keepImportNames=1;
562    int doIdiot=-1;
563    int outputFormat=2;
564    int slpValue=-1;
565    int cppValue=-1;
566    int printOptions=0;
567    int printMode=0;
568    int presolveOptions=0;
569    int substitution=3;
570    int dualize=0;
571    int doCrash=0;
572    int doSprint=-1;
573    int doScaling=1;
574    // set reasonable defaults
575    int preSolve=5;
576    int preProcess=4;
577    bool useStrategy=false;
578    bool preSolveFile=false;
579   
580    double djFix=1.0e100;
581    double gapRatio=1.0e100;
582    double tightenFactor=0.0;
583    lpSolver->setPerturbation(50);
584    lpSolver->messageHandler()->setPrefix(false);
585    const char dirsep =  CoinFindDirSeparator();
586    std::string directory = (dirsep == '/' ? "./" : ".\\");
587    std::string defaultDirectory = directory;
588    std::string importFile ="";
589    std::string exportFile ="default.mps";
590    std::string importBasisFile ="";
591    std::string importPriorityFile ="";
592    std::string debugFile="";
593    std::string printMask="";
594    double * debugValues = NULL;
595    int numberDebugValues = -1;
596    int basisHasValues=0;
597    std::string exportBasisFile ="default.bas";
598    std::string saveFile ="default.prob";
599    std::string restoreFile ="default.prob";
600    std::string solutionFile ="stdout";
601    std::string solutionSaveFile ="solution.file";
602#define CBCMAXPARAMETERS 200
603    CbcOrClpParam parameters[CBCMAXPARAMETERS];
604    int numberParameters ;
605    establishParams(numberParameters,parameters) ;
606    parameters[whichParam(BASISIN,numberParameters,parameters)].setStringValue(importBasisFile);
607    parameters[whichParam(PRIORITYIN,numberParameters,parameters)].setStringValue(importPriorityFile);
608    parameters[whichParam(BASISOUT,numberParameters,parameters)].setStringValue(exportBasisFile);
609    parameters[whichParam(DEBUG,numberParameters,parameters)].setStringValue(debugFile);
610    parameters[whichParam(PRINTMASK,numberParameters,parameters)].setStringValue(printMask);
611    parameters[whichParam(DIRECTORY,numberParameters,parameters)].setStringValue(directory);
612    parameters[whichParam(DUALBOUND,numberParameters,parameters)].setDoubleValue(lpSolver->dualBound());
613    parameters[whichParam(DUALTOLERANCE,numberParameters,parameters)].setDoubleValue(lpSolver->dualTolerance());
614    parameters[whichParam(EXPORT,numberParameters,parameters)].setStringValue(exportFile);
615    parameters[whichParam(IDIOT,numberParameters,parameters)].setIntValue(doIdiot);
616    parameters[whichParam(IMPORT,numberParameters,parameters)].setStringValue(importFile);
617    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].setDoubleValue(1.0e-8);
618    int slog = whichParam(SOLVERLOGLEVEL,numberParameters,parameters);
619    int log = whichParam(LOGLEVEL,numberParameters,parameters);
620    parameters[slog].setIntValue(0);
621    parameters[log].setIntValue(1);
622    parameters[whichParam(MAXFACTOR,numberParameters,parameters)].setIntValue(lpSolver->factorizationFrequency());
623    parameters[whichParam(MAXITERATION,numberParameters,parameters)].setIntValue(lpSolver->maximumIterations());
624    parameters[whichParam(OUTPUTFORMAT,numberParameters,parameters)].setIntValue(outputFormat);
625    parameters[whichParam(PRESOLVEPASS,numberParameters,parameters)].setIntValue(preSolve);
626    parameters[whichParam(PERTVALUE,numberParameters,parameters)].setIntValue(lpSolver->perturbation());
627    parameters[whichParam(PRIMALTOLERANCE,numberParameters,parameters)].setDoubleValue(lpSolver->primalTolerance());
628    parameters[whichParam(PRIMALWEIGHT,numberParameters,parameters)].setDoubleValue(lpSolver->infeasibilityCost());
629    parameters[whichParam(RESTORE,numberParameters,parameters)].setStringValue(restoreFile);
630    parameters[whichParam(SAVE,numberParameters,parameters)].setStringValue(saveFile);
631    //parameters[whichParam(TIMELIMIT,numberParameters,parameters)].setDoubleValue(1.0e8);
632    parameters[whichParam(TIMELIMIT_BAB,numberParameters,parameters)].setDoubleValue(1.0e8);
633    parameters[whichParam(SOLUTION,numberParameters,parameters)].setStringValue(solutionFile);
634    parameters[whichParam(SAVESOL,numberParameters,parameters)].setStringValue(solutionSaveFile);
635    parameters[whichParam(SPRINT,numberParameters,parameters)].setIntValue(doSprint);
636    parameters[whichParam(SUBSTITUTION,numberParameters,parameters)].setIntValue(substitution);
637    parameters[whichParam(DUALIZE,numberParameters,parameters)].setIntValue(dualize);
638    model.setNumberBeforeTrust(5);
639    parameters[whichParam(NUMBERBEFORE,numberParameters,parameters)].setIntValue(5);
640    parameters[whichParam(MAXNODES,numberParameters,parameters)].setIntValue(model.getMaximumNodes());
641    model.setNumberStrong(5);
642    parameters[whichParam(STRONGBRANCHING,numberParameters,parameters)].setIntValue(model.numberStrong());
643    parameters[whichParam(INFEASIBILITYWEIGHT,numberParameters,parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcInfeasibilityWeight));
644    parameters[whichParam(INTEGERTOLERANCE,numberParameters,parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcIntegerTolerance));
645    parameters[whichParam(INCREMENT,numberParameters,parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcCutoffIncrement));
646    // Set up likely cut generators and defaults
647    parameters[whichParam(PREPROCESS,numberParameters,parameters)].setCurrentOption("sos");
648    parameters[whichParam(MIPOPTIONS,numberParameters,parameters)].setIntValue(128|64|1);
649    parameters[whichParam(MOREMIPOPTIONS,numberParameters,parameters)].setIntValue(-1);
650    parameters[whichParam(MAXHOTITS,numberParameters,parameters)].setIntValue(100);
651    parameters[whichParam(CUTSSTRATEGY,numberParameters,parameters)].setCurrentOption("on");
652    parameters[whichParam(HEURISTICSTRATEGY,numberParameters,parameters)].setCurrentOption("on");
653    int doSOS=1;
654    int verbose=0;
655    CglGomory gomoryGen;
656    // try larger limit
657    gomoryGen.setLimitAtRoot(512);
658    gomoryGen.setLimit(50);
659    // set default action (0=off,1=on,2=root)
660    int gomoryAction=3;
661    parameters[whichParam(GOMORYCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
662
663    CglProbing probingGen;
664    probingGen.setUsingObjective(true);
665    probingGen.setMaxPass(3);
666    probingGen.setMaxPassRoot(3);
667    // Number of unsatisfied variables to look at
668    probingGen.setMaxProbe(10);
669    probingGen.setMaxProbeRoot(50);
670    // How far to follow the consequences
671    probingGen.setMaxLook(10);
672    probingGen.setMaxLookRoot(50);
673    probingGen.setMaxLookRoot(10);
674    // Only look at rows with fewer than this number of elements
675    probingGen.setMaxElements(200);
676    probingGen.setRowCuts(3);
677    // set default action (0=off,1=on,2=root)
678    int probingAction=3;
679    parameters[whichParam(PROBINGCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
680
681    CglKnapsackCover knapsackGen;
682    //knapsackGen.switchOnExpensive();
683    // set default action (0=off,1=on,2=root)
684    int knapsackAction=3;
685    parameters[whichParam(KNAPSACKCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
686
687    CglRedSplit redsplitGen;
688    //redsplitGen.setLimit(100);
689    // set default action (0=off,1=on,2=root)
690    // Off as seems to give some bad cuts
691    int redsplitAction=0;
692    parameters[whichParam(REDSPLITCUTS,numberParameters,parameters)].setCurrentOption("root");
693
694    CglClique cliqueGen(false,true);
695    cliqueGen.setStarCliqueReport(false);
696    cliqueGen.setRowCliqueReport(false);
697    cliqueGen.setMinViolation(0.1);
698    // set default action (0=off,1=on,2=root)
699    int cliqueAction=3;
700    parameters[whichParam(CLIQUECUTS,numberParameters,parameters)].setCurrentOption("ifmove");
701
702    CglMixedIntegerRounding2 mixedGen;
703    // set default action (0=off,1=on,2=root)
704    int mixedAction=3;
705    parameters[whichParam(MIXEDCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
706
707    CglFlowCover flowGen;
708    // set default action (0=off,1=on,2=root)
709    int flowAction=3;
710    parameters[whichParam(FLOWCUTS,numberParameters,parameters)].setCurrentOption("ifmove");
711
712    CglTwomir twomirGen;
713    twomirGen.setMaxElements(250);
714    // set default action (0=off,1=on,2=root)
715    int twomirAction=2;
716    parameters[whichParam(TWOMIRCUTS,numberParameters,parameters)].setCurrentOption("root");
717
718    bool useRounding=true;
719    parameters[whichParam(ROUNDING,numberParameters,parameters)].setCurrentOption("on");
720    bool useFpump=true;
721    parameters[whichParam(FPUMP,numberParameters,parameters)].setCurrentOption("on");
722    bool useGreedy=true;
723    parameters[whichParam(GREEDY,numberParameters,parameters)].setCurrentOption("on");
724    bool useCombine=true;
725    parameters[whichParam(COMBINE,numberParameters,parameters)].setCurrentOption("on");
726    bool useLocalTree=false;
727    parameters[whichParam(COSTSTRATEGY,numberParameters,parameters)].setCurrentOption("off");
728    int useCosts=0;
729    // don't use input solution
730    int useSolution=0;
731   
732    // total number of commands read
733    int numberGoodCommands=0;
734    // Set false if user does anything advanced
735    bool defaultSettings=true;
736
737    // Hidden stuff for barrier
738    int choleskyType = 0;
739    int gamma=0;
740    int scaleBarrier=0;
741    int doKKT=0;
742    int crossover=2; // do crossover unless quadratic
743    // For names
744    int lengthName = 0;
745    std::vector<std::string> rowNames;
746    std::vector<std::string> columnNames;
747   
748    std::string field;
749    if (!noPrinting) {
750      std::cout<<"Coin Cbc and Clp Solver version "<<CBCVERSION
751               <<", build "<<__DATE__<<std::endl;
752      // Print command line
753      if (argc>1) {
754        printf("command line - ");
755        for (int i=0;i<argc;i++)
756          printf("%s ",argv[i]);
757        printf("\n");
758      }
759    }
760    while (1) {
761      // next command
762      field=CoinReadGetCommand(argc,argv);
763      // exit if null or similar
764      if (!field.length()) {
765        if (numberGoodCommands==1&&goodModel) {
766          // we just had file name - do branch and bound
767          field="branch";
768        } else if (!numberGoodCommands) {
769          // let's give the sucker a hint
770          std::cout
771            <<"CoinSolver takes input from arguments ( - switches to stdin)"
772            <<std::endl
773            <<"Enter ? for list of commands or help"<<std::endl;
774          field="-";
775        } else {
776          break;
777        }
778      }
779     
780      // see if ? at end
781      int numberQuery=0;
782      if (field!="?"&&field!="???") {
783        int length = field.length();
784        int i;
785        for (i=length-1;i>0;i--) {
786          if (field[i]=='?') 
787            numberQuery++;
788          else
789            break;
790        }
791        field=field.substr(0,length-numberQuery);
792      }
793      // find out if valid command
794      int iParam;
795      int numberMatches=0;
796      int firstMatch=-1;
797      for ( iParam=0; iParam<numberParameters; iParam++ ) {
798        int match = parameters[iParam].matches(field);
799        if (match==1) {
800          numberMatches = 1;
801          firstMatch=iParam;
802          break;
803        } else {
804          if (match&&firstMatch<0)
805            firstMatch=iParam;
806          numberMatches += match>>1;
807        }
808      }
809      if (iParam<numberParameters&&!numberQuery) {
810        // found
811        CbcOrClpParam found = parameters[iParam];
812        CbcOrClpParameterType type = found.type();
813        int valid;
814        numberGoodCommands++;
815        if (type==BAB&&goodModel) {
816          // check if any integers
817          if (!lpSolver->integerInformation())
818            type=DUALSIMPLEX;
819        }
820        if (type==GENERALQUERY) {
821          bool evenHidden=false;
822          if ((verbose&8)!=0) {
823            // even hidden
824            evenHidden = true;
825            verbose &= ~8;
826          }
827#ifdef COIN_HAS_ASL
828          if (verbose<4&&usingAmpl)
829            verbose +=4;
830#endif
831          if (verbose<4) {
832            std::cout<<"In argument list keywords have leading - "
833              ", -stdin or just - switches to stdin"<<std::endl;
834            std::cout<<"One command per line (and no -)"<<std::endl;
835            std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
836            std::cout<<"abcd?? adds explanation, if only one fuller help"<<std::endl;
837            std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
838            std::cout<<"abcd value sets value"<<std::endl;
839            std::cout<<"Commands are:"<<std::endl;
840          } else {
841            std::cout<<"Cbc options are set within AMPL with commands like:"<<std::endl<<std::endl;
842            std::cout<<"         option cbc_options \"cuts=root log=2 feas=on slog=1\""<<std::endl<<std::endl;
843            std::cout<<"only maximize, dual, primal, help and quit are recognized without ="<<std::endl;
844          }
845          int maxAcross=5;
846          if ((verbose%4)!=0)
847            maxAcross=1;
848          int limits[]={1,51,101,151,201,251,301,351,401};
849          std::vector<std::string> types;
850          types.push_back("Double parameters:");
851          types.push_back("Branch and Cut double parameters:");
852          types.push_back("Integer parameters:");
853          types.push_back("Branch and Cut integer parameters:");
854          types.push_back("Keyword parameters:");
855          types.push_back("Branch and Cut keyword parameters:");
856          types.push_back("Actions or string parameters:");
857          types.push_back("Branch and Cut actions:");
858          int iType;
859          for (iType=0;iType<8;iType++) {
860            int across=0;
861            if ((verbose%4)!=0)
862              std::cout<<std::endl;
863            std::cout<<types[iType]<<std::endl;
864            if ((verbose&2)!=0)
865              std::cout<<std::endl;
866            for ( iParam=0; iParam<numberParameters; iParam++ ) {
867              int type = parameters[iParam].type();
868              if ((parameters[iParam].displayThis()||evenHidden)&&
869                  type>=limits[iType]
870                  &&type<limits[iType+1]) {
871                // but skip if not useful for ampl (and in ampl mode)
872                if (verbose>=4&&(parameters[iParam].whereUsed()&4)==0)
873                  continue;
874                if (!across) {
875                  if ((verbose&2)==0) 
876                    std::cout<<"  ";
877                  else
878                    std::cout<<"Command ";
879                }
880                std::cout<<parameters[iParam].matchName()<<"  ";
881                across++;
882                if (across==maxAcross) {
883                  across=0;
884                  if ((verbose%4)!=0) {
885                    // put out description as well
886                    if ((verbose&1)!=0) 
887                      std::cout<<parameters[iParam].shortHelp();
888                    std::cout<<std::endl;
889                    if ((verbose&2)!=0) {
890                      std::cout<<"---- description"<<std::endl;
891                      parameters[iParam].printLongHelp();
892                      std::cout<<"----"<<std::endl<<std::endl;
893                    }
894                  } else {
895                    std::cout<<std::endl;
896                  }
897                }
898              }
899            }
900            if (across)
901              std::cout<<std::endl;
902          }
903        } else if (type==FULLGENERALQUERY) {
904          std::cout<<"Full list of commands is:"<<std::endl;
905          int maxAcross=5;
906          int limits[]={1,51,101,151,201,251,301,351,401};
907          std::vector<std::string> types;
908          types.push_back("Double parameters:");
909          types.push_back("Branch and Cut double parameters:");
910          types.push_back("Integer parameters:");
911          types.push_back("Branch and Cut integer parameters:");
912          types.push_back("Keyword parameters:");
913          types.push_back("Branch and Cut keyword parameters:");
914          types.push_back("Actions or string parameters:");
915          types.push_back("Branch and Cut actions:");
916          int iType;
917          for (iType=0;iType<8;iType++) {
918            int across=0;
919            std::cout<<types[iType]<<"  ";
920            for ( iParam=0; iParam<numberParameters; iParam++ ) {
921              int type = parameters[iParam].type();
922              if (type>=limits[iType]
923                  &&type<limits[iType+1]) {
924                if (!across)
925                  std::cout<<"  ";
926                std::cout<<parameters[iParam].matchName()<<"  ";
927                across++;
928                if (across==maxAcross) {
929                  std::cout<<std::endl;
930                  across=0;
931                }
932              }
933            }
934            if (across)
935              std::cout<<std::endl;
936          }
937        } else if (type<101) {
938          // get next field as double
939          double value = CoinReadGetDoubleField(argc,argv,&valid);
940          if (!valid) {
941            if (type<51) {
942              parameters[iParam].setDoubleParameter(lpSolver,value);
943            } else if (type<81) {
944              parameters[iParam].setDoubleParameter(model,value);
945            } else {
946              parameters[iParam].setDoubleParameter(lpSolver,value);
947              switch(type) {
948              case DJFIX:
949                djFix=value;
950                preSolve=5;
951                defaultSettings=false; // user knows what she is doing
952                break;
953              case GAPRATIO:
954                gapRatio=value;
955                break;
956              case TIGHTENFACTOR:
957                tightenFactor=value;
958                defaultSettings=false; // user knows what she is doing
959                break;
960              default:
961                abort();
962              }
963            }
964          } else if (valid==1) {
965            abort();
966          } else {
967            std::cout<<parameters[iParam].name()<<" has value "<<
968              parameters[iParam].doubleValue()<<std::endl;
969          }
970        } else if (type<201) {
971          // get next field as int
972          int value = CoinReadGetIntField(argc,argv,&valid);
973          if (!valid) {
974            if (type<151) {
975              if (parameters[iParam].type()==PRESOLVEPASS)
976                preSolve = value;
977              else if (parameters[iParam].type()==IDIOT)
978                doIdiot = value;
979              else if (parameters[iParam].type()==SPRINT)
980                doSprint = value;
981              else if (parameters[iParam].type()==OUTPUTFORMAT)
982                outputFormat = value;
983              else if (parameters[iParam].type()==SLPVALUE)
984                slpValue = value;
985              else if (parameters[iParam].type()==CPP)
986                cppValue = value;
987              else if (parameters[iParam].type()==PRESOLVEOPTIONS)
988                presolveOptions = value;
989              else if (parameters[iParam].type()==PRINTOPTIONS)
990                printOptions = value;
991              else if (parameters[iParam].type()==SUBSTITUTION)
992                substitution = value;
993              else if (parameters[iParam].type()==DUALIZE)
994                dualize = value;
995              else if (parameters[iParam].type()==CUTPASS)
996                cutPass = value;
997              else if (parameters[iParam].type()==VERBOSE)
998                verbose = value;
999              else if (parameters[iParam].type()==FPUMPITS)
1000                { useFpump = true;parameters[iParam].setIntValue(value);}
1001              parameters[iParam].setIntParameter(lpSolver,value);
1002            } else {
1003              parameters[iParam].setIntParameter(model,value);
1004            }
1005          } else if (valid==1) {
1006            abort();
1007          } else {
1008            std::cout<<parameters[iParam].name()<<" has value "<<
1009              parameters[iParam].intValue()<<std::endl;
1010          }
1011        } else if (type<301) {
1012          // one of several strings
1013          std::string value = CoinReadGetString(argc,argv);
1014          int action = parameters[iParam].parameterOption(value);
1015          if (action<0) {
1016            if (value!="EOL") {
1017              // no match
1018              parameters[iParam].printOptions();
1019            } else {
1020              // print current value
1021              std::cout<<parameters[iParam].name()<<" has value "<<
1022                parameters[iParam].currentOption()<<std::endl;
1023            }
1024          } else {
1025            parameters[iParam].setCurrentOption(action,!noPrinting);
1026            // for now hard wired
1027            switch (type) {
1028            case DIRECTION:
1029              if (action==0)
1030                lpSolver->setOptimizationDirection(1);
1031              else if (action==1)
1032                lpSolver->setOptimizationDirection(-1);
1033              else
1034                lpSolver->setOptimizationDirection(0);
1035              break;
1036            case DUALPIVOT:
1037              if (action==0) {
1038                ClpDualRowSteepest steep(3);
1039                lpSolver->setDualRowPivotAlgorithm(steep);
1040              } else if (action==1) {
1041                //ClpDualRowDantzig dantzig;
1042                ClpDualRowSteepest dantzig(5);
1043                lpSolver->setDualRowPivotAlgorithm(dantzig);
1044              } else if (action==2) {
1045                // partial steep
1046                ClpDualRowSteepest steep(2);
1047                lpSolver->setDualRowPivotAlgorithm(steep);
1048              } else {
1049                ClpDualRowSteepest steep;
1050                lpSolver->setDualRowPivotAlgorithm(steep);
1051              }
1052              break;
1053            case PRIMALPIVOT:
1054              if (action==0) {
1055                ClpPrimalColumnSteepest steep(3);
1056                lpSolver->setPrimalColumnPivotAlgorithm(steep);
1057              } else if (action==1) {
1058                ClpPrimalColumnSteepest steep(0);
1059                lpSolver->setPrimalColumnPivotAlgorithm(steep);
1060              } else if (action==2) {
1061                ClpPrimalColumnDantzig dantzig;
1062                lpSolver->setPrimalColumnPivotAlgorithm(dantzig);
1063              } else if (action==3) {
1064                ClpPrimalColumnSteepest steep(2);
1065                lpSolver->setPrimalColumnPivotAlgorithm(steep);
1066              } else if (action==4) {
1067                ClpPrimalColumnSteepest steep(1);
1068                lpSolver->setPrimalColumnPivotAlgorithm(steep);
1069              } else if (action==5) {
1070                ClpPrimalColumnSteepest steep(4);
1071                lpSolver->setPrimalColumnPivotAlgorithm(steep);
1072              } else if (action==6) {
1073                ClpPrimalColumnSteepest steep(10);
1074                lpSolver->setPrimalColumnPivotAlgorithm(steep);
1075              }
1076              break;
1077            case SCALING:
1078              lpSolver->scaling(action);
1079              solver->setHintParam(OsiDoScale,action!=0,OsiHintTry);
1080              doScaling = 1-action;
1081              break;
1082            case AUTOSCALE:
1083              lpSolver->setAutomaticScaling(action!=0);
1084              break;
1085            case SPARSEFACTOR:
1086              lpSolver->setSparseFactorization((1-action)!=0);
1087              break;
1088            case BIASLU:
1089              lpSolver->factorization()->setBiasLU(action);
1090              break;
1091            case PERTURBATION:
1092              if (action==0)
1093                lpSolver->setPerturbation(50);
1094              else
1095                lpSolver->setPerturbation(100);
1096              break;
1097            case ERRORSALLOWED:
1098              allowImportErrors = action;
1099              break;
1100            case INTPRINT:
1101              printMode=action;
1102              break;
1103              //case ALGORITHM:
1104              //algorithm  = action;
1105              //defaultSettings=false; // user knows what she is doing
1106              //abort();
1107              //break;
1108            case KEEPNAMES:
1109              keepImportNames = 1-action;
1110              break;
1111            case PRESOLVE:
1112              if (action==0)
1113                preSolve = 5;
1114              else if (action==1)
1115                preSolve=0;
1116              else if (action==2)
1117                preSolve=10;
1118              else
1119                preSolveFile=true;
1120              break;
1121            case PFI:
1122              lpSolver->factorization()->setForrestTomlin(action==0);
1123              break;
1124            case CRASH:
1125              doCrash=action;
1126              break;
1127            case MESSAGES:
1128              lpSolver->messageHandler()->setPrefix(action!=0);
1129              break;
1130            case CHOLESKY:
1131              choleskyType = action;
1132              break;
1133            case GAMMA:
1134              gamma=action;
1135              break;
1136            case BARRIERSCALE:
1137              scaleBarrier=action;
1138              break;
1139            case KKT:
1140              doKKT=action;
1141              break;
1142            case CROSSOVER:
1143              crossover=action;
1144              break;
1145            case SOS:
1146              doSOS=action;
1147              break;
1148            case GOMORYCUTS:
1149              defaultSettings=false; // user knows what she is doing
1150              gomoryAction = action;
1151              break;
1152            case PROBINGCUTS:
1153              defaultSettings=false; // user knows what she is doing
1154              probingAction = action;
1155              break;
1156            case KNAPSACKCUTS:
1157              defaultSettings=false; // user knows what she is doing
1158              knapsackAction = action;
1159              break;
1160            case REDSPLITCUTS:
1161              defaultSettings=false; // user knows what she is doing
1162              redsplitAction = action;
1163              break;
1164            case CLIQUECUTS:
1165              defaultSettings=false; // user knows what she is doing
1166              cliqueAction = action;
1167              break;
1168            case FLOWCUTS:
1169              defaultSettings=false; // user knows what she is doing
1170              flowAction = action;
1171              break;
1172            case MIXEDCUTS:
1173              defaultSettings=false; // user knows what she is doing
1174              mixedAction = action;
1175              break;
1176            case TWOMIRCUTS:
1177              defaultSettings=false; // user knows what she is doing
1178              twomirAction = action;
1179              break;
1180            case ROUNDING:
1181              defaultSettings=false; // user knows what she is doing
1182              useRounding = action;
1183              break;
1184            case FPUMP:
1185              defaultSettings=false; // user knows what she is doing
1186              useFpump=action;
1187              break;
1188            case CUTSSTRATEGY:
1189              gomoryAction = action;
1190              probingAction = action;
1191              knapsackAction = action;
1192              cliqueAction = action;
1193              flowAction = action;
1194              mixedAction = action;
1195              twomirAction = action;
1196              parameters[whichParam(GOMORYCUTS,numberParameters,parameters)].setCurrentOption(action);
1197              parameters[whichParam(PROBINGCUTS,numberParameters,parameters)].setCurrentOption(action);
1198              parameters[whichParam(KNAPSACKCUTS,numberParameters,parameters)].setCurrentOption(action);
1199              if (!action) {
1200                redsplitAction = action;
1201                parameters[whichParam(REDSPLITCUTS,numberParameters,parameters)].setCurrentOption(action);
1202              }
1203              parameters[whichParam(CLIQUECUTS,numberParameters,parameters)].setCurrentOption(action);
1204              parameters[whichParam(FLOWCUTS,numberParameters,parameters)].setCurrentOption(action);
1205              parameters[whichParam(MIXEDCUTS,numberParameters,parameters)].setCurrentOption(action);
1206              parameters[whichParam(TWOMIRCUTS,numberParameters,parameters)].setCurrentOption(action);
1207              break;
1208            case HEURISTICSTRATEGY:
1209              useRounding = action;
1210              useGreedy = action;
1211              useCombine = action;
1212              //useLocalTree = action;
1213              useFpump=action;
1214              parameters[whichParam(ROUNDING,numberParameters,parameters)].setCurrentOption(action);
1215              parameters[whichParam(GREEDY,numberParameters,parameters)].setCurrentOption(action);
1216              parameters[whichParam(COMBINE,numberParameters,parameters)].setCurrentOption(action);
1217              //parameters[whichParam(LOCALTREE,numberParameters,parameters)].setCurrentOption(action);
1218              parameters[whichParam(FPUMP,numberParameters,parameters)].setCurrentOption(action);
1219              break;
1220            case GREEDY:
1221              defaultSettings=false; // user knows what she is doing
1222              useGreedy = action;
1223              break;
1224            case COMBINE:
1225              defaultSettings=false; // user knows what she is doing
1226              useCombine = action;
1227              break;
1228            case LOCALTREE:
1229              defaultSettings=false; // user knows what she is doing
1230              useLocalTree = action;
1231              break;
1232            case COSTSTRATEGY:
1233              useCosts=action;
1234              break;
1235            case PREPROCESS:
1236              preProcess = action;
1237              break;
1238            case USESOLUTION:
1239              useSolution = action;
1240              break;
1241            default:
1242              abort();
1243            }
1244          }
1245        } else {
1246          // action
1247          if (type==EXIT) {
1248#ifdef COIN_HAS_ASL
1249            if(usingAmpl) {
1250              if (info.numberIntegers||info.numberBinary) {
1251                // integer
1252              } else {
1253                // linear
1254              }
1255              writeAmpl(&info);
1256              freeArrays2(&info);
1257              freeArgs(&info);
1258            }
1259#endif
1260            break; // stop all
1261          }
1262          switch (type) {
1263          case DUALSIMPLEX:
1264          case PRIMALSIMPLEX:
1265          case SOLVECONTINUOUS:
1266          case BARRIER:
1267            if (goodModel) {
1268              double objScale = 
1269                parameters[whichParam(OBJSCALE2,numberParameters,parameters)].doubleValue();
1270              if (objScale!=1.0) {
1271                int iColumn;
1272                int numberColumns=lpSolver->numberColumns();
1273                double * dualColumnSolution = 
1274                  lpSolver->dualColumnSolution();
1275                ClpObjective * obj = lpSolver->objectiveAsObject();
1276                assert(dynamic_cast<ClpLinearObjective *> (obj));
1277                double offset;
1278                double * objective = obj->gradient(NULL,NULL,offset,true);
1279                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1280                  dualColumnSolution[iColumn] *= objScale;
1281                  objective[iColumn] *= objScale;;
1282                }
1283                int iRow;
1284                int numberRows=lpSolver->numberRows();
1285                double * dualRowSolution = 
1286                  lpSolver->dualRowSolution();
1287                for (iRow=0;iRow<numberRows;iRow++) 
1288                  dualRowSolution[iRow] *= objScale;
1289                lpSolver->setObjectiveOffset(objScale*lpSolver->objectiveOffset());
1290              }
1291              ClpSolve::SolveType method;
1292              ClpSolve::PresolveType presolveType;
1293              ClpSimplex * model2 = lpSolver;
1294              if (dualize) {
1295                model2 = ((ClpSimplexOther *) model2)->dualOfModel();
1296                printf("Dual of model has %d rows and %d columns\n",
1297                       model2->numberRows(),model2->numberColumns());
1298                model2->setOptimizationDirection(1.0);
1299              }
1300              if (noPrinting)
1301                lpSolver->setLogLevel(0);
1302              ClpSolve solveOptions;
1303              solveOptions.setPresolveActions(presolveOptions);
1304              solveOptions.setSubstitution(substitution);
1305              if (preSolve!=5&&preSolve) {
1306                presolveType=ClpSolve::presolveNumber;
1307                if (preSolve<0) {
1308                  preSolve = - preSolve;
1309                  if (preSolve<=100) {
1310                    presolveType=ClpSolve::presolveNumber;
1311                    printf("Doing %d presolve passes - picking up non-costed slacks\n",
1312                           preSolve);
1313                    solveOptions.setDoSingletonColumn(true);
1314                  } else {
1315                    preSolve -=100;
1316                    presolveType=ClpSolve::presolveNumberCost;
1317                    printf("Doing %d presolve passes - picking up costed slacks\n",
1318                           preSolve);
1319                  }
1320                } 
1321              } else if (preSolve) {
1322                presolveType=ClpSolve::presolveOn;
1323              } else {
1324                presolveType=ClpSolve::presolveOff;
1325              }
1326              solveOptions.setPresolveType(presolveType,preSolve);
1327              if (type==DUALSIMPLEX||type==SOLVECONTINUOUS) {
1328                method=ClpSolve::useDual;
1329              } else if (type==PRIMALSIMPLEX) {
1330                method=ClpSolve::usePrimalorSprint;
1331              } else {
1332                method = ClpSolve::useBarrier;
1333                if (crossover==1) {
1334                  method=ClpSolve::useBarrierNoCross;
1335                } else if (crossover==2) {
1336                  ClpObjective * obj = lpSolver->objectiveAsObject();
1337                  if (obj->type()>1) {
1338                    method=ClpSolve::useBarrierNoCross;
1339                    presolveType=ClpSolve::presolveOff;
1340                    solveOptions.setPresolveType(presolveType,preSolve);
1341                  } 
1342                }
1343              }
1344              solveOptions.setSolveType(method);
1345              if(preSolveFile)
1346                presolveOptions |= 0x40000000;
1347              solveOptions.setSpecialOption(4,presolveOptions);
1348              solveOptions.setSpecialOption(5,printOptions);
1349              if (method==ClpSolve::useDual) {
1350                // dual
1351                if (doCrash)
1352                  solveOptions.setSpecialOption(0,1,doCrash); // crash
1353                else if (doIdiot)
1354                  solveOptions.setSpecialOption(0,2,doIdiot); // possible idiot
1355              } else if (method==ClpSolve::usePrimalorSprint) {
1356                // primal
1357                // if slp turn everything off
1358                if (slpValue>0) {
1359                  doCrash=false;
1360                  doSprint=0;
1361                  doIdiot=-1;
1362                  solveOptions.setSpecialOption(1,10,slpValue); // slp
1363                  method=ClpSolve::usePrimal;
1364                }
1365                if (doCrash) {
1366                  solveOptions.setSpecialOption(1,1,doCrash); // crash
1367                } else if (doSprint>0) {
1368                  // sprint overrides idiot
1369                  solveOptions.setSpecialOption(1,3,doSprint); // sprint
1370                } else if (doIdiot>0) {
1371                  solveOptions.setSpecialOption(1,2,doIdiot); // idiot
1372                } else if (slpValue<=0) {
1373                  if (doIdiot==0) {
1374                    if (doSprint==0)
1375                      solveOptions.setSpecialOption(1,4); // all slack
1376                    else
1377                      solveOptions.setSpecialOption(1,9); // all slack or sprint
1378                  } else {
1379                    if (doSprint==0)
1380                      solveOptions.setSpecialOption(1,8); // all slack or idiot
1381                    else
1382                      solveOptions.setSpecialOption(1,7); // initiative
1383                  }
1384                }
1385                if (basisHasValues==-1)
1386                  solveOptions.setSpecialOption(1,11); // switch off values
1387              } else if (method==ClpSolve::useBarrier||method==ClpSolve::useBarrierNoCross) {
1388                int barrierOptions = choleskyType;
1389                if (scaleBarrier)
1390                  barrierOptions |= 8;
1391                if (doKKT)
1392                  barrierOptions |= 16;
1393                if (gamma)
1394                  barrierOptions |= 32*gamma;
1395                if (crossover==3) 
1396                  barrierOptions |= 256; // try presolve in crossover
1397                solveOptions.setSpecialOption(4,barrierOptions);
1398              }
1399              model2->initialSolve(solveOptions);
1400              basisHasValues=1;
1401              if (dualize) {
1402                ((ClpSimplexOther *) lpSolver)->restoreFromDual(model2);
1403                delete model2;
1404                model2=lpSolver;
1405              }
1406#ifdef COIN_HAS_ASL
1407              if (usingAmpl) {
1408                double value = model2->getObjValue()*model2->getObjSense();
1409                char buf[300];
1410                int pos=0;
1411                int iStat = model2->status();
1412                if (iStat==0) {
1413                  pos += sprintf(buf+pos,"optimal," );
1414                } else if (iStat==1) {
1415                  // infeasible
1416                  pos += sprintf(buf+pos,"infeasible,");
1417                } else if (iStat==2) {
1418                  // unbounded
1419                  pos += sprintf(buf+pos,"unbounded,");
1420                } else if (iStat==3) {
1421                  pos += sprintf(buf+pos,"stopped on iterations or time,");
1422                } else if (iStat==4) {
1423                  iStat = 7;
1424                  pos += sprintf(buf+pos,"stopped on difficulties,");
1425                } else if (iStat==5) {
1426                  iStat = 3;
1427                  pos += sprintf(buf+pos,"stopped on ctrl-c,");
1428                } else {
1429                  pos += sprintf(buf+pos,"status unknown,");
1430                  iStat=6;
1431                }
1432                info.problemStatus=iStat;
1433                info.objValue = value;
1434                pos += sprintf(buf+pos," objective %.*g",ampl_obj_prec(),
1435                               value);
1436                sprintf(buf+pos,"\n%d iterations",
1437                        model2->getIterationCount());
1438                free(info.primalSolution);
1439                int numberColumns=model2->numberColumns();
1440                info.primalSolution = (double *) malloc(numberColumns*sizeof(double));
1441                CoinCopyN(model2->primalColumnSolution(),numberColumns,info.primalSolution);
1442                int numberRows = model2->numberRows();
1443                free(info.dualSolution);
1444                info.dualSolution = (double *) malloc(numberRows*sizeof(double));
1445                CoinCopyN(model2->dualRowSolution(),numberRows,info.dualSolution);
1446                CoinWarmStartBasis * basis = model2->getBasis();
1447                free(info.rowStatus);
1448                info.rowStatus = (int *) malloc(numberRows*sizeof(int));
1449                free(info.columnStatus);
1450                info.columnStatus = (int *) malloc(numberColumns*sizeof(int));
1451                // Put basis in
1452                int i;
1453                // free,basic,ub,lb are 0,1,2,3
1454                for (i=0;i<numberRows;i++) {
1455                  CoinWarmStartBasis::Status status = basis->getArtifStatus(i);
1456                  info.rowStatus[i]=status;
1457                }
1458                for (i=0;i<numberColumns;i++) {
1459                  CoinWarmStartBasis::Status status = basis->getStructStatus(i);
1460                  info.columnStatus[i]=status;
1461                }
1462                // put buffer into info
1463                strcpy(info.buffer,buf);
1464                delete basis;
1465              }
1466#endif
1467            } else {
1468              std::cout<<"** Current model not valid"<<std::endl;
1469            }
1470            break;
1471          case STATISTICS:
1472            if (goodModel) {
1473              // If presolve on look at presolved
1474              bool deleteModel2=false;
1475              ClpSimplex * model2 = lpSolver;
1476              if (preSolve) {
1477                ClpPresolve pinfo;
1478                int presolveOptions2 = presolveOptions&~0x40000000;
1479                if ((presolveOptions2&0xffff)!=0)
1480                  pinfo.setPresolveActions(presolveOptions2);
1481                pinfo.setSubstitution(substitution);
1482                if ((printOptions&1)!=0)
1483                  pinfo.statistics();
1484                double presolveTolerance = 
1485                  parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
1486                model2 = 
1487                  pinfo.presolvedModel(*lpSolver,presolveTolerance,
1488                                       true,preSolve);
1489                if (model2) {
1490                  printf("Statistics for presolved model\n");
1491                  deleteModel2=true;
1492                } else {
1493                  printf("Presolved model looks infeasible - will use unpresolved\n");
1494                  model2 = lpSolver;
1495                }
1496              } else {
1497                printf("Statistics for unpresolved model\n");
1498                model2 =  lpSolver;
1499              }
1500              statistics(lpSolver,model2);
1501              if (deleteModel2)
1502                delete model2;
1503            } else {
1504              std::cout<<"** Current model not valid"<<std::endl;
1505            }
1506            break;
1507          case TIGHTEN:
1508            if (goodModel) {
1509              int numberInfeasibilities = lpSolver->tightenPrimalBounds();
1510              if (numberInfeasibilities)
1511                std::cout<<"** Analysis indicates model infeasible"<<std::endl;
1512            } else {
1513              std::cout<<"** Current model not valid"<<std::endl;
1514            }
1515            break;
1516          case PLUSMINUS:
1517            if (goodModel) {
1518              ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
1519              ClpPackedMatrix* clpMatrix =
1520                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1521              if (clpMatrix) {
1522                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
1523                if (newMatrix->getIndices()) {
1524                  lpSolver->replaceMatrix(newMatrix);
1525                  delete saveMatrix;
1526                  std::cout<<"Matrix converted to +- one matrix"<<std::endl;
1527                } else {
1528                  std::cout<<"Matrix can not be converted to +- 1 matrix"<<std::endl;
1529                }
1530              } else {
1531                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1532              }
1533            } else {
1534              std::cout<<"** Current model not valid"<<std::endl;
1535            }
1536            break;
1537          case OUTDUPROWS:
1538            if (goodModel) {
1539              int nOut = outDupRow(clpSolver);
1540              if (nOut&&!noPrinting)
1541                printf("%d rows eliminated\n",nOut);
1542            } else {
1543              std::cout<<"** Current model not valid"<<std::endl;
1544            }
1545            break;
1546          case NETWORK:
1547            if (goodModel) {
1548              ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
1549              ClpPackedMatrix* clpMatrix =
1550                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1551              if (clpMatrix) {
1552                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
1553                if (newMatrix->getIndices()) {
1554                  lpSolver->replaceMatrix(newMatrix);
1555                  delete saveMatrix;
1556                  std::cout<<"Matrix converted to network matrix"<<std::endl;
1557                } else {
1558                  std::cout<<"Matrix can not be converted to network matrix"<<std::endl;
1559                }
1560              } else {
1561                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1562              }
1563            } else {
1564              std::cout<<"** Current model not valid"<<std::endl;
1565            }
1566            break;
1567          case MIPLIB:
1568            // User can set options - main differenec is lack of model and CglPreProcess
1569            goodModel=true;
1570/*
1571  Run branch-and-cut. First set a few options -- node comparison, scaling. If
1572  the solver is Clp, consider running some presolve code (not yet converted
1573  this to generic OSI) with branch-and-cut. If presolve is disabled, or the
1574  solver is not Clp, simply run branch-and-cut. Print elapsed time at the end.
1575*/
1576          case BAB: // branchAndBound
1577          case STRENGTHEN:
1578            if (goodModel) {
1579              bool miplib = type==MIPLIB;
1580              int logLevel = parameters[slog].intValue();
1581              // Reduce printout
1582              if (logLevel<=1)
1583                model.solver()->setHintParam(OsiDoReducePrint,true,OsiHintTry);
1584              // Don't switch off all output
1585              {
1586                OsiSolverInterface * solver = model.solver();
1587                OsiClpSolverInterface * si =
1588                  dynamic_cast<OsiClpSolverInterface *>(solver) ;
1589                assert (si != NULL);
1590                si->setSpecialOptions(0x40000000);
1591              }
1592              if (!miplib) {
1593                model.initialSolve();
1594                OsiSolverInterface * solver = model.solver();
1595                OsiClpSolverInterface * si =
1596                  dynamic_cast<OsiClpSolverInterface *>(solver) ;
1597                if (si->getModelPtr()->tightenPrimalBounds()!=0) {
1598                  std::cout<<"Problem is infeasible - tightenPrimalBounds!"<<std::endl;
1599                  exit(1);
1600                }
1601                si->getModelPtr()->dual();  // clean up
1602              }
1603              // If user made settings then use them
1604              if (!defaultSettings) {
1605                OsiSolverInterface * solver = model.solver();
1606                if (!doScaling)
1607                  solver->setHintParam(OsiDoScale,false,OsiHintTry);
1608                OsiClpSolverInterface * si =
1609                  dynamic_cast<OsiClpSolverInterface *>(solver) ;
1610                assert (si != NULL);
1611                // get clp itself
1612                ClpSimplex * modelC = si->getModelPtr();
1613                //if (modelC->tightenPrimalBounds()!=0) {
1614                //std::cout<<"Problem is infeasible!"<<std::endl;
1615                //break;
1616                //}
1617                // bounds based on continuous
1618                if (tightenFactor) {
1619                  if (modelC->tightenPrimalBounds(tightenFactor)!=0) {
1620                    std::cout<<"Problem is infeasible!"<<std::endl;
1621                    break;
1622                  }
1623                }
1624                if (djFix<1.0e20) {
1625                  // do some fixing
1626                  int numberColumns = modelC->numberColumns();
1627                  int i;
1628                  const char * type = modelC->integerInformation();
1629                  double * lower = modelC->columnLower();
1630                  double * upper = modelC->columnUpper();
1631                  double * solution = modelC->primalColumnSolution();
1632                  double * dj = modelC->dualColumnSolution();
1633                  int numberFixed=0;
1634                  for (i=0;i<numberColumns;i++) {
1635                    if (type[i]) {
1636                      double value = solution[i];
1637                      if (value<lower[i]+1.0e-5&&dj[i]>djFix) {
1638                        solution[i]=lower[i];
1639                        upper[i]=lower[i];
1640                        numberFixed++;
1641                      } else if (value>upper[i]-1.0e-5&&dj[i]<-djFix) {
1642                        solution[i]=upper[i];
1643                        lower[i]=upper[i];
1644                        numberFixed++;
1645                      }
1646                    }
1647                  }
1648                  printf("%d columns fixed\n",numberFixed);
1649                }
1650              }
1651              // See if we want preprocessing
1652              OsiSolverInterface * saveSolver=NULL;
1653              CglPreProcess process;
1654              delete babModel;
1655              babModel = new CbcModel(model);
1656              OsiSolverInterface * solver3 = clpSolver->clone();
1657              babModel->assignSolver(solver3);
1658              OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
1659              int numberChanged=0;
1660              if (clpSolver2->messageHandler()->logLevel())
1661                clpSolver2->messageHandler()->setLogLevel(1);
1662              if (logLevel>-1)
1663                clpSolver2->messageHandler()->setLogLevel(logLevel);
1664              lpSolver = clpSolver2->getModelPtr();
1665              if (lpSolver->factorizationFrequency()==200&&!miplib) {
1666                // User did not touch preset
1667                int numberRows = lpSolver->numberRows();
1668                const int cutoff1=10000;
1669                const int cutoff2=100000;
1670                const int base=75;
1671                const int freq0 = 50;
1672                const int freq1=200;
1673                const int freq2=400;
1674                const int maximum=1000;
1675                int frequency;
1676                if (numberRows<cutoff1)
1677                  frequency=base+numberRows/freq0;
1678                else if (numberRows<cutoff2)
1679                  frequency=base+cutoff1/freq0 + (numberRows-cutoff1)/freq1;
1680                else
1681                  frequency=base+cutoff1/freq0 + (cutoff2-cutoff1)/freq1 + (numberRows-cutoff2)/freq2;
1682                lpSolver->setFactorizationFrequency(CoinMin(maximum,frequency));
1683              }
1684              time2 = CoinCpuTime();
1685              totalTime += time2-time1;
1686              time1 = time2;
1687              double timeLeft = babModel->getMaximumSeconds();
1688              int numberOriginalColumns = babModel->solver()->getNumCols();
1689              if (preProcess==6) {
1690                // use strategy instead
1691                preProcess=0;
1692                useStrategy=true;
1693              }
1694              if (preProcess&&type==BAB) {
1695                saveSolver=babModel->solver()->clone();
1696                /* Do not try and produce equality cliques and
1697                   do up to 10 passes */
1698                OsiSolverInterface * solver2;
1699                {
1700                  // Tell solver we are in Branch and Cut
1701                  saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;
1702                  // Default set of cut generators
1703                  CglProbing generator1;
1704                  generator1.setUsingObjective(true);
1705                  generator1.setMaxPass(3);
1706                  generator1.setMaxProbeRoot(saveSolver->getNumCols());
1707                  generator1.setMaxElements(100);
1708                  generator1.setMaxLookRoot(50);
1709                  generator1.setRowCuts(3);
1710                  // Add in generators
1711                  process.addCutGenerator(&generator1);
1712                  int translate[]={9999,0,0,-1,2,3};
1713                  process.messageHandler()->setLogLevel(babModel->logLevel());
1714#ifdef COIN_HAS_ASL
1715                  if (info.numberSos&&doSOS&&usingAmpl) {
1716                    // SOS
1717                    numberSOS = info.numberSos;
1718                    sosStart = info.sosStart;
1719                    sosIndices = info.sosIndices;
1720                  }
1721#endif
1722                  if (numberSOS&&doSOS) {
1723                    // SOS
1724                    int numberColumns = saveSolver->getNumCols();
1725                    char * prohibited = new char[numberColumns];
1726                    memset(prohibited,0,numberColumns);
1727                    int n=sosStart[numberSOS];
1728                    for (int i=0;i<n;i++) {
1729                      int iColumn = sosIndices[i];
1730                      prohibited[iColumn]=1;
1731                    }
1732                    process.passInProhibited(prohibited,numberColumns);
1733                    delete [] prohibited;
1734                  }
1735                  solver2 = process.preProcessNonDefault(*saveSolver,translate[preProcess],10);
1736                  // Tell solver we are not in Branch and Cut
1737                  saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
1738                  if (solver2)
1739                    solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;
1740                }
1741#ifdef COIN_HAS_ASL
1742                if (!solver2&&usingAmpl) {
1743                  // infeasible
1744                  info.problemStatus=1;
1745                  info.objValue = 1.0e100;
1746                  sprintf(info.buffer,"infeasible by pre-processing");
1747                  info.primalSolution=NULL;
1748                  info.dualSolution=NULL;
1749                  break;
1750                }
1751#endif
1752                if (!noPrinting) {
1753                  if (!solver2) {
1754                    printf("Pre-processing says infeasible\n");
1755                    break;
1756                  } else {
1757                    printf("processed model has %d rows, %d columns and %d elements\n",
1758                           solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements());
1759                  }
1760                }
1761                //solver2->resolve();
1762                if (preProcess==2) {
1763                  OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (solver2);
1764                  ClpSimplex * lpSolver = clpSolver2->getModelPtr();
1765                  lpSolver->writeMps("presolved.mps",0,1,lpSolver->optimizationDirection());
1766                  printf("Preprocessed model (minimization) on presolved.mps\n");
1767                }
1768                // we have to keep solver2 so pass clone
1769                solver2 = solver2->clone();
1770                babModel->assignSolver(solver2);
1771                babModel->initialSolve();
1772                babModel->setMaximumSeconds(timeLeft-(CoinCpuTime()-time1));
1773              }
1774              // now tighten bounds
1775              if (!miplib) {
1776                OsiClpSolverInterface * si =
1777                  dynamic_cast<OsiClpSolverInterface *>(babModel->solver()) ;
1778                assert (si != NULL);
1779                // get clp itself
1780                ClpSimplex * modelC = si->getModelPtr();
1781                if (noPrinting)
1782                  modelC->setLogLevel(0);
1783                if (modelC->tightenPrimalBounds()!=0) {
1784                  std::cout<<"Problem is infeasible!"<<std::endl;
1785                  break;
1786                }
1787                modelC->dual();
1788              }
1789              if (debugValues) {
1790                // for debug
1791                std::string problemName ;
1792                babModel->solver()->getStrParam(OsiProbName,problemName) ;
1793                //babModel->solver()->activateRowCutDebugger(problemName.c_str()) ;
1794                twomirGen.probname_=strdup(problemName.c_str());
1795                // checking seems odd
1796                //redsplitGen.set_given_optsol(babModel->solver()->getRowCutDebuggerAlways()->optimalSolution(),
1797                //                         babModel->getNumCols());
1798              }
1799              if (useCosts) {
1800                int numberColumns = babModel->getNumCols();
1801                int * sort = new int[numberColumns];
1802                double * dsort = new double[numberColumns];
1803                int * priority = new int [numberColumns];
1804                const double * objective = babModel->getObjCoefficients();
1805                int iColumn;
1806                int n=0;
1807                for (iColumn=0;iColumn<numberColumns;iColumn++) {
1808                  if (babModel->isInteger(iColumn)) {
1809                    sort[n]=n;
1810                    if (useCosts==1)
1811                      dsort[n++]=-objective[iColumn];
1812                    else
1813                      dsort[n++]=iColumn;
1814                  }
1815                }
1816                CoinSort_2(dsort,dsort+n,sort);
1817                int level=0;
1818                double last = -1.0e100;
1819                for (int i=0;i<n;i++) {
1820                  int iPut=sort[i];
1821                  if (dsort[i]!=last) {
1822                    level++;
1823                    last=dsort[i];
1824                  }
1825                  priority[iPut]=level;
1826                }
1827                babModel->passInPriorities( priority,false);
1828                delete [] priority;
1829                delete [] sort;
1830                delete [] dsort;
1831              }
1832              // FPump done first as it only works if no solution
1833              CbcHeuristicFPump heuristic4(*babModel);
1834              if (useFpump) {
1835                heuristic4.setMaximumPasses(parameters[whichParam(FPUMPITS,numberParameters,parameters)].intValue());
1836                babModel->addHeuristic(&heuristic4);
1837              }
1838              if (!miplib) {
1839                CbcRounding heuristic1(*babModel);
1840                if (useRounding)
1841                  babModel->addHeuristic(&heuristic1) ;
1842                CbcHeuristicLocal heuristic2(*babModel);
1843                heuristic2.setSearchType(1);
1844                if (useCombine)
1845                  babModel->addHeuristic(&heuristic2);
1846                CbcHeuristicGreedyCover heuristic3(*babModel);
1847                CbcHeuristicGreedyEquality heuristic3a(*babModel);
1848                if (useGreedy) {
1849                  babModel->addHeuristic(&heuristic3);
1850                  babModel->addHeuristic(&heuristic3a);
1851                }
1852                if (useLocalTree) {
1853                  CbcTreeLocal localTree(babModel,NULL,10,0,0,10000,2000);
1854                  babModel->passInTreeHandler(localTree);
1855                }
1856              }
1857              if (type==MIPLIB) {
1858                if (babModel->numberStrong()==5&&babModel->numberBeforeTrust()==5) 
1859                  babModel->setNumberBeforeTrust(50);
1860              }
1861              // add cut generators if wanted
1862              int switches[20];
1863              int numberGenerators=0;
1864              if (probingAction==1) {
1865                babModel->addCutGenerator(&probingGen,-1,"Probing");
1866                switches[numberGenerators++]=0;
1867              } else if (probingAction>=2) {
1868                babModel->addCutGenerator(&probingGen,-101+probingAction,"Probing");
1869                switches[numberGenerators++]=0;
1870              }
1871              if (gomoryAction==1) {
1872                babModel->addCutGenerator(&gomoryGen,-1,"Gomory");
1873                switches[numberGenerators++]=1;
1874              } else if (gomoryAction>=2) {
1875                babModel->addCutGenerator(&gomoryGen,-101+gomoryAction,"Gomory");
1876                switches[numberGenerators++]=-1;
1877              }
1878              if (knapsackAction==1) {
1879                babModel->addCutGenerator(&knapsackGen,-1,"Knapsack");
1880                switches[numberGenerators++]=0;
1881              } else if (knapsackAction>=2) {
1882                babModel->addCutGenerator(&knapsackGen,-101+knapsackAction,"Knapsack");
1883                switches[numberGenerators++]=0;
1884              }
1885              if (redsplitAction==1) {
1886                babModel->addCutGenerator(&redsplitGen,-1,"Reduce-and-split");
1887                switches[numberGenerators++]=1;
1888              } else if (redsplitAction>=2) {
1889                babModel->addCutGenerator(&redsplitGen,-101+redsplitAction,"Reduce-and-split");
1890                switches[numberGenerators++]=1;
1891              }
1892              if (cliqueAction==1) {
1893                babModel->addCutGenerator(&cliqueGen,-1,"Clique");
1894                switches[numberGenerators++]=1;
1895              } else if (cliqueAction>=2) {
1896                babModel->addCutGenerator(&cliqueGen,-101+cliqueAction,"Clique");
1897                switches[numberGenerators++]=-1;
1898              }
1899              if (mixedAction==1) {
1900                babModel->addCutGenerator(&mixedGen,-1,"MixedIntegerRounding2");
1901                switches[numberGenerators++]=1;
1902              } else if (mixedAction>=2) {
1903                babModel->addCutGenerator(&mixedGen,-101+mixedAction,"MixedIntegerRounding2");
1904                switches[numberGenerators++]=-1;
1905              }
1906              if (flowAction==1) {
1907                babModel->addCutGenerator(&flowGen,-1,"FlowCover");
1908                switches[numberGenerators++]=1;
1909              } else if (flowAction>=2) {
1910                babModel->addCutGenerator(&flowGen,-101+flowAction,"FlowCover");
1911                switches[numberGenerators++]=1;
1912              }
1913              if (twomirAction==1) {
1914                babModel->addCutGenerator(&twomirGen,-1,"TwoMirCuts");
1915                switches[numberGenerators++]=1;
1916              } else if (twomirAction>=2) {
1917                babModel->addCutGenerator(&twomirGen,-101+twomirAction,"TwoMirCuts");
1918                switches[numberGenerators++]=1;
1919              }
1920              // Say we want timings
1921              numberGenerators = babModel->numberCutGenerators();
1922              int iGenerator;
1923              int cutDepth=
1924                parameters[whichParam(CUTDEPTH,numberParameters,parameters)].intValue();
1925              for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
1926                CbcCutGenerator * generator = babModel->cutGenerator(iGenerator);
1927                int howOften = generator->howOften();
1928                if (howOften==-98||howOften==-99) 
1929                  generator->setSwitchOffIfLessThan(switches[iGenerator]);
1930                generator->setTiming(true);
1931                if (cutDepth>=0)
1932                  generator->setWhatDepth(cutDepth) ;
1933              }
1934              // Could tune more
1935              if (!miplib) {
1936                babModel->setMinimumDrop(min(5.0e-2,
1937                                             fabs(babModel->getMinimizationObjValue())*1.0e-3+1.0e-4));
1938                if (cutPass==-1234567) {
1939                  if (babModel->getNumCols()<500)
1940                    babModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible
1941                  else if (babModel->getNumCols()<5000)
1942                    babModel->setMaximumCutPassesAtRoot(100); // use minimum drop
1943                  else
1944                    babModel->setMaximumCutPassesAtRoot(20);
1945                } else {
1946                  babModel->setMaximumCutPassesAtRoot(cutPass);
1947                }
1948                babModel->setMaximumCutPasses(1);
1949              }
1950              // Do more strong branching if small
1951              //if (babModel->getNumCols()<5000)
1952              //babModel->setNumberStrong(20);
1953              // Switch off strong branching if wanted
1954              //if (babModel->getNumCols()>10*babModel->getNumRows())
1955              //babModel->setNumberStrong(0);
1956              if (!noPrinting) {
1957                babModel->messageHandler()->setLogLevel(parameters[log].intValue());
1958                if (babModel->getNumCols()>2000||babModel->getNumRows()>1500||
1959                    babModel->messageHandler()->logLevel()>1)
1960                  babModel->setPrintFrequency(100);
1961              }
1962             
1963              babModel->solver()->setIntParam(OsiMaxNumIterationHotStart,
1964                    parameters[whichParam(MAXHOTITS,numberParameters,parameters)].intValue());
1965              OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
1966              // go faster stripes
1967              if (osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
1968                osiclp->setupForRepeatedUse(2,parameters[slog].intValue());
1969              } else {
1970                osiclp->setupForRepeatedUse(0,parameters[slog].intValue());
1971              }
1972              double increment=babModel->getCutoffIncrement();;
1973              int * changed = NULL;
1974              if (!miplib)
1975                changed=analyze( osiclp,numberChanged,increment,false);
1976              if (debugValues) {
1977                if (numberDebugValues==babModel->getNumCols()) {
1978                  // for debug
1979                  babModel->solver()->activateRowCutDebugger(debugValues) ;
1980                } else {
1981                  printf("debug file has incorrect number of columns\n");
1982                }
1983              }
1984              babModel->setCutoffIncrement(CoinMax(babModel->getCutoffIncrement(),increment));
1985              // Turn this off if you get problems
1986              // Used to be automatically set
1987              int mipOptions = parameters[whichParam(MIPOPTIONS,numberParameters,parameters)].intValue();
1988              if (mipOptions!=(128|64|1))
1989                printf("mip options %d\n",mipOptions);
1990              osiclp->setSpecialOptions(mipOptions);
1991              if (gapRatio < 1.0e100) {
1992                double value = babModel->solver()->getObjValue() ;
1993                double value2 = gapRatio*(1.0e-5+fabs(value)) ;
1994                babModel->setAllowableGap(value2) ;
1995                std::cout << "Continuous " << value
1996                          << ", so allowable gap set to "
1997                          << value2 << std::endl ;
1998              }
1999              // probably faster to use a basis to get integer solutions
2000              babModel->setSpecialOptions(2);
2001              currentBranchModel = babModel;
2002              OsiSolverInterface * strengthenedModel=NULL;
2003              if (type==BAB||type==MIPLIB) {
2004                int moreMipOptions = parameters[whichParam(MOREMIPOPTIONS,numberParameters,parameters)].intValue();
2005                if (moreMipOptions>=0) {
2006                  printf("more mip options %d\n",moreMipOptions);
2007                  babModel->setSearchStrategy(moreMipOptions);
2008                }
2009              }
2010              if (type==BAB) {
2011#ifdef COIN_HAS_ASL
2012                if (usingAmpl) {
2013                  priorities=info.priorities;
2014                  branchDirection=info.branchDirection;
2015                  pseudoDown=info.pseudoDown;
2016                  pseudoUp=info.pseudoUp;
2017                  solutionIn=info.primalSolution;
2018                  prioritiesIn = info.priorities;
2019                  if (info.numberSos&&doSOS) {
2020                    // SOS
2021                    numberSOS = info.numberSos;
2022                    sosStart = info.sosStart;
2023                    sosIndices = info.sosIndices;
2024                    sosType = info.sosType;
2025                    sosReference = info.sosReference;
2026                    sosPriority = info.sosPriority;
2027                  }
2028                }
2029#endif               
2030                const int * originalColumns = preProcess ? process.originalColumns() : NULL;
2031                if (solutionIn&&useSolution) {
2032                  if (preProcess) {
2033                    int numberColumns = babModel->getNumCols();
2034                    // extend arrays in case SOS
2035                    int n = originalColumns[numberColumns-1]+1;
2036                    int nSmaller = CoinMin(n,numberOriginalColumns);
2037                    double * solutionIn2 = new double [n];
2038                    int * prioritiesIn2 = new int[n];
2039                    int i;
2040                    for (i=0;i<nSmaller;i++) {
2041                      solutionIn2[i]=solutionIn[i];
2042                      prioritiesIn2[i]=prioritiesIn[i];
2043                    }
2044                    for (;i<n;i++) {
2045                      solutionIn2[i]=0.0;
2046                      prioritiesIn2[i]=1000000;
2047                    }
2048                    int iLast=-1;
2049                    for (i=0;i<numberColumns;i++) {
2050                      int iColumn = originalColumns[i];
2051                      assert (iColumn>iLast);
2052                      iLast=iColumn;
2053                      solutionIn2[i]=solutionIn2[iColumn];
2054                      if (prioritiesIn)
2055                        prioritiesIn2[i]=prioritiesIn2[iColumn];
2056                    }
2057                    babModel->setHotstartSolution(solutionIn2,prioritiesIn2);
2058                    delete [] solutionIn2;
2059                    delete [] prioritiesIn2;
2060                  } else {
2061                    babModel->setHotstartSolution(solutionIn,prioritiesIn);
2062                  }
2063                }
2064                if (preProcess&&process.numberSOS()) {
2065                  int numberSOS = process.numberSOS();
2066                  int numberIntegers = babModel->numberIntegers();
2067                  /* model may not have created objects
2068                     If none then create
2069                  */
2070                  if (!numberIntegers||!babModel->numberObjects()) {
2071                    int type = (pseudoUp) ? 1 : 0;
2072                    babModel->findIntegers(true,type);
2073                    numberIntegers = babModel->numberIntegers();
2074                  }
2075                  CbcObject ** oldObjects = babModel->objects();
2076                  // Do sets and priorities
2077                  CbcObject ** objects = new CbcObject * [numberSOS];
2078                  // set old objects to have low priority
2079                  int numberOldObjects = babModel->numberObjects();
2080                  int numberColumns = babModel->getNumCols();
2081                  for (int iObj = 0;iObj<numberOldObjects;iObj++) {
2082                    oldObjects[iObj]->setPriority(numberColumns+1);
2083                    int iColumn = oldObjects[iObj]->columnNumber();
2084                    assert (iColumn>=0);
2085                    if (iColumn>=numberOriginalColumns)
2086                      continue;
2087                    if (originalColumns)
2088                      iColumn = originalColumns[iColumn];
2089                    if (branchDirection)
2090                      oldObjects[iObj]->setPreferredWay(branchDirection[iColumn]);
2091                    if (pseudoUp) {
2092                      CbcSimpleIntegerPseudoCost * obj1a =
2093                        dynamic_cast <CbcSimpleIntegerPseudoCost *>(oldObjects[iObj]) ;
2094                      assert (obj1a);
2095                      if (pseudoDown[iColumn]>0.0)
2096                        obj1a->setDownPseudoCost(pseudoDown[iColumn]);
2097                      if (pseudoUp[iColumn]>0.0)
2098                        obj1a->setUpPseudoCost(pseudoUp[iColumn]);
2099                    }
2100                  }
2101                  const int * starts = process.startSOS();
2102                  const int * which = process.whichSOS();
2103                  const int * type = process.typeSOS();
2104                  const double * weight = process.weightSOS();
2105                  int iSOS;
2106                  for (iSOS =0;iSOS<numberSOS;iSOS++) {
2107                    int iStart = starts[iSOS];
2108                    int n=starts[iSOS+1]-iStart;
2109                    objects[iSOS] = new CbcSOS(babModel,n,which+iStart,weight+iStart,
2110                                               iSOS,type[iSOS]);
2111                    // branch on long sets first
2112                    objects[iSOS]->setPriority(numberColumns-n);
2113                  }
2114                  babModel->addObjects(numberSOS,objects);
2115                  for (iSOS=0;iSOS<numberSOS;iSOS++)
2116                    delete objects[iSOS];
2117                  delete [] objects;
2118                } else if (priorities||branchDirection||pseudoDown||pseudoUp||numberSOS) {
2119                  // do anyway for priorities etc
2120                  int numberIntegers = babModel->numberIntegers();
2121                  /* model may not have created objects
2122                     If none then create
2123                  */
2124                  if (!numberIntegers||!babModel->numberObjects()) {
2125                    int type = (pseudoUp) ? 1 : 0;
2126                    babModel->findIntegers(true,type);
2127                  }
2128                  if (numberSOS) {
2129                    // Do sets and priorities
2130                    CbcObject ** objects = new CbcObject * [numberSOS];
2131                    int iSOS;
2132                    if (originalColumns) {
2133                      // redo sequence numbers
2134                      int numberColumns = babModel->getNumCols();
2135                      int nOld = originalColumns[numberColumns-1]+1;
2136                      int * back = new int[nOld];
2137                      int i;
2138                      for (i=0;i<nOld;i++)
2139                        back[i]=-1;
2140                      for (i=0;i<numberColumns;i++)
2141                        back[originalColumns[i]]=i;
2142                      // Really need better checks
2143                      int nMissing=0;
2144                      int n=sosStart[numberSOS];
2145                      for (i=0;i<n;i++) {
2146                        int iColumn = sosIndices[i];
2147                        int jColumn = back[iColumn];
2148                        if (jColumn>=0) 
2149                          sosIndices[i] = jColumn;
2150                        else 
2151                          nMissing++;
2152                      }
2153                      delete [] back;
2154                      if (nMissing)
2155                        printf("%d SOS variables vanished due to pre processing? - check validity?\n",nMissing);
2156                    }
2157                    for (iSOS =0;iSOS<numberSOS;iSOS++) {
2158                      int iStart = sosStart[iSOS];
2159                      int n=sosStart[iSOS+1]-iStart;
2160                      objects[iSOS] = new CbcSOS(babModel,n,sosIndices+iStart,sosReference+iStart,
2161                                                 iSOS,sosType[iSOS]);
2162                      if (sosPriority)
2163                        objects[iSOS]->setPriority(sosPriority[iSOS]);
2164                      else if (!prioritiesIn)
2165                        objects[iSOS]->setPriority(10);  // rather than 1000
2166                    }
2167                    babModel->addObjects(numberSOS,objects);
2168                    for (iSOS=0;iSOS<numberSOS;iSOS++)
2169                      delete objects[iSOS];
2170                    delete [] objects;
2171                  }
2172                  CbcObject ** objects = babModel->objects();
2173                  int numberObjects = babModel->numberObjects();
2174                  for (int iObj = 0;iObj<numberObjects;iObj++) {
2175                    // skip sos
2176                    CbcSOS * objSOS =
2177                      dynamic_cast <CbcSOS *>(objects[iObj]) ;
2178                    if (objSOS)
2179                      continue;
2180                    int iColumn = objects[iObj]->columnNumber();
2181                    assert (iColumn>=0);
2182                    if (originalColumns)
2183                      iColumn = originalColumns[iColumn];
2184                    if (branchDirection)
2185                      objects[iObj]->setPreferredWay(branchDirection[iColumn]);
2186                    if (priorities) {
2187                      int iPriority = priorities[iColumn];
2188                      if (iPriority>0)
2189                        objects[iObj]->setPriority(iPriority);
2190                    }
2191                    if (pseudoUp&&pseudoUp[iColumn]) {
2192                      CbcSimpleIntegerPseudoCost * obj1a =
2193                        dynamic_cast <CbcSimpleIntegerPseudoCost *>(objects[iObj]) ;
2194                      assert (obj1a);
2195                      if (pseudoDown[iColumn]>0.0)
2196                        obj1a->setDownPseudoCost(pseudoDown[iColumn]);
2197                      if (pseudoUp[iColumn]>0.0)
2198                        obj1a->setUpPseudoCost(pseudoUp[iColumn]);
2199                    }
2200                  }
2201                }
2202                int statistics = (printOptions>0) ? printOptions: 0;
2203#ifdef COIN_HAS_ASL
2204                if (!usingAmpl) {
2205#endif
2206                  free(priorities);
2207                  priorities=NULL;
2208                  free(branchDirection);
2209                  branchDirection=NULL;
2210                  free(pseudoDown);
2211                  pseudoDown=NULL;
2212                  free(pseudoUp);
2213                  pseudoUp=NULL;
2214                  free(solutionIn);
2215                  solutionIn=NULL;
2216                  free(prioritiesIn);
2217                  prioritiesIn=NULL;
2218                  free(sosStart);
2219                  sosStart=NULL;
2220                  free(sosIndices);
2221                  sosIndices=NULL;
2222                  free(sosType);
2223                  sosType=NULL;
2224                  free(sosReference);
2225                  sosReference=NULL;
2226                  free(sosPriority);
2227                  sosPriority=NULL;
2228#ifdef COIN_HAS_ASL
2229                }
2230#endif               
2231                if (cppValue>=0) {
2232                  int prepro = useStrategy ? -1 : preProcess;
2233                  // generate code
2234                  FILE * fp = fopen("user_driver.cpp","w");
2235                  if (fp) {
2236                    // generate enough to do BAB
2237                    babModel->generateCpp(fp,1);
2238                    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
2239                    // Make general so do factorization
2240                    int factor = osiclp->getModelPtr()->factorizationFrequency();
2241                    osiclp->getModelPtr()->setFactorizationFrequency(200);
2242                    osiclp->generateCpp(fp);
2243                    osiclp->getModelPtr()->setFactorizationFrequency(factor);
2244                    //solveOptions.generateCpp(fp);
2245                    fclose(fp);
2246                    // now call generate code
2247                    generateCode("user_driver.cpp",cppValue,prepro);
2248                  } else {
2249                    std::cout<<"Unable to open file user_driver.cpp"<<std::endl;
2250                  }
2251                }
2252                if (!babModel->numberStrong())
2253                  babModel->setNumberBeforeTrust(0);
2254                if (useStrategy) {
2255                  CbcStrategyDefault strategy(true,babModel->numberStrong(),babModel->numberBeforeTrust());
2256                  strategy.setupPreProcessing(1);
2257                  babModel->setStrategy(strategy);
2258                }
2259                babModel->branchAndBound(statistics);
2260              } else if (type==MIPLIB) {
2261                CbcStrategyDefault strategy(true,5,5);
2262                // Set up pre-processing to find sos if wanted
2263                if (preProcess)
2264                  strategy.setupPreProcessing(2);
2265                babModel->setStrategy(strategy);
2266                CbcClpUnitTest(*babModel);
2267                goodModel=false;
2268                break;
2269              } else {
2270                strengthenedModel = babModel->strengthenedModel();
2271              }
2272              currentBranchModel = NULL;
2273              osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
2274              if (debugFile=="createAfterPre"&&babModel->bestSolution()) {
2275                lpSolver = osiclp->getModelPtr();
2276                //move best solution (should be there -- but ..)
2277                int n = lpSolver->getNumCols();
2278                memcpy(lpSolver->primalColumnSolution(),babModel->bestSolution(),n*sizeof(double));
2279                saveSolution(osiclp->getModelPtr(),"debug.file");
2280              }
2281              if (!noPrinting) {
2282                // Print more statistics
2283                std::cout<<"Cuts at root node changed objective from "<<babModel->getContinuousObjective()
2284                         <<" to "<<babModel->rootObjectiveAfterCuts()<<std::endl;
2285               
2286                for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
2287                  CbcCutGenerator * generator = babModel->cutGenerator(iGenerator);
2288                  std::cout<<generator->cutGeneratorName()<<" was tried "
2289                           <<generator->numberTimesEntered()<<" times and created "
2290                           <<generator->numberCutsInTotal()<<" cuts of which "
2291                           <<generator->numberCutsActive()<<" were active after adding rounds of cuts";
2292                  if (generator->timing())
2293                    std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl;
2294                  else
2295                    std::cout<<std::endl;
2296                }
2297              }
2298              time2 = CoinCpuTime();
2299              totalTime += time2-time1;
2300              // For best solution
2301              double * bestSolution = NULL;
2302              if (babModel->getMinimizationObjValue()<1.0e50&&type==BAB) {
2303                // post process
2304                if (preProcess) {
2305                  int n = saveSolver->getNumCols();
2306                  bestSolution = new double [n];
2307                  process.postProcess(*babModel->solver());
2308                  // Solution now back in saveSolver
2309                  babModel->assignSolver(saveSolver);
2310                  memcpy(bestSolution,babModel->solver()->getColSolution(),n*sizeof(double));
2311                } else {
2312                  int n = babModel->solver()->getNumCols();
2313                  bestSolution = new double [n];
2314                  memcpy(bestSolution,babModel->solver()->getColSolution(),n*sizeof(double));
2315                }
2316              }
2317              if (type==STRENGTHEN&&strengthenedModel)
2318                clpSolver = dynamic_cast< OsiClpSolverInterface*> (strengthenedModel);
2319              lpSolver = clpSolver->getModelPtr();
2320              if (numberChanged) {
2321                for (int i=0;i<numberChanged;i++) {
2322                  int iColumn=changed[i];
2323                  clpSolver->setContinuous(iColumn);
2324                }
2325                delete [] changed;
2326              }
2327              if (type==BAB) {
2328                //move best solution (should be there -- but ..)
2329                int n = lpSolver->getNumCols();
2330                if (bestSolution)
2331                  memcpy(lpSolver->primalColumnSolution(),bestSolution,n*sizeof(double));
2332                if (debugFile=="create"&&bestSolution) {
2333                  saveSolution(lpSolver,"debug.file");
2334                }
2335                delete [] bestSolution;
2336                std::string statusName[]={"Finished","Stopped on ","Difficulties",
2337                                          "","","User ctrl-c"};
2338                std::string minor[]={"","","gap","nodes","time","","solutions","user ctrl-c"};
2339                int iStat = babModel->status();
2340                int iStat2 = babModel->secondaryStatus();
2341                if (!noPrinting)
2342                  std::cout<<"Result - "<<statusName[iStat]<<minor[iStat2]
2343                           <<" objective "<<babModel->getObjValue()<<
2344                    " after "<<babModel->getNodeCount()<<" nodes and "
2345                           <<babModel->getIterationCount()<<
2346                    " iterations - took "<<time2-time1<<" seconds"<<std::endl;
2347#ifdef COIN_HAS_ASL
2348                if (usingAmpl) {
2349                  double value = babModel->getObjValue()*lpSolver->getObjSense();
2350                  char buf[300];
2351                  int pos=0;
2352                  if (iStat==0) {
2353                    if (babModel->getObjValue()<1.0e40) {
2354                      pos += sprintf(buf+pos,"optimal," );
2355                    } else {
2356                      // infeasible
2357                      iStat=1;
2358                      pos += sprintf(buf+pos,"infeasible,");
2359                    }
2360                  } else if (iStat==1) {
2361                    if (iStat2!=6)
2362                      iStat=3;
2363                    else
2364                      iStat=4;
2365                    pos += sprintf(buf+pos,"stopped on %s,",minor[iStat2].c_str());
2366                  } else if (iStat==2) {
2367                    iStat = 7;
2368                    pos += sprintf(buf+pos,"stopped on difficulties,");
2369                  } else if (iStat==5) {
2370                    iStat = 3;
2371                    pos += sprintf(buf+pos,"stopped on ctrl-c,");
2372                  } else {
2373                    pos += sprintf(buf+pos,"status unknown,");
2374                    iStat=6;
2375                  }
2376                  info.problemStatus=iStat;
2377                  info.objValue = value;
2378                  if (babModel->getObjValue()<1.0e40) 
2379                    pos += sprintf(buf+pos," objective %.*g",ampl_obj_prec(),
2380                                   value);
2381                  sprintf(buf+pos,"\n%d nodes, %d iterations",
2382                          babModel->getNodeCount(),
2383                          babModel->getIterationCount());
2384                  if (bestSolution) {
2385                    free(info.primalSolution);
2386                    info.primalSolution = (double *) malloc(n*sizeof(double));
2387                    CoinCopyN(lpSolver->primalColumnSolution(),n,info.primalSolution);
2388                    int numberRows = lpSolver->numberRows();
2389                    free(info.dualSolution);
2390                    info.dualSolution = (double *) malloc(numberRows*sizeof(double));
2391                    CoinCopyN(lpSolver->dualRowSolution(),numberRows,info.dualSolution);
2392                  } else {
2393                    info.primalSolution=NULL;
2394                    info.dualSolution=NULL;
2395                  }
2396                  // put buffer into info
2397                  strcpy(info.buffer,buf);
2398                }
2399#endif
2400              } else {
2401                std::cout<<"Model strengthened - now has "<<clpSolver->getNumRows()
2402                         <<" rows"<<std::endl;
2403              }
2404              time1 = time2;
2405              delete babModel;
2406              babModel=NULL;
2407            } else {
2408              std::cout << "** Current model not valid" << std::endl ; 
2409            }
2410            break ;
2411          case IMPORT:
2412            {
2413#ifdef COIN_HAS_ASL
2414              if (!usingAmpl) {
2415#endif
2416                free(priorities);
2417                priorities=NULL;
2418                free(branchDirection);
2419                branchDirection=NULL;
2420                free(pseudoDown);
2421                pseudoDown=NULL;
2422                free(pseudoUp);
2423                pseudoUp=NULL;
2424                free(solutionIn);
2425                solutionIn=NULL;
2426                free(prioritiesIn);
2427                prioritiesIn=NULL;
2428                free(sosStart);
2429                sosStart=NULL;
2430                free(sosIndices);
2431                sosIndices=NULL;
2432                free(sosType);
2433                sosType=NULL;
2434                free(sosReference);
2435                sosReference=NULL;
2436                free(sosPriority);
2437                sosPriority=NULL;
2438#ifdef COIN_HAS_ASL
2439              }
2440#endif               
2441              delete babModel;
2442              babModel=NULL;
2443              // get next field
2444              field = CoinReadGetString(argc,argv);
2445              if (field=="$") {
2446                field = parameters[iParam].stringValue();
2447              } else if (field=="EOL") {
2448                parameters[iParam].printString();
2449                break;
2450              } else {
2451                parameters[iParam].setStringValue(field);
2452              }
2453              std::string fileName;
2454              bool canOpen=false;
2455              if (field=="-") {
2456                // stdin
2457                canOpen=true;
2458                fileName = "-";
2459              } else {
2460                bool absolutePath;
2461                if (dirsep=='/') {
2462                  // non Windows (or cygwin)
2463                  absolutePath=(field[0]=='/');
2464                } else {
2465                  //Windows (non cycgwin)
2466                  absolutePath=(field[0]=='\\');
2467                  // but allow for :
2468                  if (strchr(field.c_str(),':'))
2469                    absolutePath=true;
2470                }
2471                if (absolutePath) {
2472                  fileName = field;
2473                } else if (field[0]=='~') {
2474                  char * environVar = getenv("HOME");
2475                  if (environVar) {
2476                    std::string home(environVar);
2477                    field=field.erase(0,1);
2478                    fileName = home+field;
2479                  } else {
2480                    fileName=field;
2481                  }
2482                } else {
2483                  fileName = directory+field;
2484                }
2485                FILE *fp=fopen(fileName.c_str(),"r");
2486                if (fp) {
2487                  // can open - lets go for it
2488                  fclose(fp);
2489                  canOpen=true;
2490                } else {
2491                  std::cout<<"Unable to open file "<<fileName<<std::endl;
2492                }
2493              }
2494              if (canOpen) {
2495                int status =lpSolver->readMps(fileName.c_str(),
2496                                                   keepImportNames!=0,
2497                                                   allowImportErrors!=0);
2498                if (!status||(status>0&&allowImportErrors)) {
2499                  if (keepImportNames) {
2500                    lengthName = lpSolver->lengthNames();
2501                    rowNames = *(lpSolver->rowNames());
2502                    columnNames = *(lpSolver->columnNames());
2503                  } else {
2504                    lengthName=0;
2505                  }
2506                  goodModel=true;
2507                  //Set integers in clpsolver
2508                  const char * info = lpSolver->integerInformation();
2509                  if (info) {
2510                    int numberColumns = lpSolver->numberColumns();
2511                    int i;
2512                    for (i=0;i<numberColumns;i++) {
2513                      if (info[i]) 
2514                        clpSolver->setInteger(i);
2515                    }
2516                  }
2517                  // sets to all slack (not necessary?)
2518                  lpSolver->createStatus();
2519                  time2 = CoinCpuTime();
2520                  totalTime += time2-time1;
2521                  time1=time2;
2522                  // Go to canned file if just input file
2523                  if (CbcOrClpRead_mode==2&&argc==2) {
2524                    // only if ends .mps
2525                    std::string::size_type loc = fileName.find(".mps") ;
2526                    if (loc != std::string::npos &&
2527                        fileName.length() == loc+3)
2528                    { fileName.replace(loc+1,3,"par") ;
2529                      FILE *fp=fopen(fileName.c_str(),"r");
2530                      if (fp) {
2531                        CbcOrClpReadCommand=fp; // Read from that file
2532                        CbcOrClpRead_mode=-1;
2533                      }
2534                    }
2535                  }
2536                } else {
2537                  // errors
2538                  std::cout<<"There were "<<status<<
2539                    " errors on input"<<std::endl;
2540                }
2541              }
2542            }
2543            break;
2544          case EXPORT:
2545            if (goodModel) {
2546              // get next field
2547              field = CoinReadGetString(argc,argv);
2548              if (field=="$") {
2549                field = parameters[iParam].stringValue();
2550              } else if (field=="EOL") {
2551                parameters[iParam].printString();
2552                break;
2553              } else {
2554                parameters[iParam].setStringValue(field);
2555              }
2556              std::string fileName;
2557              bool canOpen=false;
2558              if (field[0]=='/'||field[0]=='\\') {
2559                fileName = field;
2560              } else if (field[0]=='~') {
2561                char * environVar = getenv("HOME");
2562                if (environVar) {
2563                  std::string home(environVar);
2564                  field=field.erase(0,1);
2565                  fileName = home+field;
2566                } else {
2567                  fileName=field;
2568                }
2569              } else {
2570                fileName = directory+field;
2571              }
2572              FILE *fp=fopen(fileName.c_str(),"w");
2573              if (fp) {
2574                // can open - lets go for it
2575                fclose(fp);
2576                canOpen=true;
2577              } else {
2578                std::cout<<"Unable to open file "<<fileName<<std::endl;
2579              }
2580              if (canOpen) {
2581                // If presolve on then save presolved
2582                bool deleteModel2=false;
2583                ClpSimplex * model2 = lpSolver;
2584                if (preSolve) {
2585                  ClpPresolve pinfo;
2586                  int presolveOptions2 = presolveOptions&~0x40000000;
2587                  if ((presolveOptions2&0xffff)!=0)
2588                    pinfo.setPresolveActions(presolveOptions2);
2589                  if ((printOptions&1)!=0)
2590                    pinfo.statistics();
2591                  double presolveTolerance = 
2592                    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
2593                  model2 = 
2594                    pinfo.presolvedModel(*lpSolver,presolveTolerance,
2595                                         true,preSolve);
2596                  if (model2) {
2597                    printf("Saving presolved model on %s\n",
2598                           fileName.c_str());
2599                    deleteModel2=true;
2600                  } else {
2601                    printf("Presolved model looks infeasible - saving original on %s\n",
2602                           fileName.c_str());
2603                    deleteModel2=false;
2604                    model2 = lpSolver;
2605
2606                  }
2607                } else {
2608                  printf("Saving model on %s\n",
2609                           fileName.c_str());
2610                }
2611#if 0
2612                // Convert names
2613                int iRow;
2614                int numberRows=model2->numberRows();
2615                int iColumn;
2616                int numberColumns=model2->numberColumns();
2617
2618                char ** rowNames = NULL;
2619                char ** columnNames = NULL;
2620                if (model2->lengthNames()) {
2621                  rowNames = new char * [numberRows];
2622                  for (iRow=0;iRow<numberRows;iRow++) {
2623                    rowNames[iRow] =
2624                      strdup(model2->rowName(iRow).c_str());
2625#ifdef STRIPBLANKS
2626                    char * xx = rowNames[iRow];
2627                    int i;
2628                    int length = strlen(xx);
2629                    int n=0;
2630                    for (i=0;i<length;i++) {
2631                      if (xx[i]!=' ')
2632                        xx[n++]=xx[i];
2633                    }
2634                    xx[n]='\0';
2635#endif
2636                  }
2637                 
2638                  columnNames = new char * [numberColumns];
2639                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
2640                    columnNames[iColumn] =
2641                      strdup(model2->columnName(iColumn).c_str());
2642#ifdef STRIPBLANKS
2643                    char * xx = columnNames[iColumn];
2644                    int i;
2645                    int length = strlen(xx);
2646                    int n=0;
2647                    for (i=0;i<length;i++) {
2648                      if (xx[i]!=' ')
2649                        xx[n++]=xx[i];
2650                    }
2651                    xx[n]='\0';
2652#endif
2653                  }
2654                }
2655                CoinMpsIO writer;
2656                writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
2657                                  model2->getColLower(), model2->getColUpper(),
2658                                  model2->getObjCoefficients(),
2659                                  (const char*) 0 /*integrality*/,
2660                                  model2->getRowLower(), model2->getRowUpper(),
2661                                  columnNames, rowNames);
2662                // Pass in array saying if each variable integer
2663                writer.copyInIntegerInformation(model2->integerInformation());
2664                writer.setObjectiveOffset(model2->objectiveOffset());
2665                writer.writeMps(fileName.c_str(),0,1,1);
2666                if (rowNames) {
2667                  for (iRow=0;iRow<numberRows;iRow++) {
2668                    free(rowNames[iRow]);
2669                  }
2670                  delete [] rowNames;
2671                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
2672                    free(columnNames[iColumn]);
2673                  }
2674                  delete [] columnNames;
2675                }
2676#else
2677                model2->writeMps(fileName.c_str(),(outputFormat-1)/2,1+((outputFormat-1)&1));
2678#endif
2679                if (deleteModel2)
2680                  delete model2;
2681                time2 = CoinCpuTime();
2682                totalTime += time2-time1;
2683                time1=time2;
2684              }
2685            } else {
2686              std::cout<<"** Current model not valid"<<std::endl;
2687            }
2688            break;
2689          case BASISIN:
2690            if (goodModel) {
2691              // get next field
2692              field = CoinReadGetString(argc,argv);
2693              if (field=="$") {
2694                field = parameters[iParam].stringValue();
2695              } else if (field=="EOL") {
2696                parameters[iParam].printString();
2697                break;
2698              } else {
2699                parameters[iParam].setStringValue(field);
2700              }
2701              std::string fileName;
2702              bool canOpen=false;
2703              if (field=="-") {
2704                // stdin
2705                canOpen=true;
2706                fileName = "-";
2707              } else {
2708                if (field[0]=='/'||field[0]=='\\') {
2709                  fileName = field;
2710                } else if (field[0]=='~') {
2711                  char * environVar = getenv("HOME");
2712                  if (environVar) {
2713                    std::string home(environVar);
2714                    field=field.erase(0,1);
2715                    fileName = home+field;
2716                  } else {
2717                    fileName=field;
2718                  }
2719                } else {
2720                  fileName = directory+field;
2721                }
2722                FILE *fp=fopen(fileName.c_str(),"r");
2723                if (fp) {
2724                  // can open - lets go for it
2725                  fclose(fp);
2726                  canOpen=true;
2727                } else {
2728                  std::cout<<"Unable to open file "<<fileName<<std::endl;
2729                }
2730              }
2731              if (canOpen) {
2732                int values = lpSolver->readBasis(fileName.c_str());
2733                if (values==0)
2734                  basisHasValues=-1;
2735                else
2736                  basisHasValues=1;
2737              }
2738            } else {
2739              std::cout<<"** Current model not valid"<<std::endl;
2740            }
2741            break;
2742          case PRIORITYIN:
2743            if (goodModel) {
2744              // get next field
2745              field = CoinReadGetString(argc,argv);
2746              if (field=="$") {
2747                field = parameters[iParam].stringValue();
2748              } else if (field=="EOL") {
2749                parameters[iParam].printString();
2750                break;
2751              } else {
2752                parameters[iParam].setStringValue(field);
2753              }
2754              std::string fileName;
2755              if (field[0]=='/'||field[0]=='\\') {
2756                fileName = field;
2757              } else if (field[0]=='~') {
2758                char * environVar = getenv("HOME");
2759                if (environVar) {
2760                  std::string home(environVar);
2761                  field=field.erase(0,1);
2762                  fileName = home+field;
2763                } else {
2764                  fileName=field;
2765                }
2766              } else {
2767                fileName = directory+field;
2768              }
2769              FILE *fp=fopen(fileName.c_str(),"r");
2770              if (fp) {
2771                // can open - lets go for it
2772                std::string headings[]={"name","number","direction","priority","up","down",
2773                                        "solution","priin"};
2774                int got[]={-1,-1,-1,-1,-1,-1,-1,-1};
2775                int order[8];
2776                assert(sizeof(got)==sizeof(order));
2777                int nAcross=0;
2778                char line[1000];
2779                int numberColumns = lpSolver->numberColumns();
2780                if (!fgets(line,1000,fp)) {
2781                  std::cout<<"Odd file "<<fileName<<std::endl;
2782                } else {
2783                  char * pos = line;
2784                  char * put = line;
2785                  while (*pos>=' '&&*pos!='\n') {
2786                    if (*pos!=' '&&*pos!='\t') {
2787                      *put=tolower(*pos);
2788                      put++;
2789                    }
2790                    pos++;
2791                  }
2792                  *put='\0';
2793                  pos=line;
2794                  int i;
2795                  bool good=true;
2796                  while (pos) {
2797                    char * comma = strchr(pos,',');
2798                    if (comma)
2799                      *comma='\0';
2800                    for (i=0;i<(int) (sizeof(got)/sizeof(int));i++) {
2801                      if (headings[i]==pos) {
2802                        if (got[i]<0) {
2803                          order[nAcross]=i;
2804                          got[i]=nAcross++;
2805                        } else {
2806                          // duplicate
2807                          good=false;
2808                        }
2809                        break;
2810                      }
2811                    }
2812                    if (i==(int) (sizeof(got)/sizeof(int)))
2813                      good=false;
2814                    if (comma) {
2815                      *comma=',';
2816                      pos=comma+1;
2817                    } else {
2818                      break;
2819                    }
2820                  }
2821                  if (got[0]<0&&got[1]<0)
2822                    good=false;
2823                  if (got[0]>=0&&got[1]>=0)
2824                    good=false;
2825                  if (got[0]>=0&&!lpSolver->lengthNames())
2826                    good=false;
2827                  if (good) {
2828                    char ** columnNames = columnNames = new char * [numberColumns];
2829                    pseudoDown= (double *) malloc(numberColumns*sizeof(double));
2830                    pseudoUp = (double *) malloc(numberColumns*sizeof(double));
2831                    branchDirection = (int *) malloc(numberColumns*sizeof(int));
2832                    priorities= (int *) malloc(numberColumns*sizeof(int));
2833                    free(solutionIn);
2834                    solutionIn=NULL;
2835                    free(prioritiesIn);
2836                    prioritiesIn=NULL;
2837                    int iColumn;
2838                    if (got[6]>=0) {
2839                      solutionIn = (double *) malloc(numberColumns*sizeof(double));
2840                      CoinZeroN(solutionIn,numberColumns);
2841                    }
2842                    if (got[7]>=0) {
2843                      prioritiesIn = (int *) malloc(numberColumns*sizeof(int));
2844                      for (iColumn=0;iColumn<numberColumns;iColumn++) 
2845                        prioritiesIn[iColumn]=10000;
2846                    }
2847                    for (iColumn=0;iColumn<numberColumns;iColumn++) {
2848                      columnNames[iColumn] = 
2849                        strdup(lpSolver->columnName(iColumn).c_str());
2850                      pseudoDown[iColumn]=0.0;
2851                      pseudoUp[iColumn]=0.0;
2852                      branchDirection[iColumn]=0;
2853                      priorities[iColumn]=0;
2854                    }
2855                    int nBadPseudo=0;
2856                    int nBadDir=0;
2857                    int nBadPri=0;
2858                    int nBadName=0;
2859                    int nBadLine=0;
2860                    int nLine=0;
2861                    while (fgets(line,1000,fp)) {
2862                      nLine++;
2863                      iColumn = -1;
2864                      double up =0.0;
2865                      double down=0.0;
2866                      int pri=0;
2867                      int dir=0;
2868                      double solValue=COIN_DBL_MAX;
2869                      int priValue=1000000;
2870                      char * pos = line;
2871                      char * put = line;
2872                      while (*pos>=' '&&*pos!='\n') {
2873                        if (*pos!=' '&&*pos!='\t') {
2874                          *put=tolower(*pos);
2875                          put++;
2876                        }
2877                        pos++;
2878                      }
2879                      *put='\0';
2880                      pos=line;
2881                      for (int i=0;i<nAcross;i++) {
2882                        char * comma = strchr(pos,',');
2883                        if (comma) {
2884                          *comma='\0';
2885                        } else if (i<nAcross-1) {
2886                          nBadLine++;
2887                          break;
2888                        }
2889                        switch (order[i]) {
2890                          // name
2891                        case 0:
2892                          for (iColumn=0;iColumn<numberColumns;iColumn++) {
2893                            if (!strcmp(columnNames[iColumn],pos))
2894                              break;
2895                          }
2896                          if (iColumn==numberColumns)
2897                            iColumn=-1;
2898                          break;
2899                          // number
2900                        case 1:
2901                          iColumn = atoi(pos);
2902                          if (iColumn<0||iColumn>=numberColumns)
2903                            iColumn=-1;
2904                          break;
2905                          // direction
2906                        case 2:
2907                          if (*pos=='D')
2908                            dir=-1;
2909                          else if (*pos=='U')
2910                            dir=1;
2911                          else if (*pos=='N')
2912                            dir=0;
2913                          else if (*pos=='1'&&*(pos+1)=='\0')
2914                            dir=1;
2915                          else if (*pos=='0'&&*(pos+1)=='\0')
2916                            dir=0;
2917                          else if (*pos=='1'&&*(pos+1)=='1'&&*(pos+2)=='\0')
2918                            dir=-1;
2919                          else
2920                            dir=-2; // bad
2921                          break;
2922                          // priority
2923                        case 3:
2924                          pri=atoi(pos);
2925                          break;
2926                          // up
2927                        case 4:
2928                          up = atof(pos);
2929                          break;
2930                          // down
2931                        case 5:
2932                          down = atof(pos);
2933                          break;
2934                          // sol value
2935                        case 6:
2936                          solValue = atof(pos);
2937                          break;
2938                          // priority in value
2939                        case 7:
2940                          priValue = atoi(pos);
2941                          break;
2942                        }
2943                        if (comma) {
2944                          *comma=',';
2945                          pos=comma+1;
2946                        }
2947                      }
2948                      if (iColumn>=0) {
2949                        if (down<0.0) {
2950                          nBadPseudo++;
2951                          down=0.0;
2952                        }
2953                        if (up<0.0) {
2954                          nBadPseudo++;
2955                          up=0.0;
2956                        }
2957                        if (!up)
2958                          up=down;
2959                        if (!down)
2960                          down=up;
2961                        if (dir<-1||dir>1) {
2962                          nBadDir++;
2963                          dir=0;
2964                        }
2965                        if (pri<0) {
2966                          nBadPri++;
2967                          pri=0;
2968                        }
2969                        pseudoDown[iColumn]=down;
2970                        pseudoUp[iColumn]=up;
2971                        branchDirection[iColumn]=dir;
2972                        priorities[iColumn]=pri;
2973                        if (solValue!=COIN_DBL_MAX) {
2974                          assert (solutionIn);
2975                          solutionIn[iColumn]=solValue;
2976                        }
2977                        if (priValue!=1000000) {
2978                          assert (prioritiesIn);
2979                          prioritiesIn[iColumn]=priValue;
2980                        }
2981                      } else {
2982                        nBadName++;
2983                      }
2984                    }
2985                    if (!noPrinting) {
2986                      printf("%d fields and %d records",nAcross,nLine);
2987                      if (nBadPseudo)
2988                        printf(" %d bad pseudo costs",nBadPseudo);
2989                      if (nBadDir)
2990                        printf(" %d bad directions",nBadDir);
2991                      if (nBadPri)
2992                        printf(" %d bad priorities",nBadPri);
2993                      if (nBadName)
2994                        printf(" ** %d records did not match on name/sequence",nBadName);
2995                      printf("\n");
2996                    }
2997                    for (iColumn=0;iColumn<numberColumns;iColumn++) {
2998                      free(columnNames[iColumn]);
2999                    }
3000                    delete [] columnNames;
3001                  } else {
3002                    std::cout<<"Duplicate or unknown keyword - or name/number fields wrong"<<line<<std::endl;
3003                  }
3004                }
3005                fclose(fp);
3006              } else {
3007                std::cout<<"Unable to open file "<<fileName<<std::endl;
3008              }
3009            } else {
3010              std::cout<<"** Current model not valid"<<std::endl;
3011            }
3012            break;
3013          case DEBUG:
3014            if (goodModel) {
3015              delete [] debugValues;
3016              debugValues=NULL;
3017              // get next field
3018              field = CoinReadGetString(argc,argv);
3019              if (field=="$") {
3020                field = parameters[iParam].stringValue();
3021              } else if (field=="EOL") {
3022                parameters[iParam].printString();
3023                break;
3024              } else {
3025                parameters[iParam].setStringValue(field);
3026                debugFile=field;
3027                if (debugFile=="create"||
3028                    debugFile=="createAfterPre") {
3029                  printf("Will create a debug file so this run should be a good one\n");
3030                  break;
3031                }
3032              }
3033              std::string fileName;
3034              if (field[0]=='/'||field[0]=='\\') {
3035                fileName = field;
3036              } else if (field[0]=='~') {
3037                char * environVar = getenv("HOME");
3038                if (environVar) {
3039                  std::string home(environVar);
3040                  field=field.erase(0,1);
3041                  fileName = home+field;
3042                } else {
3043                  fileName=field;
3044                }
3045              } else {
3046                fileName = directory+field;
3047              }
3048              FILE *fp=fopen(fileName.c_str(),"rb");
3049              if (fp) {
3050                // can open - lets go for it
3051                int numRows;
3052                double obj;
3053                fread(&numRows,sizeof(int),1,fp);
3054                fread(&numberDebugValues,sizeof(int),1,fp);
3055                fread(&obj,sizeof(double),1,fp);
3056                debugValues = new double[numberDebugValues+numRows];
3057                fread(debugValues,sizeof(double),numRows,fp);
3058                fread(debugValues,sizeof(double),numRows,fp);
3059                fread(debugValues,sizeof(double),numberDebugValues,fp);
3060                printf("%d doubles read into debugValues\n",numberDebugValues);
3061                fclose(fp);
3062              } else {
3063                std::cout<<"Unable to open file "<<fileName<<std::endl;
3064              }
3065            } else {
3066              std::cout<<"** Current model not valid"<<std::endl;
3067            }
3068            break;
3069          case PRINTMASK:
3070            // get next field
3071            {
3072              std::string name = CoinReadGetString(argc,argv);
3073              if (name!="EOL") {
3074                parameters[iParam].setStringValue(name);
3075                printMask = name;
3076              } else {
3077                parameters[iParam].printString();
3078              }
3079            }
3080            break;
3081          case BASISOUT:
3082            if (goodModel) {
3083              // get next field
3084              field = CoinReadGetString(argc,argv);
3085              if (field=="$") {
3086                field = parameters[iParam].stringValue();
3087              } else if (field=="EOL") {
3088                parameters[iParam].printString();
3089                break;
3090              } else {
3091                parameters[iParam].setStringValue(field);
3092              }
3093              std::string fileName;
3094              bool canOpen=false;
3095              if (field[0]=='/'||field[0]=='\\') {
3096                fileName = field;
3097              } else if (field[0]=='~') {
3098                char * environVar = getenv("HOME");
3099                if (environVar) {
3100                  std::string home(environVar);
3101                  field=field.erase(0,1);
3102                  fileName = home+field;
3103                } else {
3104                  fileName=field;
3105                }
3106              } else {
3107                fileName = directory+field;
3108              }
3109              FILE *fp=fopen(fileName.c_str(),"w");
3110              if (fp) {
3111                // can open - lets go for it
3112                fclose(fp);
3113                canOpen=true;
3114              } else {
3115                std::cout<<"Unable to open file "<<fileName<<std::endl;
3116              }
3117              if (canOpen) {
3118                ClpSimplex * model2 = lpSolver;
3119                model2->writeBasis(fileName.c_str(),outputFormat>1,outputFormat-2);
3120                time2 = CoinCpuTime();
3121                totalTime += time2-time1;
3122                time1=time2;
3123              }
3124            } else {
3125              std::cout<<"** Current model not valid"<<std::endl;
3126            }
3127            break;
3128          case SAVE:
3129            {
3130              // get next field
3131              field = CoinReadGetString(argc,argv);
3132              if (field=="$") {
3133                field = parameters[iParam].stringValue();
3134              } else if (field=="EOL") {
3135                parameters[iParam].printString();
3136                break;
3137              } else {
3138                parameters[iParam].setStringValue(field);
3139              }
3140              std::string fileName;
3141              bool canOpen=false;
3142              if (field[0]=='/'||field[0]=='\\') {
3143                fileName = field;
3144              } else if (field[0]=='~') {
3145                char * environVar = getenv("HOME");
3146                if (environVar) {
3147                  std::string home(environVar);
3148                  field=field.erase(0,1);
3149                  fileName = home+field;
3150                } else {
3151                  fileName=field;
3152                }
3153              } else {
3154                fileName = directory+field;
3155              }
3156              FILE *fp=fopen(fileName.c_str(),"wb");
3157              if (fp) {
3158                // can open - lets go for it
3159                fclose(fp);
3160                canOpen=true;
3161              } else {
3162                std::cout<<"Unable to open file "<<fileName<<std::endl;
3163              }
3164              if (canOpen) {
3165                int status;
3166                // If presolve on then save presolved
3167                bool deleteModel2=false;
3168                ClpSimplex * model2 = lpSolver;
3169                if (preSolve) {
3170                  ClpPresolve pinfo;
3171                  double presolveTolerance = 
3172                    parameters[whichParam(PRESOLVETOLERANCE,numberParameters,parameters)].doubleValue();
3173                  model2 = 
3174                    pinfo.presolvedModel(*lpSolver,presolveTolerance,
3175                                         false,preSolve);
3176                  if (model2) {
3177                    printf("Saving presolved model on %s\n",
3178                           fileName.c_str());
3179                    deleteModel2=true;
3180                  } else {
3181                    printf("Presolved model looks infeasible - saving original on %s\n",
3182                           fileName.c_str());
3183                    deleteModel2=false;
3184                    model2 = lpSolver;
3185
3186                  }
3187                } else {
3188                  printf("Saving model on %s\n",
3189                           fileName.c_str());
3190                }
3191                status =model2->saveModel(fileName.c_str());
3192                if (deleteModel2)
3193                  delete model2;
3194                if (!status) {
3195                  goodModel=true;
3196                  time2 = CoinCpuTime();
3197                  totalTime += time2-time1;
3198                  time1=time2;
3199                } else {
3200                  // errors
3201                  std::cout<<"There were errors on output"<<std::endl;
3202                }
3203              }
3204            }
3205            break;
3206          case RESTORE:
3207            {
3208              // get next field
3209              field = CoinReadGetString(argc,argv);
3210              if (field=="$") {
3211                field = parameters[iParam].stringValue();
3212              } else if (field=="EOL") {
3213                parameters[iParam].printString();
3214                break;
3215              } else {
3216                parameters[iParam].setStringValue(field);
3217              }
3218              std::string fileName;
3219              bool canOpen=false;
3220              if (field[0]=='/'||field[0]=='\\') {
3221                fileName = field;
3222              } else if (field[0]=='~') {
3223                char * environVar = getenv("HOME");
3224                if (environVar) {
3225                  std::string home(environVar);
3226                  field=field.erase(0,1);
3227                  fileName = home+field;
3228                } else {
3229                  fileName=field;
3230                }
3231              } else {
3232                fileName = directory+field;
3233              }
3234              FILE *fp=fopen(fileName.c_str(),"rb");
3235              if (fp) {
3236                // can open - lets go for it
3237                fclose(fp);
3238                canOpen=true;
3239              } else {
3240                std::cout<<"Unable to open file "<<fileName<<std::endl;
3241              }
3242              if (canOpen) {
3243                int status =lpSolver->restoreModel(fileName.c_str());
3244                if (!status) {
3245                  goodModel=true;
3246                  time2 = CoinCpuTime();
3247                  totalTime += time2-time1;
3248                  time1=time2;
3249                } else {
3250                  // errors
3251                  std::cout<<"There were errors on input"<<std::endl;
3252                }
3253              }
3254            }
3255            break;
3256          case MAXIMIZE:
3257            lpSolver->setOptimizationDirection(-1);
3258            break;
3259          case MINIMIZE:
3260            lpSolver->setOptimizationDirection(1);
3261            break;
3262          case ALLSLACK:
3263            lpSolver->allSlackBasis(true);
3264            break;
3265          case REVERSE:
3266            if (goodModel) {
3267              int iColumn;
3268              int numberColumns=lpSolver->numberColumns();
3269              double * dualColumnSolution = 
3270                lpSolver->dualColumnSolution();
3271              ClpObjective * obj = lpSolver->objectiveAsObject();
3272              assert(dynamic_cast<ClpLinearObjective *> (obj));
3273              double offset;
3274              double * objective = obj->gradient(NULL,NULL,offset,true);
3275              for (iColumn=0;iColumn<numberColumns;iColumn++) {
3276                dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
3277                objective[iColumn] = -objective[iColumn];
3278              }
3279              int iRow;
3280              int numberRows=lpSolver->numberRows();
3281              double * dualRowSolution = 
3282                lpSolver->dualRowSolution();
3283              for (iRow=0;iRow<numberRows;iRow++) 
3284                dualRowSolution[iRow] = dualRowSolution[iRow];
3285            }
3286            break;
3287          case DIRECTORY:
3288            {
3289              std::string name = CoinReadGetString(argc,argv);
3290              if (name!="EOL") {
3291                int length=name.length();
3292                if (name[length-1]=='/'||name[length-1]=='\\')
3293                  directory=name;
3294                else
3295                  directory = name+"/";
3296                parameters[iParam].setStringValue(directory);
3297              } else {
3298                parameters[iParam].printString();
3299              }
3300            }
3301            break;
3302          case STDIN:
3303            CbcOrClpRead_mode=-1;
3304            break;
3305          case NETLIB_DUAL:
3306          case NETLIB_EITHER:
3307          case NETLIB_BARRIER:
3308          case NETLIB_PRIMAL:
3309          case NETLIB_TUNE:
3310            {
3311              // create fields for unitTest
3312              const char * fields[4];
3313              int nFields=2;
3314              fields[0]="fake main from unitTest";
3315              fields[1]="-netlib";
3316              if (directory!=defaultDirectory) {
3317                fields[2]="-netlibDir";
3318                fields[3]=directory.c_str();
3319                nFields=4;
3320              }
3321              int algorithm;
3322              if (type==NETLIB_DUAL) {
3323                std::cerr<<"Doing netlib with dual algorithm"<<std::endl;
3324                algorithm =0;
3325              } else if (type==NETLIB_BARRIER) {
3326                std::cerr<<"Doing netlib with barrier algorithm"<<std::endl;
3327                algorithm =2;
3328              } else if (type==NETLIB_EITHER) {
3329                std::cerr<<"Doing netlib with dual or primal algorithm"<<std::endl;
3330                algorithm =3;
3331              } else if (type==NETLIB_TUNE) {
3332                std::cerr<<"Doing netlib with best algorithm!"<<std::endl;
3333                algorithm =5;
3334                // uncomment next to get active tuning
3335                // algorithm=6;
3336              } else {
3337                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
3338                algorithm=1;
3339              }
3340              int specialOptions = lpSolver->specialOptions();
3341              lpSolver->setSpecialOptions(0);
3342              mainTest(nFields,fields,algorithm,*lpSolver,
3343                       (preSolve!=0),specialOptions);
3344            }
3345            break;
3346          case UNITTEST:
3347            {
3348              // create fields for unitTest
3349              const char * fields[3];
3350              int nFields=1;
3351              fields[0]="fake main from unitTest";
3352              if (directory!=defaultDirectory) {
3353                fields[1]="-mpsDir";
3354                fields[2]=directory.c_str();
3355                nFields=3;
3356              }
3357              mainTest(nFields,fields,false,*lpSolver,(preSolve!=0),
3358                       false);
3359            }
3360            break;
3361          case FAKEBOUND:
3362            if (goodModel) {
3363              // get bound
3364              double value = CoinReadGetDoubleField(argc,argv,&valid);
3365              if (!valid) {
3366                std::cout<<"Setting "<<parameters[iParam].name()<<
3367                  " to DEBUG "<<value<<std::endl;
3368                int iRow;
3369                int numberRows=lpSolver->numberRows();
3370                double * rowLower = lpSolver->rowLower();
3371                double * rowUpper = lpSolver->rowUpper();
3372                for (iRow=0;iRow<numberRows;iRow++) {
3373                  // leave free ones for now
3374                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
3375                    rowLower[iRow]=CoinMax(rowLower[iRow],-value);
3376                    rowUpper[iRow]=CoinMin(rowUpper[iRow],value);
3377                  }
3378                }
3379                int iColumn;
3380                int numberColumns=lpSolver->numberColumns();
3381                double * columnLower = lpSolver->columnLower();
3382                double * columnUpper = lpSolver->columnUpper();
3383                for (iColumn=0;iColumn<numberColumns;iColumn++) {
3384                  // leave free ones for now
3385                  if (columnLower[iColumn]>-1.0e20||
3386                      columnUpper[iColumn]<1.0e20) {
3387                    columnLower[iColumn]=CoinMax(columnLower[iColumn],-value);
3388                    columnUpper[iColumn]=CoinMin(columnUpper[iColumn],value);
3389                  }
3390                }
3391              } else if (valid==1) {
3392                abort();
3393              } else {
3394                std::cout<<"enter value for "<<parameters[iParam].name()<<
3395                  std::endl;
3396              }
3397            }
3398            break;
3399          case REALLY_SCALE:
3400            if (goodModel) {
3401              ClpSimplex newModel(*lpSolver,
3402                                  lpSolver->scalingFlag());
3403              printf("model really really scaled\n");
3404              *lpSolver=newModel;
3405            }
3406            break;
3407          case USERCLP:
3408            // Replace the sample code by whatever you want
3409            if (goodModel) {
3410              printf("Dummy user clp code - model has %d rows and %d columns\n",
3411                     lpSolver->numberRows(),lpSolver->numberColumns());
3412            }
3413            break;
3414          case USERCBC:
3415            // Replace the sample code by whatever you want
3416            if (goodModel) {
3417              printf("Dummy user cbc code - model has %d rows and %d columns\n",
3418                     model.getNumRows(),model.getNumCols());
3419  // Reduce printout
3420  //solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry);
3421  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (model.solver());
3422  // go faster stripes
3423  if (osiclp&&0) {
3424    // Turn this off if you get problems
3425    // Used to be automatically set
3426    osiclp->setSpecialOptions(128);
3427    if(osiclp->getNumRows()<300&&osiclp->getNumCols()<500) {
3428      //osiclp->setupForRepeatedUse(2,0);
3429      osiclp->setupForRepeatedUse(0,0);
3430    }
3431  } 
3432  // Allow rounding heuristic
3433
3434  CbcRounding heuristic1(model);
3435  model.addHeuristic(&heuristic1);
3436
3437  // Do initial solve to continuous
3438  ClpPrimalColumnSteepest steepest(5);
3439  osiclp->getModelPtr()->setPrimalColumnPivotAlgorithm(steepest);
3440  osiclp->getModelPtr()->setPerturbation(50);
3441  osiclp->getModelPtr()->setInfeasibilityCost(1.0e9);
3442  osiclp->setHintParam(OsiDoPresolveInInitial,false,OsiHintTry);
3443  osiclp->setHintParam(OsiDoDualInInitial,false,OsiHintTry);
3444  //osiclp->setHintParam(OsiDoDualInResolve,false,OsiHintTry);
3445  model.setSpecialOptions(model.specialOptions()|4);
3446  osiclp->getModelPtr()->defaultFactorizationFrequency();
3447  {
3448    ClpSimplex * clp = osiclp->getModelPtr();
3449    // fix integers to 1
3450    int numberColumns = clp->numberColumns();
3451    double * lower = clp->columnLower();
3452    int i;
3453    for (i=0;i<numberColumns;i++) {
3454      if (osiclp->isInteger(i))
3455        lower[i]=1.0;
3456    }
3457    clp->primal();
3458    double objValue = clp->objectiveValue();
3459    osiclp->setDblParam(OsiDualObjectiveLimit,objValue+1.0e-4);
3460    // unfix integers
3461    for (i=0;i<numberColumns;i++) {
3462      if (osiclp->isInteger(i))
3463        lower[i]=0.0;
3464    }
3465    clp->primal();
3466    //clp->dual();
3467    int nArt=0;
3468    int nFixed0=0,nFixed1=0;
3469    double gap=objValue-clp->objectiveValue();
3470    // for those at one fix anyway
3471    double gap2=1.0;
3472    const double * solution = clp->primalColumnSolution();
3473    const double * dj = clp->dualColumnSolution();
3474    const double * objective = clp->objective();
3475    double * upper = clp->columnUpper();
3476    for (i=0;i<numberColumns;i++) {
3477      if (objective[i]>1.0e5&&solution[i]>1.0e-8)
3478        nArt++;
3479      if (osiclp->isInteger(i)) {
3480        if(dj[i]>gap+1.0e-4) {
3481          nFixed0++;
3482          upper[i]=0.0;
3483        }
3484        if(-dj[i]>gap2+1.0e-4) {
3485          nFixed1++;
3486        lower[i]=1.0;
3487        }
3488      }
3489    }
3490    printf("%d artificials, %d fixed to 0, %d fixed to 1\n",nArt,nFixed0,nFixed1);
3491    //osiclp->getModelPtr()->setPerturbation(100);
3492    osiclp->setWarmStart(NULL); // set basis in osiclp
3493  }
3494  osiclp->initialSolve();
3495
3496  // Switch off strong branching if wanted
3497  // model.setNumberStrong(0);
3498  // Do more strong branching if small
3499  model.setNumberStrong(0);
3500  model.setNumberBeforeTrust(0);
3501
3502  // TEMP - set gap - better to see if no improvement in last few nodes
3503  model.setAllowableGap(600.0);
3504  // message levels
3505  model.messageHandler()->setLogLevel(2);
3506  model.solver()->messageHandler()->setLogLevel(2);
3507  // Do complete search
3508 
3509  model.branchAndBound();
3510            }
3511            break;
3512          case HELP:
3513            std::cout<<"Coin Solver version "<<CBCVERSION
3514                     <<", build "<<__DATE__<<std::endl;
3515            std::cout<<"Non default values:-"<<std::endl;
3516            std::cout<<"Perturbation "<<lpSolver->perturbation()<<" (default 100)"
3517                     <<std::endl;
3518            CoinReadPrintit(
3519                    "Presolve being done with 5 passes\n\
3520Dual steepest edge steep/partial on matrix shape and factorization density\n\
3521Clpnnnn taken out of messages\n\
3522If Factorization frequency default then done on size of matrix\n\n\
3523(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
3524You can switch to interactive mode at any time so\n\
3525clp watson.mps -scaling off -primalsimplex\nis the same as\n\
3526clp watson.mps -\nscaling off\nprimalsimplex"
3527                    );
3528            break;
3529          case SOLUTION:
3530            if (goodModel) {
3531              // get next field
3532              field = CoinReadGetString(argc,argv);
3533              if (field=="$") {
3534                field = parameters[iParam].stringValue();
3535              } else if (field=="EOL") {
3536                parameters[iParam].printString();
3537                break;
3538              } else {
3539                parameters[iParam].setStringValue(field);
3540              }
3541              std::string fileName;
3542              FILE *fp=NULL;
3543              if (field=="-"||field=="EOL"||field=="stdout") {
3544                // stdout
3545                fp=stdout;
3546              } else if (field=="stderr") {
3547                // stderr
3548                fp=stderr;
3549              } else {
3550                if (field[0]=='/'||field[0]=='\\') {
3551                  fileName = field;
3552                } else if (field[0]=='~') {
3553                  char * environVar = getenv("HOME");
3554                  if (environVar) {
3555                    std::string home(environVar);
3556                    field=field.erase(0,1);
3557                    fileName = home+field;
3558                  } else {
3559                    fileName=field;
3560                  }
3561                } else {
3562                  fileName = directory+field;
3563                }
3564                fp=fopen(fileName.c_str(),"w");
3565              }
3566              if (fp) {
3567                // make fancy later on
3568                int iRow;
3569                int numberRows=lpSolver->numberRows();
3570                double * dualRowSolution = lpSolver->dualRowSolution();
3571                double * primalRowSolution = 
3572                  lpSolver->primalRowSolution();
3573                double * rowLower = lpSolver->rowLower();
3574                double * rowUpper = lpSolver->rowUpper();
3575                double primalTolerance = lpSolver->primalTolerance();
3576                char format[6];
3577                sprintf(format,"%%-%ds",CoinMax(lengthName,8));
3578                bool doMask = (printMask!=""&&lengthName);
3579                int * maskStarts=NULL;
3580                int maxMasks=0;
3581                char ** masks =NULL;
3582                if (doMask) {
3583                  int nAst =0;
3584                  const char * pMask2 = printMask.c_str();
3585                  char pMask[100];
3586                  int iChar;
3587                  int lengthMask = strlen(pMask2);
3588                  assert (lengthMask<100);
3589                  if (*pMask2=='"') {
3590                    if (pMask2[lengthMask-1]!='"') {
3591                      printf("mismatched \" in mask %s\n",pMask2);
3592                      break;
3593                    } else {
3594                      strcpy(pMask,pMask2+1);
3595                      *strchr(pMask,'"')='\0';
3596                    }
3597                  } else if (*pMask2=='\'') {
3598                    if (pMask2[lengthMask-1]!='\'') {
3599                      printf("mismatched ' in mask %s\n",pMask2);
3600                      break;
3601                    } else {
3602                      strcpy(pMask,pMask2+1);
3603                      *strchr(pMask,'\'')='\0';
3604                    }
3605                  } else {
3606                    strcpy(pMask,pMask2);
3607                  }
3608                  if (lengthMask>lengthName) {
3609                    printf("mask %s too long - skipping\n",pMask);
3610                    break;
3611                  }
3612                  maxMasks = 1;
3613                  for (iChar=0;iChar<lengthMask;iChar++) {
3614                    if (pMask[iChar]=='*') {
3615                      nAst++;
3616                      maxMasks *= (lengthName+1);
3617                    }
3618                  }
3619                  int nEntries = 1;
3620                  maskStarts = new int[lengthName+2];
3621                  masks = new char * [maxMasks];
3622                  char ** newMasks = new char * [maxMasks];
3623                  int i;
3624                  for (i=0;i<maxMasks;i++) {
3625                    masks[i] = new char[lengthName+1];
3626                    newMasks[i] = new char[lengthName+1];
3627                  }
3628                  strcpy(masks[0],pMask);
3629                  for (int iAst=0;iAst<nAst;iAst++) {
3630                    int nOldEntries = nEntries;
3631                    nEntries=0;
3632                    for (int iEntry = 0;iEntry<nOldEntries;iEntry++) {
3633                      char * oldMask = masks[iEntry];
3634                      char * ast = strchr(oldMask,'*');
3635                      assert (ast);
3636                      int length = strlen(oldMask)-1;
3637                      int nBefore = ast-oldMask;
3638                      int nAfter = length-nBefore;
3639                      // and add null
3640                      nAfter++;
3641                      for (int i=0;i<=lengthName-length;i++) {
3642                        char * maskOut = newMasks[nEntries];
3643                        memcpy(maskOut,oldMask,nBefore);
3644                        for (int k=0;k<i;k++) 
3645                          maskOut[k+nBefore]='?';
3646                        memcpy(maskOut+nBefore+i,ast+1,nAfter);
3647                        nEntries++;
3648                        assert (nEntries<=maxMasks);
3649                      }
3650                    }
3651                    char ** temp = masks;
3652                    masks = newMasks;
3653                    newMasks = temp;
3654                  }
3655                  // Now extend and sort
3656                  int * sort = new int[nEntries];
3657                  for (i=0;i<nEntries;i++) {
3658                    char * maskThis = masks[i];
3659                    int length = strlen(maskThis);
3660                    while (maskThis[length-1]==' ')
3661                      length--;
3662                    maskThis[length]='\0';
3663                    sort[i]=length;
3664                  }
3665                  CoinSort_2(sort,sort+nEntries,masks);
3666                  int lastLength=-1;
3667                  for (i=0;i<nEntries;i++) {
3668                    int length = sort[i];
3669                    while (length>lastLength) 
3670                      maskStarts[++lastLength] = i;
3671                  }
3672                  maskStarts[++lastLength]=nEntries;
3673                  delete [] sort;
3674                  for (i=0;i<maxMasks;i++)
3675                    delete [] newMasks[i];
3676                  delete [] newMasks;
3677                }
3678                if (printMode>2) {
3679                  for (iRow=0;iRow<numberRows;iRow++) {
3680                    int type=printMode-3;
3681                    if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
3682                        primalRowSolution[iRow]<rowLower[iRow]-primalTolerance) {
3683                      fprintf(fp,"** ");
3684                      type=2;
3685                    } else if (fabs(primalRowSolution[iRow])>1.0e-8) {
3686                      type=1;
3687                    } else if (numberRows<50) {
3688                      type=3;
3689                    }
3690                    if (doMask&&!maskMatches(maskStarts,masks,rowNames[iRow]))
3691                      type =0;
3692                    if (type) {
3693                      fprintf(fp,"%7d ",iRow);
3694                      if (lengthName)
3695                        fprintf(fp,format,rowNames[iRow].c_str());
3696                      fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
3697                              dualRowSolution[iRow]);
3698                    }
3699                  }
3700                }
3701                int iColumn;
3702                int numberColumns=lpSolver->numberColumns();
3703                double * dualColumnSolution = 
3704                  lpSolver->dualColumnSolution();
3705                double * primalColumnSolution = 
3706                  lpSolver->primalColumnSolution();
3707                double * columnLower = lpSolver->columnLower();
3708                double * columnUpper = lpSolver->columnUpper();
3709                if (printMode!=2) {
3710                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
3711                    int type=(printMode>3) ? 1 :0;
3712                    if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
3713                        primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance) {
3714                      fprintf(fp,"** ");
3715                      type=2;
3716                    } else if (fabs(primalColumnSolution[iColumn])>1.0e-8) {
3717                      type=1;
3718                    } else if (numberColumns<50) {
3719                      type=3;
3720                    }
3721                    // see if integer
3722                    if ((!lpSolver->isInteger(iColumn)||fabs(primalColumnSolution[iColumn])<1.0e-8)
3723                         &&printMode==1)
3724                      type=0;
3725                    if (doMask&&!maskMatches(maskStarts,masks,
3726                                             columnNames[iColumn]))
3727                      type =0;
3728                    if (type) {
3729                      fprintf(fp,"%7d ",iColumn);
3730                      if (lengthName)
3731                        fprintf(fp,format,columnNames[iColumn].c_str());
3732                      fprintf(fp,"%15.8g        %15.8g\n",
3733                              primalColumnSolution[iColumn],
3734                              dualColumnSolution[iColumn]);
3735                    }
3736                  }
3737                } else {
3738                  // special format suitable for OsiRowCutDebugger
3739                  int n=0;
3740                  bool comma=false;
3741                  bool newLine=false;
3742                  fprintf(fp,"\tint intIndicesV[]={\n");
3743                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
3744                    if(primalColumnSolution[iColumn]>0.5&&model.solver()->isInteger(iColumn)) {
3745                      if (comma)
3746                        fprintf(fp,",");
3747                      if (newLine)
3748                        fprintf(fp,"\n");
3749                      fprintf(fp,"%d ",iColumn);
3750                      comma=true;
3751                      newLine=false;
3752                      n++;
3753                      if (n==10) {
3754                        n=0;
3755                        newLine=true;
3756                      }
3757                    }
3758                  }
3759                  fprintf(fp,"};\n");
3760                  n=0;
3761                  comma=false;
3762                  newLine=false;
3763                  fprintf(fp,"\tdouble intSolnV[]={\n");
3764                  for ( iColumn=0;iColumn<numberColumns;iColumn++) {
3765                    if(primalColumnSolution[iColumn]>0.5&&model.solver()->isInteger(iColumn)) {
3766                      if (comma)
3767                        fprintf(fp,",");
3768                      if (newLine)
3769                        fprintf(fp,"\n");
3770                      int value = (int) (primalColumnSolution[iColumn]+0.5);
3771                      fprintf(fp,"%d. ",value);
3772                      comma=true;
3773                      newLine=false;
3774                      n++;
3775                      if (n==10) {
3776                        n=0;
3777                        newLine=true;
3778                      }
3779                    }
3780                  }
3781                  fprintf(fp,"};\n");
3782                }
3783                if (fp!=stdout)
3784                  fclose(fp);
3785                if (masks) {
3786                  delete [] maskStarts;
3787                  for (int i=0;i<maxMasks;i++)
3788                    delete [] masks[i];
3789                  delete [] masks;
3790                }
3791              } else {
3792                std::cout<<"Unable to open file "<<fileName<<std::endl;
3793              }
3794            } else {
3795              std::cout<<"** Current model not valid"<<std::endl;
3796             
3797            }
3798            break;
3799          case SAVESOL:
3800            if (goodModel) {
3801              // get next field
3802              field = CoinReadGetString(argc,argv);
3803              if (field=="$") {
3804                field = parameters[iParam].stringValue();
3805              } else if (field=="EOL") {
3806                parameters[iParam].printString();
3807                break;
3808              } else {
3809                parameters[iParam].setStringValue(field);
3810              }
3811              std::string fileName;
3812              if (field[0]=='/'||field[0]=='\\') {
3813                fileName = field;
3814              } else if (field[0]=='~') {
3815                char * environVar = getenv("HOME");
3816                if (environVar) {
3817                  std::string home(environVar);
3818                  field=field.erase(0,1);
3819                  fileName = home+field;
3820                } else {
3821                  fileName=field;
3822                }
3823              } else {
3824                fileName = directory+field;
3825              }
3826              saveSolution(lpSolver,fileName);
3827            } else {
3828              std::cout<<"** Current model not valid"<<std::endl;
3829             
3830            }
3831            break;
3832          case DUMMY:
3833            break;
3834          default:
3835            abort();
3836          }
3837        } 
3838      } else if (!numberMatches) {
3839        std::cout<<"No match for "<<field<<" - ? for list of commands"
3840                 <<std::endl;
3841      } else if (numberMatches==1) {
3842        if (!numberQuery) {
3843          std::cout<<"Short match for "<<field<<" - completion: ";
3844          std::cout<<parameters[firstMatch].matchName()<<std::endl;
3845        } else if (numberQuery) {
3846          std::cout<<parameters[firstMatch].matchName()<<" : ";
3847          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
3848          if (numberQuery>=2) 
3849            parameters[firstMatch].printLongHelp();
3850        }
3851      } else {
3852        if (!numberQuery) 
3853          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
3854                   <<std::endl;
3855        else
3856          std::cout<<"Completions of "<<field<<":"<<std::endl;
3857        for ( iParam=0; iParam<numberParameters; iParam++ ) {
3858          int match = parameters[iParam].matches(field);
3859          if (match&&parameters[iParam].displayThis()) {
3860            std::cout<<parameters[iParam].matchName();
3861            if (numberQuery>=2) 
3862              std::cout<<" : "<<parameters[iParam].shortHelp();
3863            std::cout<<std::endl;
3864          }
3865        }
3866      }
3867    }
3868  }
3869  // By now all memory should be freed
3870#ifdef DMALLOC
3871  dmalloc_log_unfreed();
3872  dmalloc_shutdown();
3873#endif
3874  return 0;
3875}   
3876static void breakdown(const char * name, int numberLook, const double * region)
3877{
3878  double range[] = {
3879    -COIN_DBL_MAX,
3880    -1.0e15,-1.0e11,-1.0e8,-1.0e5,-1.0e4,-1.0e3,-1.0e2,-1.0e1,
3881    -1.0,
3882    -1.0e-1,-1.0e-2,-1.0e-3,-1.0e-4,-1.0e-5,-1.0e-8,-1.0e-11,-1.0e-15,
3883    0.0,
3884    1.0e-15,1.0e-11,1.0e-8,1.0e-5,1.0e-4,1.0e-3,1.0e-2,1.0e-1,
3885    1.0,
3886    1.0e1,1.0e2,1.0e3,1.0e4,1.0e5,1.0e8,1.0e11,1.0e15,
3887    COIN_DBL_MAX};
3888  int nRanges = (int) (sizeof(range)/sizeof(double));
3889  int * number = new int[nRanges];
3890  memset(number,0,nRanges*sizeof(int));
3891  int * numberExact = new int[nRanges];
3892  memset(numberExact,0,nRanges*sizeof(int));
3893  int i;
3894  for ( i=0;i<numberLook;i++) {
3895    double value = region[i];
3896    for (int j=0;j<nRanges;j++) {
3897      if (value==range[j]) {
3898        numberExact[j]++;
3899        break;
3900      } else if (value<range[j]) {
3901        number[j]++;
3902        break;
3903      }
3904    }
3905  }
3906  printf("\n%s has %d entries\n",name,numberLook);
3907  for (i=0;i<nRanges;i++) {
3908    if (number[i]) 
3909      printf("%d between %g and %g",number[i],range[i-1],range[i]);
3910    if (numberExact[i]) {
3911      if (number[i])
3912        printf(", ");
3913      printf("%d exactly at %g",numberExact[i],range[i]);
3914    }
3915    if (number[i]+numberExact[i])
3916      printf("\n");
3917  }
3918  delete [] number;
3919  delete [] numberExact;
3920}
3921static void statistics(ClpSimplex * originalModel, ClpSimplex * model)
3922{
3923  int numberColumns = originalModel->numberColumns();
3924  const char * integerInformation  = originalModel->integerInformation(); 
3925  const double * columnLower = originalModel->columnLower();
3926  const double * columnUpper = originalModel->columnUpper();
3927  int numberIntegers=0;
3928  int numberBinary=0;
3929  int iRow,iColumn;
3930  if (integerInformation) {
3931    for (iColumn=0;iColumn<numberColumns;iColumn++) {
3932      if (integerInformation[iColumn]) {
3933        if (columnUpper[iColumn]>columnLower[iColumn]) {
3934          numberIntegers++;
3935          if (columnUpper[iColumn]==0.0&&columnLower[iColumn]==1) 
3936            numberBinary++;
3937        }
3938      }
3939    }
3940  }
3941  numberColumns = model->numberColumns();
3942  int numberRows = model->numberRows();
3943  columnLower = model->columnLower();
3944  columnUpper = model->columnUpper();
3945  const double * rowLower = model->rowLower();
3946  const double * rowUpper = model->rowUpper();
3947  const double * objective = model->objective();
3948  CoinPackedMatrix * matrix = model->matrix();
3949  CoinBigIndex numberElements = matrix->getNumElements();
3950  const int * columnLength = matrix->getVectorLengths();
3951  //const CoinBigIndex * columnStart = matrix->getVectorStarts();
3952  const double * elementByColumn = matrix->getElements();
3953  int * number = new int[numberRows+1];
3954  memset(number,0,(numberRows+1)*sizeof(int));
3955  int numberObjSingletons=0;
3956  /* cType
3957     0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up,
3958     8 0/1
3959  */ 
3960  int cType[9];
3961  std::string cName[]={"0.0->inf,","0.0->up,","lo->inf,","lo->up,","free,","fixed,","-inf->0.0,",
3962                       "-inf->up,","0.0->1.0"};
3963  int nObjective=0;
3964  memset(cType,0,sizeof(cType));
3965  for (iColumn=0;iColumn<numberColumns;iColumn++) {
3966    int length=columnLength[iColumn];
3967    if (length==1&&objective[iColumn])
3968      numberObjSingletons++;
3969    number[length]++;
3970    if (objective[iColumn])
3971      nObjective++;
3972    if (columnLower[iColumn]>-1.0e20) {
3973      if (columnLower[iColumn]==0.0) {
3974        if (columnUpper[iColumn]>1.0e20)
3975          cType[0]++;
3976        else if (columnUpper[iColumn]==1.0)
3977          cType[8]++;
3978        else if (columnUpper[iColumn]==0.0)
3979          cType[5]++;
3980        else
3981          cType[1]++;
3982      } else {
3983        if (columnUpper[iColumn]>1.0e20) 
3984          cType[2]++;
3985        else if (columnUpper[iColumn]==columnLower[iColumn])
3986          cType[5]++;
3987        else
3988          cType[3]++;
3989      }
3990    } else {
3991      if (columnUpper[iColumn]>1.0e20) 
3992        cType[4]++;
3993      else if (columnUpper[iColumn]==0.0) 
3994        cType[6]++;
3995      else
3996        cType[7]++;
3997    }
3998  }
3999  /* rType
4000     0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other,
4001     7 L 0,  8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free
4002  */ 
4003  int rType[13];
4004  std::string rName[]={"E 0.0,","E 1.0,","E -1.0,","E other,","G 0.0,","G 1.0,","G other,",
4005                       "L 0.0,","L 1.0,","L other,","Range 0.0->1.0,","Range other,","Free"};
4006  memset(rType,0,sizeof(rType));
4007  for (iRow=0;iRow<numberRows;iRow++) {
4008    if (rowLower[iRow]>-1.0e20) {
4009      if (rowLower[iRow]==0.0) {
4010        if (rowUpper[iRow]>1.0e20)
4011          rType[4]++;
4012        else if (rowUpper[iRow]==1.0)
4013          rType[10]++;
4014        else if (rowUpper[iRow]==0.0)
4015          rType[0]++;
4016        else
4017          rType[11]++;
4018      } else if (rowLower[iRow]==1.0) {
4019        if (rowUpper[iRow]>1.0e20) 
4020          rType[5]++;
4021        else if (rowUpper[iRow]==rowLower[iRow])
4022          rType[1]++;
4023        else
4024          rType[11]++;
4025      } else if (rowLower[iRow]==-1.0) {
4026        if (rowUpper[iRow]>1.0e20) 
4027          rType[6]++;
4028        else if (rowUpper[iRow]==rowLower[iRow])
4029          rType[2]++;
4030        else
4031          rType[11]++;
4032      } else {
4033        if (rowUpper[iRow]>1.0e20) 
4034          rType[6]++;
4035        else if (rowUpper[iRow]==rowLower[iRow])
4036          rType[3]++;
4037        else
4038          rType[11]++;
4039      }
4040    } else {
4041      if (rowUpper[iRow]>1.0e20) 
4042        rType[12]++;
4043      else if (rowUpper[iRow]==0.0) 
4044        rType[7]++;
4045      else if (rowUpper[iRow]==1.0) 
4046        rType[8]++;
4047      else
4048        rType[9]++;
4049    }
4050  }
4051  // Basic statistics
4052  printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n",
4053         numberRows,numberColumns,nObjective,numberElements);
4054  if (number[0]+number[1]) {
4055    printf("There are ");
4056    if (numberObjSingletons)
4057      printf("%d singletons with objective ",numberObjSingletons);
4058    int numberNoObj = number[1]-numberObjSingletons;
4059    if (numberNoObj)
4060      printf("%d singletons with no objective ",numberNoObj);
4061    if (number[0])
4062      printf("** %d columns have no entries",number[0]);
4063    printf("\n");
4064  }
4065  printf("Column breakdown:\n");
4066  int k;
4067  for (k=0;k<(int) (sizeof(cType)/sizeof(int));k++) {
4068    printf("%d of type %s ",cType[k],cName[k].c_str());
4069    if (((k+1)%3)==0)
4070      printf("\n");
4071  }
4072  if ((k%3)!=0)
4073    printf("\n");
4074  printf("Row breakdown:\n");
4075  for (k=0;k<(int) (sizeof(rType)/sizeof(int));k++) {
4076    printf("%d of type %s ",rType[k],rName[k].c_str());
4077    if (((k+1)%3)==0)
4078      printf("\n");
4079  }
4080  if ((k%3)!=0)
4081    printf("\n");
4082  if (model->logLevel()<2)
4083    return ;
4084  int kMax = model->logLevel()>3 ? 1000000 : 10;
4085  k=0;
4086  for (iRow=1;iRow<=numberRows;iRow++) {
4087    if (number[iRow]) {
4088      k++;
4089      printf("%d columns have %d entries\n",number[iRow],iRow);
4090      if (k==kMax)
4091        break;
4092    }
4093  }
4094  if (k<numberRows) {
4095    int kk=k;
4096    k=0;
4097    for (iRow=numberRows;iRow>=1;iRow--) {
4098      if (number[iRow]) {
4099        k++;
4100        if (k==kMax)
4101          break;
4102      }
4103    }
4104    if (k>kk) {
4105      printf("\n    .........\n\n");
4106      iRow=k;
4107      k=0;
4108      for (;iRow<numberRows;iRow++) {
4109        if (number[iRow]) {
4110          k++;
4111          printf("%d columns have %d entries\n",number[iRow],iRow);
4112          if (k==kMax)
4113            break;
4114        }
4115      }
4116    }
4117  }
4118  delete [] number;
4119  printf("\n\n");
4120  // get row copy
4121  CoinPackedMatrix rowCopy = *matrix;
4122  rowCopy.reverseOrdering();
4123  //const int * column = rowCopy.getIndices();
4124  const int * rowLength = rowCopy.getVectorLengths();
4125  //const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
4126  //const double * element = rowCopy.getElements();
4127  number = new int[numberColumns+1];
4128  memset(number,0,(numberColumns+1)*sizeof(int));
4129  for (iRow=0;iRow<numberRows;iRow++) {
4130    int length=rowLength[iRow];
4131    number[length]++;
4132  }
4133  if (number[0])
4134    printf("** %d rows have no entries\n",number[0]);
4135  k=0;
4136  for (iColumn=1;iColumn<=numberColumns;iColumn++) {
4137    if (number[iColumn]) {
4138      k++;
4139      printf("%d rows have %d entries\n",number[iColumn],iColumn);
4140      if (k==kMax)
4141        break;
4142    }
4143  }
4144  if (k<numberColumns) {
4145    int kk=k;
4146    k=0;
4147    for (iColumn=numberColumns;iColumn>=1;iColumn--) {
4148      if (number[iColumn]) {
4149        k++;
4150        if (k==kMax)
4151          break;
4152      }
4153    }
4154    if (k>kk) {
4155      printf("\n    .........\n\n");
4156      iColumn=k;
4157      k=0;
4158      for (;iColumn<numberColumns;iColumn++) {
4159        if (number[iColumn]) {
4160          k++;
4161          printf("%d rows have %d entries\n",number[iColumn],iColumn);
4162          if (k==kMax)
4163            break;
4164        }
4165      }
4166    }
4167  }
4168  delete [] number;
4169  // Now do breakdown of ranges
4170  breakdown("Elements",numberElements,elementByColumn);
4171  breakdown("RowLower",numberRows,rowLower);
4172  breakdown("RowUpper",numberRows,rowUpper);
4173  breakdown("ColumnLower",numberColumns,columnLower);
4174  breakdown("ColumnUpper",numberColumns,columnUpper);
4175  breakdown("Objective",numberColumns,objective);
4176}
4177static bool maskMatches(const int * starts, char ** masks,
4178                        std::string & check)
4179{
4180  // back to char as I am old fashioned
4181  const char * checkC = check.c_str();
4182  int length = strlen(checkC);
4183  while (checkC[length-1]==' ')
4184    length--;
4185  for (int i=starts[length];i<starts[length+1];i++) {
4186    char * thisMask = masks[i];
4187    int k;
4188    for ( k=0;k<length;k++) {
4189      if (thisMask[k]!='?'&&thisMask[k]!=checkC[k]) 
4190        break;
4191    }
4192    if (k==length)
4193      return true;
4194  }
4195  return false;
4196}
4197static void clean(char * temp)
4198{
4199  char * put = temp;
4200  while (*put>=' ')
4201    put++;
4202  *put='\0';
4203}
4204static void generateCode(const char * fileName,int type,int preProcess)
4205{
4206  // options on code generation
4207  bool sizecode = (type&4)!=0;
4208  type &= 3;
4209  FILE * fp = fopen(fileName,"r");
4210  assert (fp);
4211  int numberLines=0;
4212#define MAXLINES 5000
4213#define MAXONELINE 200
4214  char line[MAXLINES][MAXONELINE];
4215  strcpy(line[numberLines++],"0#if defined(_MSC_VER)");
4216  strcpy(line[numberLines++],"0// Turn off compiler warning about long names");
4217  strcpy(line[numberLines++],"0#  pragma warning(disable:4786)");
4218  strcpy(line[numberLines++],"0#endif\n");
4219  strcpy(line[numberLines++],"0#include <cassert>");
4220  strcpy(line[numberLines++],"0#include <iomanip>");
4221  strcpy(line[numberLines++],"0#include \"OsiClpSolverInterface.hpp\"");
4222  strcpy(line[numberLines++],"0#include \"CbcModel.hpp\"");
4223  strcpy(line[numberLines++],"0#include \"CbcCutGenerator.hpp\"");
4224  strcpy(line[numberLines++],"0#include \"CbcStrategy.hpp\"");
4225  strcpy(line[numberLines++],"0#include \"CglPreProcess.hpp\"");
4226  strcpy(line[numberLines++],"0#include \"CoinTime.hpp\"");
4227  while (fgets(line[numberLines],MAXONELINE,fp)) {
4228    assert (numberLines<MAXLINES);
4229    clean(line[numberLines]);
4230    numberLines++;
4231  }
4232  fclose(fp);
4233  strcpy(line[numberLines++],"0\nint main (int argc, const char *argv[])\n{");
4234  strcpy(line[numberLines++],"0  OsiClpSolverInterface solver1;");
4235  strcpy(line[numberLines++],"0  int status=1;");
4236  strcpy(line[numberLines++],"0  if (argc<2)");
4237  strcpy(line[numberLines++],"0    std::cout<<\"Please give file name\"<<std::endl;");
4238  strcpy(line[numberLines++],"0  else");
4239  strcpy(line[numberLines++],"0    status=solver1.readMps(argv[1],\"\");");
4240  strcpy(line[numberLines++],"0  if (status) {");
4241  strcpy(line[numberLines++],"0    std::cout<<\"Bad readMps \"<<argv[1]<<std::endl;");
4242  strcpy(line[numberLines++],"0    exit(1);");
4243  strcpy(line[numberLines++],"0  }\n");
4244  strcpy(line[numberLines++],"0  double time1 = CoinCpuTime();");
4245  strcpy(line[numberLines++],"0  CbcModel model(solver1);");
4246  strcpy(line[numberLines++],"0  // Now do requested saves and modifications");
4247  strcpy(line[numberLines++],"0  CbcModel * cbcModel = & model;");
4248  strcpy(line[numberLines++],"0  OsiSolverInterface * osiModel = model.solver();");
4249  strcpy(line[numberLines++],"0  OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel);");
4250  strcpy(line[numberLines++],"0  ClpSimplex * clpModel = osiclpModel->getModelPtr();");
4251  // add in comments about messages
4252  strcpy(line[numberLines++],"3  // You can save some time by switching off message building");
4253  strcpy(line[numberLines++],"3  // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);");
4254  strcpy(line[numberLines++],"5  cbcModel->initialSolve();");
4255  strcpy(line[numberLines++],"5  if (clpModel->tightenPrimalBounds()!=0) {");
4256  strcpy(line[numberLines++],"5    std::cout<<\"Problem is infeasible - tightenPrimalBounds!\"<<std::endl;");
4257  strcpy(line[numberLines++],"5    exit(1);");
4258  strcpy(line[numberLines++],"5  }");
4259  strcpy(line[numberLines++],"5  clpModel->dual();  // clean up");
4260  if (sizecode) {
4261    // override some settings
4262    strcpy(line[numberLines++],"5  // compute some things using problem size");
4263    strcpy(line[numberLines++],"5  cbcModel->setMinimumDrop(min(5.0e-2,");
4264    strcpy(line[numberLines++],"5       fabs(cbcModel->getMinimizationObjValue())*1.0e-3+1.0e-4));");
4265    strcpy(line[numberLines++],"5  if (cbcModel->getNumCols()<500)");
4266    strcpy(line[numberLines++],"5    cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible");
4267    strcpy(line[numberLines++],"5  else if (cbcModel->getNumCols()<5000)");
4268    strcpy(line[numberLines++],"5    cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop");
4269    strcpy(line[numberLines++],"5  else");
4270    strcpy(line[numberLines++],"5    cbcModel->setMaximumCutPassesAtRoot(20);");
4271    strcpy(line[numberLines++],"5  cbcModel->setMaximumCutPasses(1);");
4272  }
4273  if (preProcess<=0) {
4274    // no preprocessing or strategy
4275    if (preProcess) {
4276      strcpy(line[numberLines++],"5  // Preprocessing using CbcStrategy");
4277      strcpy(line[numberLines++],"5  CbcStrategyDefault strategy(true,5,5);");
4278      strcpy(line[numberLines++],"5  strategy.setupPreProcessing(1);");
4279      strcpy(line[numberLines++],"5  cbcModel->setStrategy(strategy);");
4280    }
4281  } else {
4282    int translate[]={9999,0,0,-1,2,3};
4283    strcpy(line[numberLines++],"5  // Hand coded preprocessing");
4284    strcpy(line[numberLines++],"5  CglPreProcess process;");
4285    strcpy(line[numberLines++],"5  OsiSolverInterface * saveSolver=cbcModel->solver()->clone();");
4286    strcpy(line[numberLines++],"5  // Tell solver we are in Branch and Cut");
4287    strcpy(line[numberLines++],"5  saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;");
4288    strcpy(line[numberLines++],"5  // Default set of cut generators");
4289    strcpy(line[numberLines++],"5  CglProbing generator1;");
4290    strcpy(line[numberLines++],"5  generator1.setUsingObjective(true);");
4291    strcpy(line[numberLines++],"5  generator1.setMaxPass(3);");
4292    strcpy(line[numberLines++],"5  generator1.setMaxProbeRoot(saveSolver->getNumCols());");
4293    strcpy(line[numberLines++],"5  generator1.setMaxElements(100);");
4294    strcpy(line[numberLines++],"5  generator1.setMaxLookRoot(50);");
4295    strcpy(line[numberLines++],"5  generator1.setRowCuts(3);");
4296    strcpy(line[numberLines++],"5  // Add in generators");
4297    strcpy(line[numberLines++],"5  process.addCutGenerator(&generator1);");
4298    strcpy(line[numberLines++],"5  process.messageHandler()->setLogLevel(cbcModel->logLevel());");
4299    strcpy(line[numberLines++],"5  OsiSolverInterface * solver2 = ");
4300    sprintf(line[numberLines++],"5    process.preProcessNonDefault(*saveSolver,%d,10);",translate[preProcess]);
4301    strcpy(line[numberLines++],"5  // Tell solver we are not in Branch and Cut");
4302    strcpy(line[numberLines++],"5  saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;");
4303    strcpy(line[numberLines++],"5  if (solver2)");
4304    strcpy(line[numberLines++],"5    solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;");
4305    strcpy(line[numberLines++],"5  if (!solver2) {");
4306    strcpy(line[numberLines++],"5    std::cout<<\"Pre-processing says infeasible!\"<<std::endl;");
4307    strcpy(line[numberLines++],"5    exit(1);");
4308    strcpy(line[numberLines++],"5  } else {");
4309    strcpy(line[numberLines++],"5    std::cout<<\"processed model has \"<<solver2->getNumRows()");
4310    strcpy(line[numberLines++],"5            <<\" rows, \"<<solver2->getNumCols()");
4311    strcpy(line[numberLines++],"5            <<\" and \"<<solver2->getNumElements()<<std::endl;");
4312    strcpy(line[numberLines++],"5  }");
4313    strcpy(line[numberLines++],"5  // we have to keep solver2 so pass clone");
4314    strcpy(line[numberLines++],"5  solver2 = solver2->clone();");
4315    strcpy(line[numberLines++],"5  cbcModel->assignSolver(solver2);");
4316    strcpy(line[numberLines++],"5  cbcModel->initialSolve();");
4317  }
4318  // add in actual solve
4319  strcpy(line[numberLines++],"5  cbcModel->branchAndBound();");
4320  strcpy(line[numberLines++],"8  std::cout<<argv[1]<<\" took \"<<CoinCpuTime()-time1<<\" seconds, \"");
4321  strcpy(line[numberLines++],"8    <<cbcModel->getNodeCount()<<\" nodes with objective \"");
4322  strcpy(line[numberLines++],"8    <<cbcModel->getObjValue()");
4323  strcpy(line[numberLines++],"8    <<(!cbcModel->status() ? \" Finished\" : \" Not finished\")");
4324  strcpy(line[numberLines++],"8    <<std::endl;");
4325  strcpy(line[numberLines++],"5  // For best solution");
4326  strcpy(line[numberLines++],"5  int numberColumns = solver1.getNumCols();");
4327  strcpy(line[numberLines++],"5  if (cbcModel->getMinimizationObjValue()<1.0e50) {");
4328  if (preProcess>0) {
4329    strcpy(line[numberLines++],"5    // post process");
4330    strcpy(line[numberLines++],"5    process.postProcess(*cbcModel->solver());");
4331    strcpy(line[numberLines++],"5    // Solution now back in saveSolver");
4332    strcpy(line[numberLines++],"5    cbcModel->assignSolver(saveSolver);");
4333    strcpy(line[numberLines++],"5    memcpy(cbcModel->bestSolution(),cbcModel->solver()->getColSolution(),");
4334    strcpy(line[numberLines++],"5          numberColumns*sizeof(double));");
4335  }
4336  strcpy(line[numberLines++],"5    // put back in original solver");
4337  strcpy(line[numberLines++],"5    solver1.setColSolution(cbcModel->bestSolution());");
4338  strcpy(line[numberLines++],"5    const double * solution = solver1.getColSolution();");
4339  strcpy(line[numberLines++],"8  \n  // Now you would use solution etc etc\n");
4340  strcpy(line[numberLines++],"5");
4341  strcpy(line[numberLines++],"5    // Get names from solver1 (as OsiSolverInterface may lose)");
4342  strcpy(line[numberLines++],"5    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();");
4343  strcpy(line[numberLines++],"5    ");
4344  strcpy(line[numberLines++],"5    int iColumn;");
4345  strcpy(line[numberLines++],"5    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);");
4346  strcpy(line[numberLines++],"5    ");
4347  strcpy(line[numberLines++],"5    std::cout<<\"--------------------------------------\"<<std::endl;");
4348  strcpy(line[numberLines++],"5    for (iColumn=0;iColumn<numberColumns;iColumn++) {");
4349  strcpy(line[numberLines++],"5      double value=solution[iColumn];");
4350  strcpy(line[numberLines++],"5      if (fabs(value)>1.0e-7&&solver1.isInteger(iColumn)) ");
4351  strcpy(line[numberLines++],"5 std::cout<<std::setw(6)<<iColumn<<\" \"");
4352  strcpy(line[numberLines++],"5                 <<columnNames[iColumn]<<\" \"");
4353  strcpy(line[numberLines++],"5                 <<value<<std::endl;");
4354  strcpy(line[numberLines++],"5    }");
4355  strcpy(line[numberLines++],"5    std::cout<<\"--------------------------------------\"<<std::endl;");
4356  strcpy(line[numberLines++],"5  ");
4357  strcpy(line[numberLines++],"5    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);");
4358  strcpy(line[numberLines++],"5  }");
4359  strcpy(line[numberLines++],"8  return 0;\n}");
4360  fp = fopen(fileName,"w");
4361  assert (fp);
4362
4363  int wanted[9];
4364  memset(wanted,0,sizeof(wanted));
4365  wanted[0]=wanted[3]=wanted[5]=wanted[8]=1;
4366  if (type>0) 
4367    wanted[1]=wanted[6]=1;
4368  if (type>1) 
4369    wanted[2]=wanted[4]=wanted[7]=1;
4370  std::string header[9]=
4371  { "","Save values","Redundant save of default values","Set changed values",
4372    "Redundant set default values","Solve","Restore values","Redundant restore values","Add to model"};
4373  for (int iType=0;iType<9;iType++) {
4374    if (!wanted[iType])
4375      continue;
4376    int n=0;
4377    int iLine;
4378    for (iLine=0;iLine<numberLines;iLine++) {
4379      if (line[iLine][0]=='0'+iType) {
4380        if (!n&&header[iType]!="")
4381          fprintf(fp,"\n  // %s\n\n",header[iType].c_str());
4382        n++;
4383        // skip save and clp as cloned
4384        if (!strstr(line[iLine],"save")||(!strstr(line[iLine],"clpMo")&&
4385                                          !strstr(line[iLine],"_Osi")))
4386          fprintf(fp,"%s\n",line[iLine]+1);
4387      }
4388    }
4389  }
4390  fclose(fp);
4391  printf("C++ file written to %s\n",fileName);
4392}
4393/*
4394  Version 1.00.00 November 16 2005.
4395  This is to stop me (JJF) messing about too much.
4396  Tuning changes should be noted here.
4397  The testing next version may be activated by CBC_NEXT_VERSION
4398  This applies to OsiClp, Clp etc
4399  Version 1.00.01 November 24 2005
4400  Added several classes for advanced users.  This can't affect code (if you don't use it)
4401  Made some tiny changes (for N way branching) which should not change anything.
4402  CbcNWay object class - for N way branching this also allows use of CbcConsequence class.
4403  CbcBranchAllDifferent object class - for branching on general integer variables
4404  to stop them having same value so branches are x >= y+1 and x <= y-1.
4405  Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly)
4406  and CglStored which just has a list of cuts which can be activated.
4407  Modified preprocess option to SOS
4408  Version 1.00.02 December 9 2005
4409  Added use of CbcStrategy to do clean preprocessing
4410  Added use of referenceSolver for cleaner repetition of Cbc
4411  Version 1.01.00 February 2 2006
4412  Added first try at Ampl interface
4413*/
Note: See TracBrowser for help on using the repository browser.