source: branches/devel/Cbc/src/CoinSolve.cpp @ 497

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

obviously needs more work

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