source: branches/pre/ClpSolve.cpp @ 212

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

lots of stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.5 KB
Line 
1// Copyright (C) 2003, International Business Machines
2// Corporation and others.  All Rights Reserved.
3
4// This file has higher level solve functions
5
6
7#include "CoinPragma.hpp"
8
9#include <math.h>
10
11#include "CoinHelperFunctions.hpp"
12#include "CoinSort.hpp"
13#include "ClpFactorization.hpp"
14#include "ClpSimplex.hpp"
15#include "ClpSolve.hpp"
16#include "ClpPackedMatrix.hpp"
17#include "ClpPlusMinusOneMatrix.hpp"
18#include "ClpMessage.hpp"
19#include "CoinTime.hpp"
20
21#include "ClpPresolve.hpp"
22#ifdef CLP_IDIOT
23#include "Idiot.hpp"
24#endif
25//#############################################################################
26// Allow for interrupts
27// But is this threadsafe ? (so switched off by option
28#include <signal.h>
29static ClpSimplex * currentModel = NULL;
30static void signal_handler(int whichSignal)
31{
32  if (currentModel!=NULL) 
33    currentModel->setMaximumIterations(0); // stop at next iterations
34  return;
35}
36
37/** General solve algorithm which can do presolve
38    special options (bits)
39    1 - do not perturb
40    2 - do not scale
41    4 - use crash (default allslack in dual, idiot in primal)
42    8 - all slack basis in primal
43    16 - switch off interrupt handling
44    32 - do not try and make plus minus one matrix
45 */
46int 
47ClpSimplex::initialSolve(ClpSolve & options)
48{
49  ClpSolve::SolveType method=options.getSolveType();
50  ClpSolve::PresolveType presolve = options.getPresolveType();
51  int saveMaxIterations = maximumIterations();
52  int finalStatus=-1;
53  int numberIterations=0;
54  double time1 = CoinCpuTime();
55  double timeX = time1;
56  double time2;
57  ClpMatrixBase * saveMatrix=NULL;
58  ClpSimplex * model2 = this;
59  bool interrupt = (options.getSpecialOption(2)==0);
60  sighandler_t saveSignal=SIG_DFL;
61  if (interrupt) {
62    currentModel = model2;
63    // register signal handler
64    saveSignal = signal(SIGINT,signal_handler);
65  }
66  ClpPresolve pinfo;
67  double timePresolve=0.0;
68  double timeIdiot=0.0;
69  double timeCore=0.0;
70  double timeSimplex=0.0;
71  int savePerturbation=perturbation_;
72  int saveScaling = scalingFlag_;
73
74  if (presolve!=ClpSolve::presolveOff) {
75    int numberPasses=5;
76    if (presolve==ClpSolve::presolveNumber) {
77      numberPasses=options.getPresolvePasses();
78      presolve = ClpSolve::presolveOn;
79    }
80    model2 = pinfo.presolvedModel(*this,1.0e-8,
81                                  false,numberPasses,true);
82    time2 = CoinCpuTime();
83    timePresolve = time2-timeX;
84    handler_->message(CLP_INTERVAL_TIMING,messages_)
85      <<"Presolve"<<timePresolve<<time2-time1
86      <<CoinMessageEol;
87    timeX=time2;
88    if (model2) {
89      if (method==ClpSolve::useDual) {
90        int numberInfeasibilities = model2->tightenPrimalBounds();
91        if (numberInfeasibilities) {
92          handler_->message(CLP_INFEASIBLE,messages_)
93            <<CoinMessageEol;
94          model2 = this;
95          presolve=ClpSolve::presolveOff;
96        }
97      }
98    } else {
99      handler_->message(CLP_INFEASIBLE,messages_)
100        <<CoinMessageEol;
101      model2 = this;
102      presolve=ClpSolve::presolveOff;
103    }
104    // We may be better off using original
105    if (presolve!=ClpSolve::presolveOff&&
106        numberRows_<1.01*model2->numberRows_&&numberColumns_<1.01*model2->numberColumns_) {
107      delete model2;
108      model2 = this;
109      presolve=ClpSolve::presolveOff;
110    }
111  }
112  if (interrupt)
113    currentModel = model2;
114  // See if worth trying +- one matrix
115  bool plusMinus=false;
116  int numberElements=model2->getNumElements();
117  // For below >0 overrides
118  // 0 means no, -1 means maybe
119  int doIdiot=0;
120  int doCrash=0;
121  int doSprint=0;
122  switch (options.getSpecialOption(1)) {
123  case 0:
124    doIdiot=-1;
125    doCrash=-1;
126    doSprint=-1;
127    break;
128  case 1:
129    doIdiot=0;
130    doCrash=1;
131    doSprint=0;
132    break;
133  case 2:
134    doIdiot=1;
135    doCrash=0;
136    doSprint=0;
137    break;
138  case 3:
139    doIdiot=0;
140    doCrash=0;
141    doSprint=1;
142    break;
143  case 4:
144    doIdiot=0;
145    doCrash=0;
146    doSprint=0;
147    break;
148  case 5:
149    doIdiot=0;
150    doCrash=-1;
151    doSprint=-1;
152    break;
153  case 6:
154    doIdiot=-1;
155    doCrash=-1;
156    doSprint=0;
157    break;
158  case 7:
159    doIdiot=-1;
160    doCrash=0;
161    doSprint=-1;
162    break;
163  case 8:
164    doIdiot=-1;
165    doCrash=0;
166    doSprint=0;
167    break;
168  case 9:
169    doIdiot=0;
170    doCrash=0;
171    doSprint=-1;
172    break;
173  default:
174    abort();
175  }
176  int numberColumns = model2->numberColumns();
177  int numberRows = model2->numberRows();
178  // If not all slack basis - switch off all
179  int number=0;
180  int iRow;
181  for (iRow=0;iRow<numberRows;iRow++)
182    if (model2->getRowStatus(iRow)==basic)
183      number++;
184  if (number<numberRows) {
185    doIdiot=0;
186    doCrash=0;
187    doSprint=0;
188  }
189  if (options.getSpecialOption(3)==0) {
190    if(numberElements>100000)
191      plusMinus=true;
192    if(numberElements>10000&&((doIdiot||doSprint)&&method==ClpSolve::usePrimal)) 
193      plusMinus=true;
194  }
195  if (plusMinus) {
196    saveMatrix = model2->clpMatrix();
197    ClpPackedMatrix* clpMatrix =
198      dynamic_cast< ClpPackedMatrix*>(saveMatrix);
199    if (clpMatrix) {
200      ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
201      if (newMatrix->getIndices()) {
202        model2->replaceMatrix(newMatrix);
203      } else {
204        handler_->message(CLP_MATRIX_CHANGE,messages_)
205          <<"+- 1"
206          <<CoinMessageEol;
207        saveMatrix=NULL;
208        plusMinus=false;
209        delete newMatrix;
210      }
211    } else {
212      saveMatrix=NULL;
213      plusMinus=false;
214    }
215  }
216  if (model2->factorizationFrequency()==200) {
217    // User did not touch preset
218    model2->setFactorizationFrequency(100+model2->numberRows()/200);
219  }
220  if (method==ClpSolve::usePrimalorSprint) {
221    if (doSprint<0) { 
222      if(numberRows*10>numberColumns||numberColumns<6000
223         ||(numberRows*20>numberColumns&&!plusMinus))
224        method=ClpSolve::usePrimal; // switch off sprint
225    } else if (doSprint==0) {
226      method=ClpSolve::usePrimal; // switch off sprint
227    }
228  }
229  if (method==ClpSolve::useDual) {
230    if (options.getSpecialOption(0)!=0)
231      model2->crash(1000,1);
232    model2->dual();
233    time2 = CoinCpuTime();
234    timeCore = time2-timeX;
235    handler_->message(CLP_INTERVAL_TIMING,messages_)
236      <<"Dual"<<timeCore<<time2-time1
237      <<CoinMessageEol;
238    timeX=time2;
239  } else if (method==ClpSolve::usePrimal) {
240#ifdef CLP_IDIOT
241    if (doIdiot) {
242      int nPasses=0;
243      Idiot info(*model2);
244      // Get ratio of average number of elements per column to 5
245      double ratio  = ((double) numberElements/(double) numberColumns)/5.0;
246      if (numberRows>200&&numberColumns>5000&&numberColumns>2*numberRows) {
247        if (plusMinus) {
248          // look at rhs
249          int iRow;
250          double largest=0.0;
251          double smallest = 1.0e30;
252          for (iRow=0;iRow<numberRows;iRow++) {
253            double value;
254            value = model2->rowLower_[iRow];
255            if (value) {
256              largest = max(largest,fabs(value));
257              smallest=min(smallest,fabs(value));
258            }
259            value = model2->rowUpper_[iRow];
260            if (value) {
261              largest = max(largest,fabs(value));
262              smallest=min(smallest,fabs(value));
263            }
264          }
265          if (largest/smallest>2.0) {
266            nPasses = 10+numberColumns/100000;
267            nPasses = min(nPasses,50);
268            nPasses = max(nPasses,15);
269            if (numberElements<3*numberColumns) 
270              nPasses=10; // probably not worh it
271            info.setLightweight(1); // say lightweight idiot
272          } else if (largest/smallest>1.01||numberElements<=3*numberColumns) {
273            nPasses = 10+numberColumns/1000;
274            nPasses = min(nPasses,100);
275            nPasses = max(nPasses,30);
276          } else {
277            nPasses = 10+numberColumns/1000;
278            nPasses = min(nPasses,200);
279            nPasses = max(nPasses,100);
280            info.setStartingWeight(1.0e-1);
281            info.setReduceIterations(6);
282            //info.setFeasibilityTolerance(1.0e-7);
283          }
284        } else {
285          nPasses = 10+numberColumns/100000;
286          if (numberColumns>4*numberRows) 
287            nPasses = min(nPasses,50);
288          else
289            nPasses=5;
290          info.setLightweight(1); // say lightweight idiot
291          if (numberElements<3*numberColumns) 
292            nPasses=2; // probably not worh it
293          else
294            nPasses = max(nPasses,5);
295          nPasses = (int) (((double) nPasses)/ratio); // reduce if lots of elements per column
296          if (nPasses<2)
297            nPasses=0;
298          //info.setStartingWeight(1.0e-1);
299        }
300      }
301      if (doIdiot>0) {
302        // pick up number passes
303        nPasses=options.getExtraInfo(1);
304        if (nPasses>70)
305          info.setReduceIterations(6);
306      }
307      if (nPasses) {
308        doCrash=0;
309        info.crash(nPasses,model2->messageHandler(),model2->messagesPointer());
310        time2 = CoinCpuTime();
311        timeIdiot = time2-timeX;
312        handler_->message(CLP_INTERVAL_TIMING,messages_)
313          <<"Idiot Crash"<<timeIdiot<<time2-time1
314          <<CoinMessageEol;
315        timeX=time2;
316      }
317    }
318#endif
319    // ?
320    if (doCrash)
321      model2->crash(1000,1);
322    model2->primal(2);
323    time2 = CoinCpuTime();
324    timeCore = time2-timeX;
325    timeSimplex = timeCore;
326    handler_->message(CLP_INTERVAL_TIMING,messages_)
327      <<"Primal"<<timeCore<<time2-time1
328      <<CoinMessageEol;
329    timeX=time2;
330  } else if (method==ClpSolve::usePrimalorSprint) {
331    // Sprint
332    /*
333      This driver implements what I called Sprint when I introduced the idea
334      many years ago.  Cplex calls it "sifting" which I think is just as silly.
335      When I thought of this trivial idea
336      it reminded me of an LP code of the 60's called sprint which after
337      every factorization took a subset of the matrix into memory (all
338      64K words!) and then iterated very fast on that subset.  On the
339      problems of those days it did not work very well, but it worked very
340      well on aircrew scheduling problems where there were very large numbers
341      of columns all with the same flavor.
342    */
343   
344    /* The idea works best if you can get feasible easily.  To make it
345       more general we can add in costed slacks */
346   
347    int originalNumberColumns = model2->numberColumns();
348    int numberRows = model2->numberRows();
349   
350    // We will need arrays to choose variables.  These are too big but ..
351    double * weight = new double [numberRows+originalNumberColumns];
352    int * sort = new int [numberRows+originalNumberColumns];
353    int numberSort=0;
354    // We are going to add slacks to get feasible.
355    // initial list will just be artificials
356    // first we will set all variables as close to zero as possible
357    int iColumn;
358    const double * columnLower = model2->columnLower();
359    const double * columnUpper = model2->columnUpper();
360    double * columnSolution = model2->primalColumnSolution();
361   
362    for (iColumn=0;iColumn<originalNumberColumns;iColumn++) {
363      double value =0.0;
364      if (columnLower[iColumn]>0.0)
365        value = columnLower[iColumn];
366      else if (columnUpper[iColumn]<0.0)
367        value = columnUpper[iColumn];
368      columnSolution[iColumn]=value;
369    }
370    // now see what that does to row solution
371    double * rowSolution = model2->primalRowSolution();
372    memset (rowSolution,0,numberRows*sizeof(double));
373    model2->times(1.0,columnSolution,rowSolution);
374   
375    int * addStarts = new int [numberRows+1];
376    int * addRow = new int[numberRows];
377    double * addElement = new double[numberRows];
378    const double * lower = model2->rowLower();
379    const double * upper = model2->rowUpper();
380    addStarts[0]=0;
381    int numberArtificials=0;
382    double * addCost = new double [numberRows];
383    const double penalty=1.0e8;
384    int iRow;
385    for (iRow=0;iRow<numberRows;iRow++) {
386      if (lower[iRow]>rowSolution[iRow]) {
387        addRow[numberArtificials]=iRow;
388        addElement[numberArtificials]=1.0;
389        addCost[numberArtificials]=penalty;
390        numberArtificials++;
391        addStarts[numberArtificials]=numberArtificials;
392      } else if (upper[iRow]<rowSolution[iRow]) {
393        addRow[numberArtificials]=iRow;
394        addElement[numberArtificials]=-1.0;
395        addCost[numberArtificials]=penalty;
396        numberArtificials++;
397        addStarts[numberArtificials]=numberArtificials;
398      }
399    }
400    model2->addColumns(numberArtificials,NULL,NULL,addCost,
401                       addStarts,addRow,addElement);
402    delete [] addStarts;
403    delete [] addRow;
404    delete [] addElement;
405    delete [] addCost;
406    // look at rhs to see if to perturb
407    double largest=0.0;
408    double smallest = 1.0e30;
409    for (iRow=0;iRow<numberRows;iRow++) {
410      double value;
411      value = fabs(model2->rowLower_[iRow]);
412      if (value&&value<1.0e30) {
413        largest = max(largest,value);
414        smallest=min(smallest,value);
415      }
416      value = fabs(model2->rowUpper_[iRow]);
417      if (value&&value<1.0e30) {
418        largest = max(largest,value);
419        smallest=min(smallest,value);
420      }
421    }
422    double * saveLower = NULL;
423    double * saveUpper = NULL;
424    if (largest<2.01*smallest) {
425      // perturb - so switch off standard
426      model2->setPerturbation(100);
427      saveLower = new double[numberRows];
428      memcpy(saveLower,model2->rowLower_,numberRows*sizeof(double));
429      saveUpper = new double[numberRows];
430      memcpy(saveUpper,model2->rowUpper_,numberRows*sizeof(double));
431      double * lower = model2->rowLower();
432      double * upper = model2->rowUpper();
433      for (iRow=0;iRow<numberRows;iRow++) {
434        double lowerValue=lower[iRow], upperValue=upper[iRow];
435        double value = CoinDrand48();
436        if (upperValue>lowerValue+primalTolerance_) {
437          if (lowerValue>-1.0e20&&lowerValue)
438            lowerValue -= value * 1.0e-4*fabs(lowerValue); 
439          if (upperValue<1.0e20&&upperValue)
440            upperValue += value * 1.0e-4*fabs(upperValue); 
441        } else if (upperValue>0.0) {
442          upperValue -= value * 1.0e-4*fabs(lowerValue); 
443          lowerValue -= value * 1.0e-4*fabs(lowerValue); 
444        } else if (upperValue<0.0) {
445          upperValue += value * 1.0e-4*fabs(lowerValue); 
446          lowerValue += value * 1.0e-4*fabs(lowerValue); 
447        } else {
448        }
449        lower[iRow]=lowerValue;
450        upper[iRow]=upperValue;
451      }
452    }
453    int i;
454    // Set up initial list
455    if (numberArtificials) {
456      numberSort=numberArtificials;
457      for (i=0;i<numberSort;i++)
458        sort[i] = i+originalNumberColumns;
459    } else {
460      numberSort = min(numberRows_,numberColumns_);
461      for (i=0;i<numberSort;i++)
462        sort[i] = i;
463    }
464   
465    // redo as will have changed
466    columnLower = model2->columnLower();
467    columnUpper = model2->columnUpper();
468    int numberColumns = model2->numberColumns();
469    double * fullSolution = model2->primalColumnSolution();
470   
471    // Just do this number of passes
472    int maxPass=100;
473    if (doSprint>0)
474      maxPass=options.getExtraInfo(1);
475    int iPass;
476    double lastObjective=1.0e31;
477    // It will be safe to allow dense
478    model2->setInitialDenseFactorization(true);
479   
480    // Just take this number of columns in small problem
481    int smallNumberColumns = min(3*numberRows,numberColumns);
482    smallNumberColumns = max(smallNumberColumns,3000);
483    // We will be using all rows
484    int * whichRows = new int [numberRows];
485    for (int iRow=0;iRow<numberRows;iRow++)
486      whichRows[iRow]=iRow;
487    double originalOffset;
488    model2->getDblParam(ClpObjOffset,originalOffset);
489    int totalIterations=0;
490    for (iPass=0;iPass<maxPass;iPass++) {
491      //printf("Bug until submodel new version\n");
492      //CoinSort_2(sort,sort+numberSort,weight);
493      // Create small problem
494      ClpSimplex small(model2,numberRows,whichRows,numberSort,sort);
495      small.setPerturbation(model2->perturbation());
496      // now see what variables left out do to row solution
497      double * rowSolution = model2->primalRowSolution();
498      double * sumFixed = new double[numberRows];
499      memset (sumFixed,0,numberRows*sizeof(double));
500      int iRow,iColumn;
501      // zero out ones in small problem
502      for (iColumn=0;iColumn<numberSort;iColumn++) {
503        int kColumn = sort[iColumn];
504        fullSolution[kColumn]=0.0;
505      }
506      // Get objective offset
507      double offset=0.0;
508      const double * objective = model2->objective();
509      for (iColumn=0;iColumn<numberColumns_;iColumn++) 
510        offset += fullSolution[iColumn]*objective[iColumn];
511      small.setDblParam(ClpObjOffset,originalOffset-offset);
512      model2->times(1.0,fullSolution,sumFixed);
513     
514      double * lower = small.rowLower();
515      double * upper = small.rowUpper();
516      for (iRow=0;iRow<numberRows;iRow++) {
517        if (lower[iRow]>-1.0e50) 
518          lower[iRow] -= sumFixed[iRow];
519        if (upper[iRow]<1.0e50)
520          upper[iRow] -= sumFixed[iRow];
521        rowSolution[iRow] -= sumFixed[iRow];
522      }
523      delete [] sumFixed;
524      // Solve
525      if (interrupt)
526        currentModel = &small;
527      small.primal();
528      totalIterations += small.numberIterations();
529      // move solution back
530      const double * solution = small.primalColumnSolution();
531      for (iColumn=0;iColumn<numberSort;iColumn++) {
532        int kColumn = sort[iColumn];
533        model2->setColumnStatus(kColumn,small.getColumnStatus(iColumn));
534        fullSolution[kColumn]=solution[iColumn];
535      }
536      for (iRow=0;iRow<numberRows;iRow++) 
537        model2->setRowStatus(iRow,small.getRowStatus(iRow));
538      memcpy(model2->primalRowSolution(),small.primalRowSolution(),
539             numberRows*sizeof(double));
540      // get reduced cost for large problem
541      memcpy(weight,model2->objective(),numberColumns*sizeof(double));
542      model2->transposeTimes(-1.0,small.dualRowSolution(),weight);
543      int numberNegative=0;
544      double sumNegative = 0.0;
545      // now massage weight so all basic in plus good djs
546      for (iColumn=0;iColumn<numberColumns;iColumn++) {
547        double dj = weight[iColumn]*optimizationDirection_;
548        double value = fullSolution[iColumn];
549        if (model2->getColumnStatus(iColumn)==ClpSimplex::basic) 
550          dj = -1.0e50;
551        else if (dj<0.0&&value<columnUpper[iColumn])
552          dj = dj;
553        else if (dj>0.0&&value>columnLower[iColumn])
554          dj = -dj;
555        else if (columnUpper[iColumn]>columnLower[iColumn])
556          dj = fabs(dj);
557        else
558          dj = 1.0e50;
559        weight[iColumn] = dj;
560        if (dj<-dualTolerance_&&dj>-1.0e50) {
561          numberNegative++;
562          sumNegative -= dj;
563        }
564        sort[iColumn] = iColumn;
565      }
566      handler_->message(CLP_SPRINT,messages_)
567        <<iPass+1<<small.numberIterations()<<small.objectiveValue()<<sumNegative
568        <<numberNegative
569        <<CoinMessageEol;
570      if ((small.objectiveValue()>lastObjective-1.0e-7&&iPass>5)||
571          !small.numberIterations()||
572          iPass==maxPass-1||small.status()==3) {
573       
574        break; // finished
575      } else {
576        lastObjective = small.objectiveValue();
577        // sort
578        CoinSort_2(weight,weight+numberColumns,sort);
579        numberSort = smallNumberColumns;
580      }
581    }
582    if (interrupt) 
583      currentModel = model2;
584    for (i=0;i<numberArtificials;i++)
585      sort[i] = i + originalNumberColumns;
586    model2->deleteColumns(numberArtificials,sort);
587    delete [] weight;
588    delete [] sort;
589    delete [] whichRows;
590    if (saveLower) {
591      // unperturb
592      memcpy(model2->rowLower_,saveLower,numberRows*sizeof(double));
593      delete [] saveLower;
594      memcpy(model2->rowUpper_,saveUpper,numberRows*sizeof(double));
595      delete [] saveUpper;
596    }
597    model2->primal(1);
598    model2->setPerturbation(savePerturbation);
599    time2 = CoinCpuTime();
600    timeCore = time2-timeX;
601    timeSimplex = timeCore;
602    handler_->message(CLP_INTERVAL_TIMING,messages_)
603      <<"Sprint"<<timeCore<<time2-time1
604      <<CoinMessageEol;
605    timeX=time2;
606    model2->setNumberIterations(model2->numberIterations()+totalIterations);
607  } else {
608    assert (method!=ClpSolve::automatic); // later
609    time2=0.0;
610  }
611  if (saveMatrix) {
612    // delete and replace
613    delete model2->clpMatrix();
614    model2->replaceMatrix(saveMatrix);
615  }
616  numberIterations = model2->numberIterations();
617  finalStatus=model2->status();
618  if (presolve==ClpSolve::presolveOn) {
619    int saveLevel = logLevel();
620    setLogLevel(1);
621    pinfo.postsolve(true);
622    time2 = CoinCpuTime();
623    timePresolve += time2-timeX;
624    handler_->message(CLP_INTERVAL_TIMING,messages_)
625      <<"Postsolve"<<time2-timeX<<time2-time1
626      <<CoinMessageEol;
627    timeX=time2;
628    delete model2;
629    if (interrupt)
630      currentModel = this;
631    checkSolution();
632    setLogLevel(saveLevel);
633    if (finalStatus!=3&&(finalStatus||status()==-1)) {
634      int savePerturbation = perturbation();
635      setPerturbation(100);
636      primal(1);
637      setPerturbation(savePerturbation);
638      numberIterations += this->numberIterations();
639      finalStatus=status();
640      time2 = CoinCpuTime();
641      timeSimplex += time2-timeX;
642      handler_->message(CLP_INTERVAL_TIMING,messages_)
643      <<"Cleanup"<<time2-timeX<<time2-time1
644      <<CoinMessageEol;
645      timeX=time2;
646    }
647  }
648  setMaximumIterations(saveMaxIterations);
649  std::string statusMessage[]={"Unknown","Optimal","PrimalInfeasible","DualInfeasible","Stopped"};
650  assert (finalStatus>=-1&&finalStatus<=3);
651  handler_->message(CLP_TIMING,messages_)
652    <<statusMessage[finalStatus+1]<<objectiveValue()<<numberIterations<<time2-time1;
653  handler_->printing(presolve==ClpSolve::presolveOn)
654    <<timePresolve;
655  handler_->printing(timeIdiot)
656    <<timeIdiot;
657  handler_->message()<<CoinMessageEol;
658  if (interrupt) 
659    signal(SIGINT,saveSignal);
660  perturbation_=savePerturbation;
661  scalingFlag_=saveScaling;
662  return finalStatus;
663}
664// Default constructor
665ClpSolve::ClpSolve (  )
666{
667  method_ = useDual;
668  presolveType_=presolveOn;
669  numberPasses_=5;
670  for (int i=0;i<4;i++)
671    options_[i]=0;
672  for (int i=0;i<4;i++)
673    extraInfo_[i]=-1;
674}
675
676// Copy constructor.
677ClpSolve::ClpSolve(const ClpSolve & rhs)
678{
679  method_ = rhs.method_;
680  presolveType_=rhs.presolveType_;
681  numberPasses_=rhs.numberPasses_;
682  for (int i=0;i<4;i++)
683    options_[i]=rhs.options_[i];
684  for (int i=0;i<4;i++)
685    extraInfo_[i]=rhs.extraInfo_[i];
686}
687// Assignment operator. This copies the data
688ClpSolve & 
689ClpSolve::operator=(const ClpSolve & rhs)
690{
691  if (this != &rhs) {
692    method_ = rhs.method_;
693    presolveType_=rhs.presolveType_;
694    numberPasses_=rhs.numberPasses_;
695    for (int i=0;i<4;i++)
696      options_[i]=rhs.options_[i];
697    for (int i=0;i<4;i++)
698      extraInfo_[i]=rhs.extraInfo_[i];
699  }
700  return *this;
701
702}
703// Destructor
704ClpSolve::~ClpSolve (  )
705{
706}
707/*   which translation is:
708     which:
709     0 - startup in Dual  (nothing if basis exists).:
710             0 - no basis, 1 crash
711     1 - startup in Primal (nothing if basis exists):
712        0 - use initiative
713        1 - use crash
714        2 - use idiot and look at further info
715        3 - use sprint and look at further info
716        4 - use all slack
717        5 - use initiative but no idiot
718        6 - use initiative but no sprint
719        7 - use initiative but no crash
720        8 - do allslack or idiot
721        9 - do allslack or sprint
722     2 - interrupt handling - 0 yes, 1 no (for threadsafe)
723     3 - whether to make +- 1matrix - 0 yes, 1 no
724*/
725void 
726ClpSolve::setSpecialOption(int which,int value,int extraInfo)
727{
728  options_[which]=value;
729  extraInfo_[which]=extraInfo;
730}
731int 
732ClpSolve::getSpecialOption(int which) const
733{
734  return options_[which];
735}
736
737// Solve types
738void 
739ClpSolve::setSolveType(SolveType method, int extraInfo)
740{
741  method_=method;
742}
743
744ClpSolve::SolveType
745ClpSolve::getSolveType()
746{
747  return method_;
748}
749
750// Presolve types
751void 
752ClpSolve::setPresolveType(PresolveType amount, int extraInfo)
753{
754  presolveType_=amount;
755  numberPasses_=extraInfo;
756}
757ClpSolve::PresolveType
758ClpSolve::getPresolveType()
759{
760  return presolveType_;
761}
762// Extra info for idiot (or sprint)
763int 
764ClpSolve::getExtraInfo(int which) const
765{
766  return extraInfo_[which];
767}
768int 
769ClpSolve::getPresolvePasses() const
770{
771  return numberPasses_;
772}
Note: See TracBrowser for help on using the repository browser.