source: branches/pre/ClpSolve.cpp @ 220

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

Stuff

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