source: trunk/ClpNonLinearCost.cpp @ 159

Last change on this file since 159 was 159, checked in by forrest, 17 years ago

Still not very good

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.8 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3
4#include "CoinPragma.hpp"
5#include <iostream>
6
7#include "CoinIndexedVector.hpp"
8
9#include "ClpNonLinearCost.hpp"
10#include "ClpSimplex.hpp"
11
12//#############################################################################
13// Constructors / Destructor / Assignment
14//#############################################################################
15
16//-------------------------------------------------------------------
17// Default Constructor
18//-------------------------------------------------------------------
19ClpNonLinearCost::ClpNonLinearCost () :
20  changeCost_(0.0),
21  largestInfeasibility_(0.0),
22  sumInfeasibilities_(0.0),
23  numberRows_(0),
24  numberColumns_(0),
25  start_(NULL),
26  whichRange_(NULL),
27  offset_(NULL),
28  lower_(NULL),
29  cost_(NULL),
30  model_(NULL),
31  infeasible_(NULL),
32  numberInfeasibilities_(-1),
33  convex_(true)
34{
35
36}
37/* Constructor from simplex.
38   This will just set up wasteful arrays for linear, but
39   later may do dual analysis and even finding duplicate columns
40*/
41ClpNonLinearCost::ClpNonLinearCost ( ClpSimplex * model)
42{
43  model_ = model;
44  numberRows_ = model_->numberRows();
45  numberColumns_ = model_->numberColumns();
46  int numberTotal = numberRows_+numberColumns_;
47  convex_ = true;
48  start_ = new int [numberTotal+1];
49  whichRange_ = new int [numberTotal];
50  offset_ = new int [numberTotal];
51  memset(offset_,0,numberTotal*sizeof(int));
52
53  numberInfeasibilities_=0;
54  changeCost_=0.0;
55  double infeasibilityCost = model_->infeasibilityCost();
56  sumInfeasibilities_=0.0;
57  largestInfeasibility_=0.0;
58
59  // First see how much space we need
60  int put=0;
61
62  int iSequence;
63  double * upper = model_->upperRegion();
64  double * lower = model_->lowerRegion();
65  double * cost = model_->costRegion();
66
67  for (iSequence=0;iSequence<numberTotal;iSequence++) {
68    if (upper[iSequence]<1.0e20)
69      put++;
70    put += 3;
71  }
72
73  lower_ = new double [put];
74  cost_ = new double [put];
75  infeasible_ = new unsigned int[(put+31)>>5];
76  memset(infeasible_,0,((put+31)>>5)*sizeof(unsigned int));
77
78  put=0;
79
80  start_[0]=0;
81
82  for (iSequence=0;iSequence<numberTotal;iSequence++) {
83
84    lower_[put] = -COIN_DBL_MAX;
85    setInfeasible(put,true);
86
87    cost_[put++] = cost[iSequence]-infeasibilityCost;
88    whichRange_[iSequence]=put;
89    lower_[put] = lower[iSequence];
90    cost_[put++] = cost[iSequence];
91    lower_[put] = upper[iSequence];
92    cost_[put++] = cost[iSequence]+infeasibilityCost;
93    if (upper[iSequence]<1.0e20) {
94      lower_[put] = COIN_DBL_MAX;
95      setInfeasible(put-1,true);
96      cost_[put++] = 1.0e50;
97    }
98    start_[iSequence+1]=put;
99  }
100
101}
102ClpNonLinearCost::ClpNonLinearCost(ClpSimplex * model,const int * starts,
103                   const double * lowerNon, const double * costNon)
104{
105
106  // what about scaling? - only try without it initially
107  assert(!model->scalingFlag());
108  model_ = model;
109  numberRows_ = model_->numberRows();
110  numberColumns_ = model_->numberColumns();
111  int numberTotal = numberRows_+numberColumns_;
112  convex_ = true;
113  start_ = new int [numberTotal+1];
114  whichRange_ = new int [numberTotal];
115  offset_ = new int [numberTotal];
116  memset(offset_,0,numberTotal*sizeof(int));
117 
118  double whichWay = model_->optimizationDirection();
119  printf("Direction %g\n",whichWay);
120
121  numberInfeasibilities_=0;
122  changeCost_=0.0;
123  double infeasibilityCost = model_->infeasibilityCost();
124  largestInfeasibility_=0.0;
125  sumInfeasibilities_=0.0;
126
127  int iSequence;
128  assert (!model_->rowObjective());
129  double * cost = model_->objective();
130
131  // First see how much space we need
132  // Also set up feasible bounds
133  int put=starts[numberColumns_];
134
135  double * columnUpper = model_->columnUpper();
136  double * columnLower = model_->columnLower();
137  for (iSequence=0;iSequence<numberColumns_;iSequence++) {
138    if (columnLower[iSequence]>-1.0e20)
139      put++;
140    if (columnUpper[iSequence]<1.0e20)
141      put++;
142  }
143
144  double * rowUpper = model_->rowUpper();
145  double * rowLower = model_->rowLower();
146  for (iSequence=0;iSequence<numberRows_;iSequence++) {
147    if (rowLower[iSequence]>-1.0e20)
148      put++;
149    if (rowUpper[iSequence]<1.0e20)
150      put++;
151    put +=2;
152  }
153  lower_ = new double [put];
154  cost_ = new double [put];
155  infeasible_ = new unsigned int[(put+31)>>5];
156  memset(infeasible_,0,((put+31)>>5)*sizeof(unsigned int));
157
158  // now fill in
159  put=0;
160
161  start_[0]=0;
162  for (iSequence=0;iSequence<numberTotal;iSequence++) {
163    lower_[put] = -COIN_DBL_MAX;
164    whichRange_[iSequence]=put+1;
165    double thisCost;
166    double lowerValue;
167    double upperValue;
168    if (iSequence>=numberColumns_) {
169      // rows
170      lowerValue = rowLower[iSequence-numberColumns_];
171      upperValue = rowUpper[iSequence-numberColumns_];
172      if (lowerValue>-1.0e30) {
173        cost_[put++] = -infeasibilityCost;
174        lower_[put] = lowerValue;
175      }
176      cost_[put++] = 0.0;
177      thisCost = 0.0;
178    } else {
179      // columns - move costs and see if convex
180      lowerValue = columnLower[iSequence];
181      upperValue = columnUpper[iSequence];
182      if (lowerValue>-1.0e30) {
183        cost_[put++] = whichWay*cost[iSequence]-infeasibilityCost;
184        lower_[put] = lowerValue;
185      }
186      int iIndex = starts[iSequence];
187      int end = starts[iSequence+1];
188      assert (fabs(columnLower[iSequence]-lowerNon[iIndex])<1.0e-8);
189      thisCost = -COIN_DBL_MAX;
190      for (;iIndex<end;iIndex++) {
191        if (lowerNon[iIndex]<columnUpper[iSequence]-1.0e-8) {
192          lower_[put] = lowerNon[iIndex];
193          cost_[put++] = whichWay*costNon[iIndex];
194          // check convexity
195          if (whichWay*costNon[iIndex]<thisCost-1.0e-12)
196            convex_ = false;
197          thisCost = whichWay*costNon[iIndex];
198        } else {
199          break;
200        }
201      }
202    }
203    lower_[put] = upperValue;
204    cost_[put++] = thisCost+infeasibilityCost;
205    if (upperValue<1.0e20) {
206      lower_[put] = COIN_DBL_MAX;
207      setInfeasible(put-1,true);
208      cost_[put++] = 1.0e50;
209    }
210    int iFirst = start_[iSequence];
211    if (lower_[iFirst] != -COIN_DBL_MAX) {
212      setInfeasible(iFirst,true);
213      whichRange_[iSequence]=iFirst+1;
214    } else {
215      whichRange_[iSequence]=iFirst;
216    }
217    start_[iSequence+1]=put;
218  }
219  // can't handle non-convex at present
220  assert(convex_);
221}
222
223//-------------------------------------------------------------------
224// Copy constructor
225//-------------------------------------------------------------------
226ClpNonLinearCost::ClpNonLinearCost (const ClpNonLinearCost & rhs) :
227  changeCost_(0.0),
228  largestInfeasibility_(0.0),
229  sumInfeasibilities_(0.0),
230  numberRows_(rhs.numberRows_),
231  numberColumns_(rhs.numberColumns_),
232  start_(NULL),
233  whichRange_(NULL),
234  offset_(NULL),
235  lower_(NULL),
236  cost_(NULL),
237  model_(NULL),
238  infeasible_(NULL),
239  numberInfeasibilities_(-1),
240  convex_(true)
241{ 
242  if (numberRows_) {
243    int numberTotal = numberRows_+numberColumns_;
244    start_ = new int [numberTotal+1];
245    memcpy(start_,rhs.start_,(numberTotal+1)*sizeof(int));
246    whichRange_ = new int [numberTotal];
247    memcpy(whichRange_,rhs.whichRange_,numberTotal*sizeof(int));
248    offset_ = new int [numberTotal];
249    memcpy(offset_,rhs.offset_,numberTotal*sizeof(int));
250    int numberEntries = start_[numberTotal];
251    lower_ = new double [numberEntries];
252    memcpy(lower_,rhs.lower_,numberEntries*sizeof(double));
253    cost_ = new double [numberEntries];
254    memcpy(cost_,rhs.cost_,numberEntries*sizeof(double));
255    model_ = rhs.model_;
256    numberInfeasibilities_=rhs.numberInfeasibilities_;
257    changeCost_ = rhs.changeCost_;
258    largestInfeasibility_ = rhs.largestInfeasibility_;
259    sumInfeasibilities_ = rhs.sumInfeasibilities_;
260    convex_ = rhs.convex_;
261    infeasible_ = new unsigned int[(numberEntries+31)>>5];
262    memcpy(infeasible_,rhs.infeasible_,
263           ((numberEntries+31)>>5)*sizeof(unsigned int));
264  }
265}
266
267//-------------------------------------------------------------------
268// Destructor
269//-------------------------------------------------------------------
270ClpNonLinearCost::~ClpNonLinearCost ()
271{
272  delete [] start_;
273  delete [] whichRange_;
274  delete [] offset_;
275  delete [] lower_;
276  delete [] cost_;
277  delete [] infeasible_;
278}
279
280//----------------------------------------------------------------
281// Assignment operator
282//-------------------------------------------------------------------
283ClpNonLinearCost &
284ClpNonLinearCost::operator=(const ClpNonLinearCost& rhs)
285{
286  if (this != &rhs) {
287    numberRows_ = rhs.numberRows_;
288    numberColumns_ = rhs.numberColumns_;
289    delete [] start_;
290    delete [] whichRange_;
291    delete [] offset_;
292    delete [] lower_;
293    delete []cost_;
294    delete [] infeasible_;
295    start_ = NULL;
296    whichRange_ = NULL;
297    lower_ = NULL;
298    cost_= NULL;
299    infeasible_=NULL;
300    if (numberRows_) {
301      int numberTotal = numberRows_+numberColumns_;
302      start_ = new int [numberTotal+1];
303      memcpy(start_,rhs.start_,(numberTotal+1)*sizeof(int));
304      whichRange_ = new int [numberTotal];
305      memcpy(whichRange_,rhs.whichRange_,numberTotal*sizeof(int));
306      offset_ = new int [numberTotal];
307      memcpy(offset_,rhs.offset_,numberTotal*sizeof(int));
308      int numberEntries = start_[numberTotal];
309      lower_ = new double [numberEntries];
310      memcpy(lower_,rhs.lower_,numberEntries*sizeof(double));
311      cost_ = new double [numberEntries];
312      memcpy(cost_,rhs.cost_,numberEntries*sizeof(double));
313      infeasible_ = new unsigned int[(numberEntries+31)>>5];
314      memcpy(infeasible_,rhs.infeasible_,
315             ((numberEntries+31)>>5)*sizeof(unsigned int));
316    }
317    model_ = rhs.model_;
318    numberInfeasibilities_=rhs.numberInfeasibilities_;
319    changeCost_ = rhs.changeCost_;
320    largestInfeasibility_ = rhs.largestInfeasibility_;
321    sumInfeasibilities_ = rhs.sumInfeasibilities_;
322    convex_ = rhs.convex_;
323  }
324  return *this;
325}
326
327// Changes infeasible costs and computes number and cost of infeas
328// We will need to re-think objective offsets later
329// We will also need a 2 bit per variable array for some
330// purpose which will come to me later
331void 
332ClpNonLinearCost::checkInfeasibilities(bool toNearest)
333{
334  numberInfeasibilities_=0;
335  double infeasibilityCost = model_->infeasibilityCost();
336  changeCost_=0.0;
337  largestInfeasibility_ = 0.0;
338  sumInfeasibilities_ = 0.0;
339  double primalTolerance = model_->currentPrimalTolerance();
340 
341  int iSequence;
342  double * solution = model_->solutionRegion();
343  double * upper = model_->upperRegion();
344  double * lower = model_->lowerRegion();
345  double * cost = model_->costRegion();
346   
347  // nonbasic should be at a valid bound
348  for (iSequence=0;iSequence<numberColumns_+numberRows_;iSequence++) {
349    double lowerValue;
350    double upperValue;
351    double value=solution[iSequence];
352    int iRange;
353    // get correct place
354    int start = start_[iSequence];
355    int end = start_[iSequence+1]-1;
356    // correct costs for this infeasibility weight
357    if (infeasible(start))
358      cost_[start] = cost_[start+1]-infeasibilityCost;
359    if (infeasible(end-1))
360      cost_[end-1] = cost_[end-2]+infeasibilityCost;
361    for (iRange=start; iRange<end;iRange++) {
362      if (value<lower_[iRange+1]+primalTolerance) {
363        // put in better range if infeasible
364        if (value>=lower_[iRange+1]-primalTolerance&&iRange==start) 
365          iRange++;
366        whichRange_[iSequence]=iRange;
367        break;
368      }
369    }
370    assert(iRange<end);
371    lowerValue = lower_[iRange];
372    upperValue = lower_[iRange+1];
373    ClpSimplex::Status status = model_->getStatus(iSequence);
374    if (upperValue==lowerValue) {
375      if (status != ClpSimplex::basic) 
376        model_->setStatus(iSequence,ClpSimplex::isFixed);
377    }
378    switch(status) {
379     
380    case ClpSimplex::basic:
381    case ClpSimplex::superBasic:
382      // iRange is in correct place
383      // slot in here
384      if (infeasible(iRange)) {
385        if (lower_[iRange]<-1.0e50) {
386          //cost_[iRange] = cost_[iRange+1]-infeasibilityCost;
387          // possibly below
388          lowerValue = lower_[iRange+1];
389          if (value<lowerValue-primalTolerance) {
390            value = lowerValue-value;
391            sumInfeasibilities_ += value;
392            largestInfeasibility_ = max(largestInfeasibility_,value);
393            changeCost_ -= lowerValue*
394              (cost_[iRange]-cost[iSequence]);
395            numberInfeasibilities_++;
396          }
397        } else {
398          //cost_[iRange] = cost_[iRange-1]+infeasibilityCost;
399          // possibly above
400          upperValue = lower_[iRange];
401          if (value>upperValue+primalTolerance) {
402            value = value-upperValue;
403            sumInfeasibilities_ += value;
404            largestInfeasibility_ = max(largestInfeasibility_,value);
405            changeCost_ -= upperValue*
406              (cost_[iRange]-cost[iSequence]);
407            numberInfeasibilities_++;
408          }
409        }
410      }
411      lower[iSequence] = lower_[iRange];
412      upper[iSequence] = lower_[iRange+1];
413      cost[iSequence] = cost_[iRange];
414      break;
415    case ClpSimplex::isFree:
416      if (toNearest)
417        solution[iSequence] = 0.0;
418      break;
419    case ClpSimplex::atUpperBound:
420      if (!toNearest) {
421        // With increasing tolerances - we may be at wrong place
422        if (fabs(value-upperValue)>primalTolerance*1.0001) {
423          assert(fabs(value-lowerValue)<=primalTolerance*1.0001); 
424          model_->setStatus(iSequence,ClpSimplex::atLowerBound);
425        }
426      } else {
427        if (fabs(value-upperValue)<=fabs(value-lowerValue)) {
428          solution[iSequence] = upperValue;
429        } else {
430          model_->setStatus(iSequence,ClpSimplex::atLowerBound);
431          solution[iSequence] = lowerValue;
432        }
433      }
434      break;
435    case ClpSimplex::atLowerBound:
436      if (!toNearest) {
437        // With increasing tolerances - we may be at wrong place
438        if (fabs(value-lowerValue)>primalTolerance*1.0001) {
439          assert(fabs(value-upperValue)<=primalTolerance*1.0001); 
440          model_->setStatus(iSequence,ClpSimplex::atUpperBound);
441        }
442      } else {
443        if (fabs(value-lowerValue)<=fabs(value-upperValue)) {
444          solution[iSequence] = lowerValue;
445        } else {
446          model_->setStatus(iSequence,ClpSimplex::atUpperBound);
447          solution[iSequence] = upperValue;
448        }
449      }
450      break;
451    case ClpSimplex::isFixed:
452      break;
453    }
454  }
455}
456/* Goes through one bound for each variable.
457   If array[i]*multiplier>0 goes down, otherwise up.
458   The indices are row indices and need converting to sequences
459*/
460void 
461ClpNonLinearCost::goThru(int numberInArray, double multiplier,
462              const int * index, const double * array,
463                         double * rhs)
464{
465  assert (model_!=NULL);
466  const int * pivotVariable = model_->pivotVariable();
467  int i;
468  for (i=0;i<numberInArray;i++) {
469    int iRow = index[i];
470    int iPivot = pivotVariable[iRow];
471    double alpha = multiplier*array[iRow];
472    // get where in bound sequence
473    int iRange = whichRange_[iPivot];
474    iRange += offset_[iPivot]; //add temporary bias
475    double value = model_->solution(iPivot);
476    if (alpha>0.0) {
477      // down one
478      iRange--;
479      assert(iRange>=start_[iPivot]);
480      rhs[iRow] = value - lower_[iRange];
481    } else {
482      // up one
483      iRange++;
484      assert(iRange<start_[iPivot+1]-1);
485      rhs[iRow] = lower_[iRange+1] - value;
486    }
487    offset_[iPivot] = iRange - whichRange_[iPivot];
488  }
489}
490/* Takes off last iteration (i.e. offsets closer to 0)
491 */
492void 
493ClpNonLinearCost::goBack(int numberInArray, const int * index, 
494              double * rhs)
495{
496  assert (model_!=NULL);
497  const int * pivotVariable = model_->pivotVariable();
498  int i;
499  for (i=0;i<numberInArray;i++) {
500    int iRow = index[i];
501    int iPivot = pivotVariable[iRow];
502    // get where in bound sequence
503    int iRange = whichRange_[iPivot];
504    bool down;
505    // get closer to original
506    if (offset_[iPivot]>0) {
507      offset_[iPivot]--;
508      assert (offset_[iPivot]>=0);
509      down = false;
510    } else {
511      offset_[iPivot]++;
512      assert (offset_[iPivot]<=0);
513      down = true;
514    }
515    iRange += offset_[iPivot]; //add temporary bias
516    double value = model_->solution(iPivot);
517    if (down) {
518      // down one
519      assert(iRange>=start_[iPivot]);
520      rhs[iRow] = value - lower_[iRange];
521    } else {
522      // up one
523      assert(iRange<start_[iPivot+1]-1);
524      rhs[iRow] = lower_[iRange+1] - value;
525    }
526  }
527}
528void 
529ClpNonLinearCost::goBackAll(const CoinIndexedVector * update)
530{
531  assert (model_!=NULL);
532  const int * pivotVariable = model_->pivotVariable();
533  int i;
534  int number = update->getNumElements();
535  const int * index = update->getIndices();
536  for (i=0;i<number;i++) {
537    int iRow = index[i];
538    int iPivot = pivotVariable[iRow];
539    offset_[iPivot]=0;
540  }
541#ifdef CLP_DEBUG
542  for (i=0;i<numberRows_+numberColumns_;i++) 
543    assert(!offset_[i]);
544#endif
545}
546void 
547ClpNonLinearCost::checkInfeasibilities(int numberInArray, const int * index)
548{
549  assert (model_!=NULL);
550  double primalTolerance = model_->currentPrimalTolerance();
551  const int * pivotVariable = model_->pivotVariable();
552  int i;
553  for (i=0;i<numberInArray;i++) {
554    int iRow = index[i];
555    int iPivot = pivotVariable[iRow];
556    // get where in bound sequence
557    int iRange;
558    double value = model_->solution(iPivot);
559    int start = start_[iPivot];
560    int end = start_[iPivot+1]-1;
561    for (iRange=start; iRange<end;iRange++) {
562      if (value<lower_[iRange+1]+primalTolerance) {
563        // put in better range
564        if (value>=lower_[iRange+1]-primalTolerance&&iRange==start) 
565          iRange++;
566        break;
567      }
568    }
569    assert(iRange<end);
570    assert(model_->getStatus(iPivot)==ClpSimplex::basic);
571    double & lower = model_->lowerAddress(iPivot);
572    double & upper = model_->upperAddress(iPivot);
573    double & cost = model_->costAddress(iPivot);
574    whichRange_[iPivot]=iRange;
575    lower = lower_[iRange];
576    upper = lower_[iRange+1];
577    cost = cost_[iRange];
578  }
579}
580/* Puts back correct infeasible costs for each variable
581   The input indices are row indices and need converting to sequences
582   for costs.
583   On input array is empty (but indices exist).  On exit just
584   changed costs will be stored as normal CoinIndexedVector
585*/
586void 
587ClpNonLinearCost::checkChanged(int numberInArray, CoinIndexedVector * update)
588{
589  assert (model_!=NULL);
590  double primalTolerance = model_->currentPrimalTolerance();
591  const int * pivotVariable = model_->pivotVariable();
592  int number=0;
593  int * index = update->getIndices();
594  double * work = update->denseVector();
595  int i;
596  for (i=0;i<numberInArray;i++) {
597    int iRow = index[i];
598    int iPivot = pivotVariable[iRow];
599    // get where in bound sequence
600    int iRange;
601    double value = model_->solution(iPivot);
602    int start = start_[iPivot];
603    int end = start_[iPivot+1]-1;
604    for (iRange=start; iRange<end;iRange++) {
605      if (value<lower_[iRange+1]+primalTolerance) {
606        // put in better range
607        if (value>=lower_[iRange+1]-primalTolerance&&iRange==start) 
608          iRange++;
609        break;
610      }
611    }
612    assert(iRange<end);
613    assert(model_->getStatus(iPivot)==ClpSimplex::basic);
614    int jRange = whichRange_[iPivot];
615    if (iRange!=jRange) {
616      // changed
617      work[iRow] = cost_[jRange]-cost_[iRange];
618      index[number++]=iRow;
619      double & lower = model_->lowerAddress(iPivot);
620      double & upper = model_->upperAddress(iPivot);
621      double & cost = model_->costAddress(iPivot);
622      whichRange_[iPivot]=iRange;
623      lower = lower_[iRange];
624      upper = lower_[iRange+1];
625      cost = cost_[iRange];
626    }
627  }
628  update->setNumElements(number);
629}
630/* Sets bounds and cost for one variable - returns change in cost*/
631double 
632ClpNonLinearCost::setOne(int iPivot, double value)
633{
634  assert (model_!=NULL);
635  double primalTolerance = model_->currentPrimalTolerance();
636  // get where in bound sequence
637  int iRange;
638  int start = start_[iPivot];
639  int end = start_[iPivot+1]-1;
640  for (iRange=start; iRange<end;iRange++) {
641    if (value<lower_[iRange+1]+primalTolerance) {
642      // put in better range
643      if (value>=lower_[iRange+1]-primalTolerance&&iRange==start) 
644        iRange++;
645      break;
646    }
647  }
648  assert(iRange<end);
649  whichRange_[iPivot]=iRange;
650  double & lower = model_->lowerAddress(iPivot);
651  double & upper = model_->upperAddress(iPivot);
652  double & cost = model_->costAddress(iPivot);
653  lower = lower_[iRange];
654  upper = lower_[iRange+1];
655  ClpSimplex::Status status = model_->getStatus(iPivot);
656  if (upper==lower) {
657    if (status != ClpSimplex::basic) {
658      model_->setStatus(iPivot,ClpSimplex::isFixed);
659      status = ClpSimplex::basic; // so will skip
660    }
661  }
662  switch(status) {
663     
664  case ClpSimplex::basic:
665  case ClpSimplex::superBasic:
666  case ClpSimplex::isFree:
667    break;
668  case ClpSimplex::atUpperBound:
669  case ClpSimplex::atLowerBound:
670  case ClpSimplex::isFixed:
671    // set correctly
672    if (fabs(value-lower)<=primalTolerance*1.001){
673      model_->setStatus(iPivot,ClpSimplex::atLowerBound);
674    } else if (fabs(value-upper)<=primalTolerance*1.001){
675      model_->setStatus(iPivot,ClpSimplex::atUpperBound);
676    } else {
677      // set superBasic
678      model_->setStatus(iPivot,ClpSimplex::superBasic);
679    }
680    break;
681  }
682  double difference = cost-cost_[iRange]; 
683  cost = cost_[iRange];
684  changeCost_ += value*difference;
685  return difference;
686}
687// Returns nearest bound
688double 
689ClpNonLinearCost::nearest(int sequence, double solutionValue)
690{
691  assert (model_!=NULL);
692  // get where in bound sequence
693  int iRange;
694  int start = start_[sequence];
695  int end = start_[sequence+1];
696  int jRange=-1;
697  double nearest=COIN_DBL_MAX;
698  for (iRange=start; iRange<end;iRange++) {
699    if (fabs(solutionValue-lower_[iRange])<nearest) {
700      jRange=iRange;
701      nearest=fabs(solutionValue-lower_[iRange]);
702    }
703  }
704  assert(jRange<end);
705  return lower_[jRange];
706}
707
Note: See TracBrowser for help on using the repository browser.