source: trunk/Cbc/src/CbcMipStartIO.cpp

Last change on this file was 2632, checked in by unxusr, 3 months ago

close file on error

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1#include <cstdlib>
2#include <cmath>
3#include <ctime>
4#include <cassert>
5#include <cstdio>
6#include <cstring>
7#include <algorithm>
8#include <vector>
9#include <string>
10#include <map>
11#include <OsiSolverInterface.hpp>
12#include "CbcMessage.hpp"
13#include "CbcHeuristic.hpp"
14#include <CbcModel.hpp>
15#include "CbcMipStartIO.hpp"
16#include "CbcSOS.hpp"
17#include "CoinTime.hpp"
18
19using namespace std;
20
21bool isNumericStr(const char *str)
22{
23  const size_t l = strlen(str);
24
25  for (size_t i = 0; i < l; ++i)
26    if (!(isdigit(str[i]) || (str[i] == '.') || (str[i] == '-') || (str[i] == '+') || (str[i] == 'e')))
27      return false;
28
29  return true;
30}
31
32int readMIPStart(CbcModel *model, const char *fileName,
33  vector< pair< string, double > > &colValues,
34  double & /*solObj*/)
35{
36#define STR_SIZE 256
37  FILE *f = fopen(fileName, "r");
38  if (!f)
39    return 1;
40  char line[STR_SIZE];
41
42  int nLine = 0;
43  char printLine[STR_SIZE];
44  while (fgets(line, STR_SIZE, f)) {
45    ++nLine;
46    char col[4][STR_SIZE];
47    int nread = sscanf(line, "%s %s %s %s", col[0], col[1], col[2], col[3]);
48    if (!nread)
49      continue;
50    /* line with variable value */
51    if (strlen(col[0]) && isdigit(col[0][0]) && (nread >= 3)) {
52      if (!isNumericStr(col[0])) {
53        sprintf(printLine, "Reading: %s, line %d - first column in mipstart file should be numeric, ignoring.", fileName, nLine);
54        model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol;
55        continue;
56      }
57      if (!isNumericStr(col[2])) {
58        sprintf(printLine, "Reading: %s, line %d - Third column in mipstart file should be numeric, ignoring.", fileName, nLine);
59        model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol;
60        continue;
61      }
62
63      char *name = col[1];
64      double value = atof(col[2]);
65
66      colValues.push_back(pair< string, double >(string(name), value));
67    }
68  }
69
70  if (colValues.size()) {
71    sprintf(printLine, "MIPStart values read for %d variables.", static_cast< int >(colValues.size()));
72    model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol;
73    if (colValues.size() < model->getNumCols()) {
74      int numberColumns = model->getNumCols();
75      OsiSolverInterface *solver = model->solver();
76      vector< pair< string, double > > fullValues;
77      /* for fast search of column names */
78      map< string, int > colIdx;
79      for (int i = 0; i < numberColumns; i++) {
80        fullValues.push_back(pair< string, double >(solver->getColName(i), 0.0));
81        colIdx[solver->getColName(i)] = i;
82      }
83      for (int i = 0; (i < static_cast< int >(colValues.size())); ++i) {
84        map< string, int >::const_iterator mIt = colIdx.find(colValues[i].first);
85        if (mIt != colIdx.end()) {
86          const int idx = mIt->second;
87          double v = colValues[i].second;
88          fullValues[idx].second = v;
89        }
90      }
91      colValues = fullValues;
92    }
93  } else {
94    sprintf(printLine, "No mipstart solution read from %s", fileName);
95    model->messageHandler()->message(CBC_GENERAL, model->messages()) << printLine << CoinMessageEol;
96    fclose(f);
97    return 1;
98  }
99
100  fclose(f);
101  return 0;
102}
103
104int computeCompleteSolution(CbcModel *model,
105  const vector< string > colNames,
106  const std::vector< std::pair< std::string, double > > &colValues,
107                            double *sol, double &obj, int extraActions)
108{
109  if (!model->getNumCols())
110    return 0;
111
112  int status = 0;
113  double compObj = COIN_DBL_MAX;
114  bool foundIntegerSol = false;
115  OsiSolverInterface *lp = model->solver()->clone();
116  map< string, int > colIdx;
117  assert((static_cast< int >(colNames.size())) == lp->getNumCols());
118  /* for fast search of column names */
119  for (int i = 0; (i < static_cast< int >(colNames.size())); ++i)
120    colIdx[colNames[i]] = i;
121
122  char printLine[STR_SIZE];
123  int fixed = 0;
124  int notFound = 0;
125  char colNotFound[256] = "";
126  int nContinuousFixed = 0;
127
128#ifndef JUST_FIX_INTEGER
129#define JUST_FIX_INTEGER 0
130#endif
131
132#if JUST_FIX_INTEGER > 1
133  // all not mentioned are at zero
134  for (int i = 0; (i < lp->getNumCols()); ++i) {
135    if (lp->isInteger(i))
136      lp->setColBounds(i, 0.0, 0.0);
137  }
138#endif
139  if (extraActions) {
140    const double * objective = lp->getObjCoefficients();
141    const double * lower = lp->getColLower();
142    const double * upper = lp->getColUpper();
143    for (int i = 0; (i < lp->getNumCols()); ++i) {
144      if (lp->isInteger(i)) {
145        double objValue = objective[i];
146        double lowerValue = lower[i];
147        double upperValue = upper[i];
148        switch (extraActions) {
149        case 1:
150          lp->setColBounds(i, lowerValue, lowerValue);
151          break;
152        case 2:
153          lp->setColBounds(i, upperValue, upperValue);
154          break;
155        case 3:
156          lp->setColBounds(i, lowerValue, lowerValue);
157          if (objValue<0.0)
158            lp->setColBounds(i, upperValue, upperValue);
159          break;
160        case 4:
161          lp->setColBounds(i, upperValue, upperValue);
162          if (objValue>0.0)
163            lp->setColBounds(i, lowerValue, lowerValue);
164          break;
165        case 5:
166          lp->setColBounds(i, lowerValue, lowerValue);
167          if (objValue>0.0)
168            lp->setColBounds(i, upperValue, upperValue);
169          break;
170        case 6:
171          lp->setColBounds(i, upperValue, upperValue);
172          if (objValue<0.0)
173            lp->setColBounds(i, lowerValue, lowerValue);
174          break;
175        }
176      }
177    }
178  }
179  for (int i = 0; (i < static_cast< int >(colValues.size())); ++i) {
180    map< string, int >::const_iterator mIt = colIdx.find(colValues[i].first);
181    if (mIt == colIdx.end()) {
182      if (!notFound)
183        strcpy(colNotFound, colValues[i].first.c_str());
184      notFound++;
185    } else {
186      const int idx = mIt->second;
187      double v = colValues[i].second;
188#if JUST_FIX_INTEGER
189      if (!lp->isInteger(idx))
190        continue;
191#endif
192      if (fabs(v) < 1e-8)
193        v = 0.0;
194      if (lp->isInteger(idx)) // just to avoid small
195        v = floor(v + 0.5); // fractional garbage
196      else
197        nContinuousFixed++;
198
199      lp->setColBounds(idx, v, v);
200      ++fixed;
201    }
202  }
203
204  if (extraActions)
205    fixed = lp->getNumIntegers();
206  if (!fixed) {
207    model->messageHandler()->message(CBC_GENERAL, model->messages())
208      << "Warning: MIPstart solution is not valid, column names do not match, ignoring it."
209      << CoinMessageEol;
210    goto TERMINATE;
211  }
212
213  if (notFound >= ((static_cast< double >(colNames.size())) * 0.5)) {
214    sprintf(printLine, "Warning: %d column names were not found (e.g. %s) while filling solution.", notFound, colNotFound);
215    model->messageHandler()->message(CBC_GENERAL, model->messages())
216      << printLine << CoinMessageEol;
217  }
218#if JUST_FIX_INTEGER
219  lp->setHintParam(OsiDoPresolveInInitial, true, OsiHintDo);
220#endif
221  lp->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
222  lp->initialSolve();
223
224  if ((lp->isProvenPrimalInfeasible()) || (lp->isProvenDualInfeasible())) {
225    if (nContinuousFixed) {
226      model->messageHandler()->message(CBC_GENERAL, model->messages())
227        << "Trying just fixing integer variables (and fixingish SOS)." << CoinMessageEol;
228      int numberColumns = lp->getNumCols();
229      const double *oldLower = model->solver()->getColLower();
230      const double *oldUpper = model->solver()->getColUpper();
231      double *savedSol = CoinCopyOfArray(lp->getColLower(), numberColumns);
232      for (int i = 0; i < numberColumns; ++i) {
233        if (!lp->isInteger(i)) {
234          lp->setColLower(i, oldLower[i]);
235          lp->setColUpper(i, oldUpper[i]);
236        }
237      }
238      // but look at SOS
239      int numberObjects = model->numberObjects();
240      for (int i = 0; i < numberObjects; i++) {
241        const CbcSOS *object = dynamic_cast< const CbcSOS * >(model->object(i));
242        if (object) {
243          int n = object->numberMembers();
244          const int *members = object->members();
245          int sosType = object->sosType();
246          if (sosType == 1) {
247            // non zero can take any value - others zero
248            int iColumn = -1;
249            for (int j = 0; j < n; j++) {
250              int jColumn = members[j];
251              if (savedSol[jColumn])
252                iColumn = jColumn;
253            }
254            for (int j = 0; j < n; j++) {
255              int jColumn = members[j];
256              if (jColumn != iColumn) {
257                lp->setColLower(jColumn, 0.0);
258                lp->setColUpper(jColumn, 0.0);
259              }
260            }
261          } else if (sosType == 2) {
262            // SOS 2 - make a guess if just one nonzero
263            int jA = -1;
264            int jB = -1;
265            for (int j = 0; j < n; j++) {
266              int jColumn = members[j];
267              if (savedSol[jColumn]) {
268                if (jA == -1)
269                  jA = j;
270                jB = j;
271              }
272            }
273            if (jB > jA + 1) {
274              jB = jA + 1;
275            } else if (jA == jB) {
276              if (jA == n - 1)
277                jA--;
278              else
279                jB++;
280            }
281            for (int j = 0; j < n; j++) {
282              if (j != jA && j != jB) {
283                int jColumn = members[j];
284                lp->setColLower(jColumn, 0.0);
285                lp->setColUpper(jColumn, 0.0);
286              }
287            }
288          }
289        }
290      }
291      delete[] savedSol;
292      lp->initialSolve();
293    } else {
294      model->messageHandler()->message(CBC_GENERAL, model->messages())
295        << "Fixing only non-zero variables." << CoinMessageEol;
296      /* unfix all variables which are zero */
297      int notZeroAnymore = 0;
298      for (int i = 0; (i < lp->getNumCols()); ++i)
299        if (((fabs(lp->getColLower()[i])) <= 1e-8) && (fabs(lp->getColLower()[i] - lp->getColUpper()[i]) <= 1e-8)) {
300          const double *oldLower = model->solver()->getColLower();
301          const double *oldUpper = model->solver()->getColUpper();
302          lp->setColLower(i, oldLower[i]);
303          lp->setColUpper(i, oldUpper[i]);
304          notZeroAnymore++;
305        }
306      if (notZeroAnymore)
307        lp->initialSolve();
308    }
309  }
310
311  if (!lp->isProvenOptimal()) {
312    model->messageHandler()->message(CBC_GENERAL, model->messages())
313      << "Warning: mipstart values could not be used to build a solution." << CoinMessageEol;
314    status = 1;
315    goto TERMINATE;
316  }
317
318  /* some additional effort is needed to provide an integer solution */
319  if (lp->getFractionalIndices().size() > 0) {
320    sprintf(printLine, "MIPStart solution provided values for %d of %d integer variables, %d variables are still fractional.", fixed, lp->getNumIntegers(), static_cast< int >(lp->getFractionalIndices().size()));
321    model->messageHandler()->message(CBC_GENERAL, model->messages())
322      << printLine << CoinMessageEol;
323    double start = CoinCpuTime();
324#if 1
325    CbcSerendipity heuristic(*model);
326    heuristic.setFractionSmall(2.0);
327    heuristic.setFeasibilityPumpOptions(1008013);
328    int returnCode = heuristic.smallBranchAndBound(lp,
329      1000, sol,
330      compObj,
331      model->getCutoff(),
332      "ReduceInMIPStart");
333    if ((returnCode & 1) != 0) {
334      sprintf(printLine, "Mini branch and bound defined values for remaining variables in %.2f seconds.",
335        CoinCpuTime() - start);
336      model->messageHandler()->message(CBC_GENERAL, model->messages())
337        << printLine << CoinMessageEol;
338      foundIntegerSol = true;
339      obj = compObj;
340    }
341#else
342    CbcModel babModel(*lp);
343    lp->writeLp("lessFix");
344    babModel.setLogLevel(2);
345    babModel.setMaximumNodes(1000);
346    babModel.setMaximumSeconds(60);
347    babModel.branchAndBound();
348    if (babModel.bestSolution()) {
349      sprintf(printLine, "Mini branch and bound defined values for remaining variables in %.2f seconds.",
350        CoinCpuTime() - start);
351      model->messageHandler()->message(CBC_GENERAL, model->messages())
352        << printLine << CoinMessageEol;
353      copy(babModel.bestSolution(), babModel.bestSolution() + babModel.getNumCols(), sol);
354      foundIntegerSol = true;
355      obj = compObj = babModel.getObjValue();
356    }
357#endif
358    else {
359      model->messageHandler()->message(CBC_GENERAL, model->messages())
360        << "Warning: mipstart values could not be used to build a solution." << CoinMessageEol;
361      status = 1;
362      goto TERMINATE;
363    }
364  } else {
365    foundIntegerSol = true;
366    obj = compObj = lp->getObjValue();
367    copy(lp->getColSolution(), lp->getColSolution() + lp->getNumCols(), sol);
368  }
369
370  if (foundIntegerSol) {
371    sprintf(printLine, "MIPStart provided solution with cost %g", compObj);
372    model->messageHandler()->message(CBC_GENERAL, model->messages())
373      << printLine << CoinMessageEol;
374#if 0
375      {
376        int numberColumns=lp->getNumCols();
377        double largestInfeasibility = 0.0;
378        double primalTolerance ;
379        double offset;
380        lp->getDblParam(OsiObjOffset, offset);
381        lp->getDblParam(OsiPrimalTolerance, primalTolerance) ;
382        const double *objective = lp->getObjCoefficients() ;
383        const double * rowLower = lp->getRowLower() ;
384        const double * rowUpper = lp->getRowUpper() ;
385        const double * columnLower = lp->getColLower() ;
386        const double * columnUpper = lp->getColUpper() ;
387        int numberRows = lp->getNumRows() ;
388        double *rowActivity = new double[numberRows] ;
389        memset(rowActivity, 0, numberRows*sizeof(double)) ;
390        double *rowSum = new double[numberRows] ;
391        memset(rowSum, 0, numberRows*sizeof(double)) ;
392        const double * element = lp->getMatrixByCol()->getElements();
393        const int * row = lp->getMatrixByCol()->getIndices();
394        const CoinBigIndex * columnStart = lp->getMatrixByCol()->getVectorStarts();
395        const int * columnLength = lp->getMatrixByCol()->getVectorLengths();
396        const CoinPackedMatrix * rowCopy = lp->getMatrixByRow();
397        const int * column = rowCopy->getIndices();
398        const int * rowLength = rowCopy->getVectorLengths();
399        const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
400        const double * elementByRow = rowCopy->getElements();
401        double objValue=-offset;
402        for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
403          double value = sol[iColumn];
404          if (lp->isInteger(iColumn))
405            assert (fabs(value-floor(value+0.5))<1.0e-6);
406          objValue += value*objective[iColumn];
407          if (value>columnUpper[iColumn]) {
408            if (value-columnUpper[iColumn]>1.0e-8)
409              printf("column %d has value %.12g above %.12g\n",iColumn,value,columnUpper[iColumn]);
410            value=columnUpper[iColumn];
411          } else if (value<columnLower[iColumn]) {
412            if (value-columnLower[iColumn]<-1.0e-8)
413              printf("column %d has value %.12g below %.12g\n",iColumn,value,columnLower[iColumn]);
414            value=columnLower[iColumn];
415          }
416          if (value) {
417            CoinBigIndex start = columnStart[iColumn];
418            CoinBigIndex end = start + columnLength[iColumn];
419            for (CoinBigIndex j = start; j < end; j++) {
420              int iRow = row[j];
421              if (fabs(value)<1.0e-6&&fabs(value*element[j])>1.0e-5)
422                printf("Column %d row %d value %.8g element %g %s\n",
423                       iColumn,iRow,value,element[j],lp->isInteger(iColumn) ? "integer" : "");
424              rowActivity[iRow] += value * element[j];
425              rowSum[iRow] += fabs(value * element[j]);
426            }
427          }
428        }
429        for (int i = 0 ; i < numberRows ; i++) {
430#if 0 //def CLP_INVESTIGATE
431          double inf;
432          inf = rowLower[i] - rowActivity[i];
433          if (inf > primalTolerance)
434            printf("Row %d inf %g sum %g %g <= %g <= %g\n",
435                   i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
436          inf = rowActivity[i] - rowUpper[i];
437          if (inf > primalTolerance)
438            printf("Row %d inf %g sum %g %g <= %g <= %g\n",
439                   i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
440#endif
441          double infeasibility = CoinMax(rowActivity[i]-rowUpper[i],
442                                         rowLower[i]-rowActivity[i]);
443          // but allow for errors
444          double factor = CoinMax(1.0,rowSum[i]*1.0e-3);
445          if (infeasibility>largestInfeasibility*factor) {
446            largestInfeasibility = infeasibility/factor;
447            printf("Cinf of %g on row %d sum %g scaled %g\n",
448                   infeasibility,i,rowSum[i],largestInfeasibility);
449            if (infeasibility>1.0e10) {
450              for (CoinBigIndex j=rowStart[i];
451                   j<rowStart[i]+rowLength[i];j++) {
452                printf("col %d element %g\n",
453                       column[j],elementByRow[j]);
454              }
455            }
456          }
457        }
458        delete [] rowActivity ;
459        delete [] rowSum;
460        if (largestInfeasibility > 10.0*primalTolerance)
461          printf("Clargest infeasibility is %g - obj %g\n", largestInfeasibility,objValue);
462        else
463          printf("Cfeasible (%g) - obj %g\n", largestInfeasibility,objValue);
464      }
465#endif
466    for (int i = 0; (i < lp->getNumCols()); ++i) {
467#if 0
468         if (sol[i]<1e-8)
469            sol[i] = 0.0;
470         else
471            if (lp->isInteger(i))
472               sol[i] = floor( sol[i]+0.5 );
473#else
474      if (lp->isInteger(i)) {
475        //if (fabs(sol[i] - floor( sol[i]+0.5 ))>1.0e-8)
476        //printf("bad sol for %d - %.12g\n",i,sol[i]);
477        sol[i] = floor(sol[i] + 0.5);
478      }
479#endif
480    }
481#if 0
482      {
483        int numberColumns=lp->getNumCols();
484        double largestInfeasibility = 0.0;
485        double primalTolerance ;
486        double offset;
487        lp->getDblParam(OsiObjOffset, offset);
488        lp->getDblParam(OsiPrimalTolerance, primalTolerance) ;
489        const double *objective = lp->getObjCoefficients() ;
490        const double * rowLower = lp->getRowLower() ;
491        const double * rowUpper = lp->getRowUpper() ;
492        const double * columnLower = lp->getColLower() ;
493        const double * columnUpper = lp->getColUpper() ;
494        int numberRows = lp->getNumRows() ;
495        double *rowActivity = new double[numberRows] ;
496        memset(rowActivity, 0, numberRows*sizeof(double)) ;
497        double *rowSum = new double[numberRows] ;
498        memset(rowSum, 0, numberRows*sizeof(double)) ;
499        const double * element = lp->getMatrixByCol()->getElements();
500        const int * row = lp->getMatrixByCol()->getIndices();
501        const CoinBigIndex * columnStart = lp->getMatrixByCol()->getVectorStarts();
502        const int * columnLength = lp->getMatrixByCol()->getVectorLengths();
503        const CoinPackedMatrix * rowCopy = lp->getMatrixByRow();
504        const int * column = rowCopy->getIndices();
505        const int * rowLength = rowCopy->getVectorLengths();
506        const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
507        const double * elementByRow = rowCopy->getElements();
508        double objValue=-offset;
509        for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
510          double value = sol[iColumn];
511          if (lp->isInteger(iColumn))
512            assert (fabs(value-floor(value+0.5))<1.0e-6);
513          objValue += value*objective[iColumn];
514          if (value>columnUpper[iColumn]) {
515            if (value-columnUpper[iColumn]>1.0e-8)
516              printf("column %d has value %.12g above %.12g\n",iColumn,value,columnUpper[iColumn]);
517            value=columnUpper[iColumn];
518          } else if (value<columnLower[iColumn]) {
519            if (value-columnLower[iColumn]<-1.0e-8)
520              printf("column %d has value %.12g below %.12g\n",iColumn,value,columnLower[iColumn]);
521            value=columnLower[iColumn];
522          }
523          if (value) {
524            CoinBigIndex start = columnStart[iColumn];
525            CoinBigIndex end = start + columnLength[iColumn];
526            for (CoinBigIndex j = start; j < end; j++) {
527              int iRow = row[j];
528              rowActivity[iRow] += value * element[j];
529              rowSum[iRow] += fabs(value * element[j]);
530            }
531          }
532        }
533        for (int i = 0 ; i < numberRows ; i++) {
534#if 0 //def CLP_INVESTIGATE
535          double inf;
536          inf = rowLower[i] - rowActivity[i];
537          if (inf > primalTolerance)
538            printf("Row %d inf %g sum %g %g <= %g <= %g\n",
539                   i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
540          inf = rowActivity[i] - rowUpper[i];
541          if (inf > primalTolerance)
542            printf("Row %d inf %g sum %g %g <= %g <= %g\n",
543                   i, inf, rowSum[i], rowLower[i], rowActivity[i], rowUpper[i]);
544#endif
545          double infeasibility = CoinMax(rowActivity[i]-rowUpper[i],
546                                         rowLower[i]-rowActivity[i]);
547          // but allow for errors
548          double factor = CoinMax(1.0,rowSum[i]*1.0e-3);
549          if (infeasibility>largestInfeasibility*factor) {
550            largestInfeasibility = infeasibility/factor;
551            printf("Dinf of %g on row %d sum %g scaled %g\n",
552                   infeasibility,i,rowSum[i],largestInfeasibility);
553            if (infeasibility>1.0e10) {
554              for (CoinBigIndex j=rowStart[i];
555                   j<rowStart[i]+rowLength[i];j++) {
556                printf("col %d element %g\n",
557                       column[j],elementByRow[j]);
558              }
559            }
560          }
561        }
562        delete [] rowActivity ;
563        delete [] rowSum;
564        if (largestInfeasibility > 10.0*primalTolerance)
565          printf("Dlargest infeasibility is %g - obj %g\n", largestInfeasibility,objValue);
566        else
567          printf("Dfeasible (%g) - obj %g\n", largestInfeasibility,objValue);
568      }
569#endif
570#if JUST_FIX_INTEGER
571    const double *oldLower = model->solver()->getColLower();
572    const double *oldUpper = model->solver()->getColUpper();
573    const double *dj = lp->getReducedCost();
574    int nNaturalLB = 0;
575    int nMaybeLB = 0;
576    int nForcedLB = 0;
577    int nNaturalUB = 0;
578    int nMaybeUB = 0;
579    int nForcedUB = 0;
580    int nOther = 0;
581    for (int i = 0; i < lp->getNumCols(); ++i) {
582      if (lp->isInteger(i)) {
583        if (sol[i] == oldLower[i]) {
584          if (dj[i] > 1.0e-5)
585            nNaturalLB++;
586          else if (dj[i] < -1.0e-5)
587            nForcedLB++;
588          else
589            nMaybeLB++;
590        } else if (sol[i] == oldUpper[i]) {
591          if (dj[i] < -1.0e-5)
592            nNaturalUB++;
593          else if (dj[i] > 1.0e-5)
594            nForcedUB++;
595          else
596            nMaybeUB++;
597        } else {
598          nOther++;
599        }
600      }
601    }
602    printf("%d other, LB %d natural, %d neutral, %d forced, UB %d natural, %d neutral, %d forced\n",
603      nOther, nNaturalLB, nMaybeLB, nForcedLB,
604      nNaturalUB, nMaybeUB, nForcedUB = 0);
605#endif
606  }
607
608TERMINATE:
609  delete lp;
610  return status;
611}
612#undef STR_SIZE
613
614/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
615*/
Note: See TracBrowser for help on using the repository browser.