1 | /* $Id: ClpNonLinearCost.cpp 1753 2011-06-19 16:27:26Z stefan $ */ |
2 | // Copyright (C) 2002, International Business Machines |
3 | // Corporation and others. All Rights Reserved. |
4 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
5 | |
6 | #include "CoinPragma.hpp" |
7 | #include <iostream> |
8 | #include <cassert> |
9 | |
10 | #include "CoinIndexedVector.hpp" |
11 | |
12 | #include "ClpSimplex.hpp" |
13 | #include "CoinHelperFunctions.hpp" |
14 | #include "ClpNonLinearCost.hpp" |
15 | //############################################################################# |
16 | // Constructors / Destructor / Assignment |
17 | //############################################################################# |
18 | |
19 | //------------------------------------------------------------------- |
20 | // Default Constructor |
21 | //------------------------------------------------------------------- |
22 | ClpNonLinearCost::ClpNonLinearCost () : |
23 | changeCost_(0.0), |
24 | feasibleCost_(0.0), |
25 | infeasibilityWeight_(-1.0), |
26 | largestInfeasibility_(0.0), |
27 | sumInfeasibilities_(0.0), |
28 | averageTheta_(0.0), |
29 | numberRows_(0), |
30 | numberColumns_(0), |
31 | start_(NULL), |
32 | whichRange_(NULL), |
33 | offset_(NULL), |
34 | lower_(NULL), |
35 | cost_(NULL), |
36 | model_(NULL), |
37 | infeasible_(NULL), |
38 | numberInfeasibilities_(-1), |
39 | status_(NULL), |
40 | bound_(NULL), |
41 | cost2_(NULL), |
42 | method_(1), |
43 | convex_(true), |
44 | bothWays_(false) |
45 | { |
46 | |
47 | } |
48 | //#define VALIDATE |
49 | #ifdef VALIDATE |
50 | static double * saveLowerV = NULL; |
51 | static double * saveUpperV = NULL; |
52 | #ifdef NDEBUG |
53 | Validate sgould not be set if no debug |
54 | #endif |
55 | #endif |
56 | /* Constructor from simplex. |
57 | This will just set up wasteful arrays for linear, but |
58 | later may do dual analysis and even finding duplicate columns |
59 | */ |
60 | ClpNonLinearCost::ClpNonLinearCost ( ClpSimplex * model, int method) |
61 | { |
62 | method = 2; |
63 | model_ = model; |
64 | numberRows_ = model_->numberRows(); |
65 | //if (numberRows_==402) { |
66 | //model_->setLogLevel(63); |
67 | //model_->setMaximumIterations(30000); |
68 | //} |
69 | numberColumns_ = model_->numberColumns(); |
70 | // If gub then we need this extra |
71 | int = model_->numberExtraRows(); |
72 | if (numberExtra) |
73 | method = 1; |
74 | int numberTotal1 = numberRows_ + numberColumns_; |
75 | int numberTotal = numberTotal1 + numberExtra; |
76 | convex_ = true; |
77 | bothWays_ = false; |
78 | method_ = method; |
79 | numberInfeasibilities_ = 0; |
80 | changeCost_ = 0.0; |
81 | feasibleCost_ = 0.0; |
82 | infeasibilityWeight_ = -1.0; |
83 | double * cost = model_->costRegion(); |
84 | // check if all 0 |
85 | int iSequence; |
86 | bool allZero = true; |
87 | for (iSequence = 0; iSequence < numberTotal1; iSequence++) { |
88 | if (cost[iSequence]) { |
89 | allZero = false; |
90 | break; |
91 | } |
92 | } |
93 | if (allZero&&model_->clpMatrix()->type()<15) |
94 | model_->setInfeasibilityCost(1.0); |
95 | double infeasibilityCost = model_->infeasibilityCost(); |
96 | sumInfeasibilities_ = 0.0; |
97 | averageTheta_ = 0.0; |
98 | largestInfeasibility_ = 0.0; |
99 | // All arrays NULL to start |
100 | status_ = NULL; |
101 | bound_ = NULL; |
102 | cost2_ = NULL; |
103 | start_ = NULL; |
104 | whichRange_ = NULL; |
105 | offset_ = NULL; |
106 | lower_ = NULL; |
107 | cost_ = NULL; |
108 | infeasible_ = NULL; |
109 | |
110 | double * upper = model_->upperRegion(); |
111 | double * lower = model_->lowerRegion(); |
112 | |
113 | // See how we are storing things |
114 | bool always4 = (model_->clpMatrix()-> |
115 | generalExpanded(model_, 10, iSequence) != 0); |
116 | if (always4) |
117 | method_ = 1; |
118 | if (CLP_METHOD1) { |
119 | start_ = new int [numberTotal+1]; |
120 | whichRange_ = new int [numberTotal]; |
121 | offset_ = new int [numberTotal]; |
122 | memset(offset_, 0, numberTotal * sizeof(int)); |
123 | |
124 | |
125 | // First see how much space we need |
126 | int put = 0; |
127 | |
128 | // For quadratic we need -inf,0,0,+inf |
129 | for (iSequence = 0; iSequence < numberTotal1; iSequence++) { |
130 | if (!always4) { |
131 | if (lower[iSequence] > -COIN_DBL_MAX) |
132 | put++; |
133 | if (upper[iSequence] < COIN_DBL_MAX) |
134 | put++; |
135 | put += 2; |
136 | } else { |
137 | put += 4; |
138 | } |
139 | } |
140 | |
141 | // and for extra |
142 | put += 4 * numberExtra; |
143 | #ifndef NDEBUG |
144 | int kPut = put; |
145 | #endif |
146 | lower_ = new double [put]; |
147 | cost_ = new double [put]; |
148 | infeasible_ = new unsigned int[(put+31)>>5]; |
149 | memset(infeasible_, 0, ((put + 31) >> 5)*sizeof(unsigned int)); |
150 | |
151 | put = 0; |
152 | |
153 | start_[0] = 0; |
154 | |
155 | for (iSequence = 0; iSequence < numberTotal1; iSequence++) { |
156 | if (!always4) { |
157 | if (lower[iSequence] > -COIN_DBL_MAX) { |
158 | lower_[put] = -COIN_DBL_MAX; |
159 | setInfeasible(put, true); |
160 | cost_[put++] = cost[iSequence] - infeasibilityCost; |
161 | } |
162 | whichRange_[iSequence] = put; |
163 | lower_[put] = lower[iSequence]; |
164 | cost_[put++] = cost[iSequence]; |
165 | lower_[put] = upper[iSequence]; |
166 | cost_[put++] = cost[iSequence] + infeasibilityCost; |
167 | if (upper[iSequence] < COIN_DBL_MAX) { |
168 | lower_[put] = COIN_DBL_MAX; |
169 | setInfeasible(put - 1, true); |
170 | cost_[put++] = 1.0e50; |
171 | } |
172 | } else { |
173 | lower_[put] = -COIN_DBL_MAX; |
174 | setInfeasible(put, true); |
175 | cost_[put++] = cost[iSequence] - infeasibilityCost; |
176 | whichRange_[iSequence] = put; |
177 | lower_[put] = lower[iSequence]; |
178 | cost_[put++] = cost[iSequence]; |
179 | lower_[put] = upper[iSequence]; |
180 | cost_[put++] = cost[iSequence] + infeasibilityCost; |
181 | lower_[put] = COIN_DBL_MAX; |
182 | setInfeasible(put - 1, true); |
183 | cost_[put++] = 1.0e50; |
184 | } |
185 | start_[iSequence+1] = put; |
186 | } |
187 | for (; iSequence < numberTotal; iSequence++) { |
188 | |
189 | lower_[put] = -COIN_DBL_MAX; |
190 | setInfeasible(put, true); |
191 | put++; |
192 | whichRange_[iSequence] = put; |
193 | lower_[put] = 0.0; |
194 | cost_[put++] = 0.0; |
195 | lower_[put] = 0.0; |
196 | cost_[put++] = 0.0; |
197 | lower_[put] = COIN_DBL_MAX; |
198 | setInfeasible(put - 1, true); |
199 | cost_[put++] = 1.0e50; |
200 | start_[iSequence+1] = put; |
201 | } |
202 | assert (put <= kPut); |
203 | } |
204 | #ifdef FAST_CLPNON |
205 | // See how we are storing things |
206 | CoinAssert (model_->clpMatrix()-> |
207 | generalExpanded(model_, 10, iSequence) == 0); |
208 | #endif |
209 | if (CLP_METHOD2) { |
210 | assert (!numberExtra); |
211 | bound_ = new double[numberTotal]; |
212 | cost2_ = new double[numberTotal]; |
213 | status_ = new unsigned char[numberTotal]; |
214 | #ifdef VALIDATE |
215 | delete [] saveLowerV; |
216 | saveLowerV = CoinCopyOfArray(model_->lowerRegion(), numberTotal); |
217 | delete [] saveUpperV; |
218 | saveUpperV = CoinCopyOfArray(model_->upperRegion(), numberTotal); |
219 | #endif |
220 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
221 | bound_[iSequence] = 0.0; |
222 | cost2_[iSequence] = cost[iSequence]; |
223 | setInitialStatus(status_[iSequence]); |
224 | } |
225 | } |
226 | } |
227 | // Refreshes costs always makes row costs zero |
228 | void |
229 | ClpNonLinearCost::refreshCosts(const double * columnCosts) |
230 | { |
231 | double * cost = model_->costRegion(); |
232 | // zero row costs |
233 | memset(cost + numberColumns_, 0, numberRows_ * sizeof(double)); |
234 | // copy column costs |
235 | CoinMemcpyN(columnCosts, numberColumns_, cost); |
236 | if ((method_ & 1) != 0) { |
237 | for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { |
238 | int start = start_[iSequence]; |
239 | int end = start_[iSequence+1] - 1; |
240 | double thisFeasibleCost = cost[iSequence]; |
241 | if (infeasible(start)) { |
242 | cost_[start] = thisFeasibleCost - infeasibilityWeight_; |
243 | cost_[start+1] = thisFeasibleCost; |
244 | } else { |
245 | cost_[start] = thisFeasibleCost; |
246 | } |
247 | if (infeasible(end - 1)) { |
248 | cost_[end-1] = thisFeasibleCost + infeasibilityWeight_; |
249 | } |
250 | } |
251 | } |
252 | if (CLP_METHOD2) { |
253 | for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) { |
254 | cost2_[iSequence] = cost[iSequence]; |
255 | } |
256 | } |
257 | } |
258 | ClpNonLinearCost::ClpNonLinearCost(ClpSimplex * model, const int * starts, |
259 | const double * lowerNon, const double * costNon) |
260 | { |
261 | #ifndef FAST_CLPNON |
262 | // what about scaling? - only try without it initially |
263 | assert(!model->scalingFlag()); |
264 | model_ = model; |
265 | numberRows_ = model_->numberRows(); |
266 | numberColumns_ = model_->numberColumns(); |
267 | int numberTotal = numberRows_ + numberColumns_; |
268 | convex_ = true; |
269 | bothWays_ = true; |
270 | start_ = new int [numberTotal+1]; |
271 | whichRange_ = new int [numberTotal]; |
272 | offset_ = new int [numberTotal]; |
273 | memset(offset_, 0, numberTotal * sizeof(int)); |
274 | |
275 | double whichWay = model_->optimizationDirection(); |
276 | COIN_DETAIL_PRINT(printf("Direction %g\n" , whichWay)); |
277 | |
278 | numberInfeasibilities_ = 0; |
279 | changeCost_ = 0.0; |
280 | feasibleCost_ = 0.0; |
281 | double infeasibilityCost = model_->infeasibilityCost(); |
282 | infeasibilityWeight_ = infeasibilityCost; |
283 | largestInfeasibility_ = 0.0; |
284 | sumInfeasibilities_ = 0.0; |
285 | |
286 | int iSequence; |
287 | assert (!model_->rowObjective()); |
288 | double * cost = model_->objective(); |
289 | |
290 | // First see how much space we need |
291 | // Also set up feasible bounds |
292 | int put = starts[numberColumns_]; |
293 | |
294 | double * columnUpper = model_->columnUpper(); |
295 | double * columnLower = model_->columnLower(); |
296 | for (iSequence = 0; iSequence < numberColumns_; iSequence++) { |
297 | if (columnLower[iSequence] > -1.0e20) |
298 | put++; |
299 | if (columnUpper[iSequence] < 1.0e20) |
300 | put++; |
301 | } |
302 | |
303 | double * rowUpper = model_->rowUpper(); |
304 | double * rowLower = model_->rowLower(); |
305 | for (iSequence = 0; iSequence < numberRows_; iSequence++) { |
306 | if (rowLower[iSequence] > -1.0e20) |
307 | put++; |
308 | if (rowUpper[iSequence] < 1.0e20) |
309 | put++; |
310 | put += 2; |
311 | } |
312 | lower_ = new double [put]; |
313 | cost_ = new double [put]; |
314 | infeasible_ = new unsigned int[(put+31)>>5]; |
315 | memset(infeasible_, 0, ((put + 31) >> 5)*sizeof(unsigned int)); |
316 | |
317 | // now fill in |
318 | put = 0; |
319 | |
320 | start_[0] = 0; |
321 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
322 | lower_[put] = -COIN_DBL_MAX; |
323 | whichRange_[iSequence] = put + 1; |
324 | double thisCost; |
325 | double lowerValue; |
326 | double upperValue; |
327 | if (iSequence >= numberColumns_) { |
328 | // rows |
329 | lowerValue = rowLower[iSequence-numberColumns_]; |
330 | upperValue = rowUpper[iSequence-numberColumns_]; |
331 | if (lowerValue > -1.0e30) { |
332 | setInfeasible(put, true); |
333 | cost_[put++] = -infeasibilityCost; |
334 | lower_[put] = lowerValue; |
335 | } |
336 | cost_[put++] = 0.0; |
337 | thisCost = 0.0; |
338 | } else { |
339 | // columns - move costs and see if convex |
340 | lowerValue = columnLower[iSequence]; |
341 | upperValue = columnUpper[iSequence]; |
342 | if (lowerValue > -1.0e30) { |
343 | setInfeasible(put, true); |
344 | cost_[put++] = whichWay * cost[iSequence] - infeasibilityCost; |
345 | lower_[put] = lowerValue; |
346 | } |
347 | int iIndex = starts[iSequence]; |
348 | int end = starts[iSequence+1]; |
349 | assert (fabs(columnLower[iSequence] - lowerNon[iIndex]) < 1.0e-8); |
350 | thisCost = -COIN_DBL_MAX; |
351 | for (; iIndex < end; iIndex++) { |
352 | if (lowerNon[iIndex] < columnUpper[iSequence] - 1.0e-8) { |
353 | lower_[put] = lowerNon[iIndex]; |
354 | cost_[put++] = whichWay * costNon[iIndex]; |
355 | // check convexity |
356 | if (whichWay * costNon[iIndex] < thisCost - 1.0e-12) |
357 | convex_ = false; |
358 | thisCost = whichWay * costNon[iIndex]; |
359 | } else { |
360 | break; |
361 | } |
362 | } |
363 | } |
364 | lower_[put] = upperValue; |
365 | setInfeasible(put, true); |
366 | cost_[put++] = thisCost + infeasibilityCost; |
367 | if (upperValue < 1.0e20) { |
368 | lower_[put] = COIN_DBL_MAX; |
369 | cost_[put++] = 1.0e50; |
370 | } |
371 | int iFirst = start_[iSequence]; |
372 | if (lower_[iFirst] != -COIN_DBL_MAX) { |
373 | setInfeasible(iFirst, true); |
374 | whichRange_[iSequence] = iFirst + 1; |
375 | } else { |
376 | whichRange_[iSequence] = iFirst; |
377 | } |
378 | start_[iSequence+1] = put; |
379 | } |
380 | // can't handle non-convex at present |
381 | assert(convex_); |
382 | status_ = NULL; |
383 | bound_ = NULL; |
384 | cost2_ = NULL; |
385 | method_ = 1; |
386 | #else |
387 | printf("recompile ClpNonLinearCost without FAST_CLPNON\n" ); |
388 | abort(); |
389 | #endif |
390 | } |
391 | //------------------------------------------------------------------- |
392 | // Copy constructor |
393 | //------------------------------------------------------------------- |
394 | ClpNonLinearCost::ClpNonLinearCost (const ClpNonLinearCost & rhs) : |
395 | changeCost_(0.0), |
396 | feasibleCost_(0.0), |
397 | infeasibilityWeight_(-1.0), |
398 | largestInfeasibility_(0.0), |
399 | sumInfeasibilities_(0.0), |
400 | averageTheta_(0.0), |
401 | numberRows_(rhs.numberRows_), |
402 | numberColumns_(rhs.numberColumns_), |
403 | start_(NULL), |
404 | whichRange_(NULL), |
405 | offset_(NULL), |
406 | lower_(NULL), |
407 | cost_(NULL), |
408 | model_(NULL), |
409 | infeasible_(NULL), |
410 | numberInfeasibilities_(-1), |
411 | status_(NULL), |
412 | bound_(NULL), |
413 | cost2_(NULL), |
414 | method_(rhs.method_), |
415 | convex_(true), |
416 | bothWays_(rhs.bothWays_) |
417 | { |
418 | if (numberRows_) { |
419 | int numberTotal = numberRows_ + numberColumns_; |
420 | model_ = rhs.model_; |
421 | numberInfeasibilities_ = rhs.numberInfeasibilities_; |
422 | changeCost_ = rhs.changeCost_; |
423 | feasibleCost_ = rhs.feasibleCost_; |
424 | infeasibilityWeight_ = rhs.infeasibilityWeight_; |
425 | largestInfeasibility_ = rhs.largestInfeasibility_; |
426 | sumInfeasibilities_ = rhs.sumInfeasibilities_; |
427 | averageTheta_ = rhs.averageTheta_; |
428 | convex_ = rhs.convex_; |
429 | if (CLP_METHOD1) { |
430 | start_ = new int [numberTotal+1]; |
431 | CoinMemcpyN(rhs.start_, (numberTotal + 1), start_); |
432 | whichRange_ = new int [numberTotal]; |
433 | CoinMemcpyN(rhs.whichRange_, numberTotal, whichRange_); |
434 | offset_ = new int [numberTotal]; |
435 | CoinMemcpyN(rhs.offset_, numberTotal, offset_); |
436 | int numberEntries = start_[numberTotal]; |
437 | lower_ = new double [numberEntries]; |
438 | CoinMemcpyN(rhs.lower_, numberEntries, lower_); |
439 | cost_ = new double [numberEntries]; |
440 | CoinMemcpyN(rhs.cost_, numberEntries, cost_); |
441 | infeasible_ = new unsigned int[(numberEntries+31)>>5]; |
442 | CoinMemcpyN(rhs.infeasible_, ((numberEntries + 31) >> 5), infeasible_); |
443 | } |
444 | if (CLP_METHOD2) { |
445 | bound_ = CoinCopyOfArray(rhs.bound_, numberTotal); |
446 | cost2_ = CoinCopyOfArray(rhs.cost2_, numberTotal); |
447 | status_ = CoinCopyOfArray(rhs.status_, numberTotal); |
448 | } |
449 | } |
450 | } |
451 | |
452 | //------------------------------------------------------------------- |
453 | // Destructor |
454 | //------------------------------------------------------------------- |
455 | ClpNonLinearCost::~ClpNonLinearCost () |
456 | { |
457 | delete [] start_; |
458 | delete [] whichRange_; |
459 | delete [] offset_; |
460 | delete [] lower_; |
461 | delete [] cost_; |
462 | delete [] infeasible_; |
463 | delete [] status_; |
464 | delete [] bound_; |
465 | delete [] cost2_; |
466 | } |
467 | |
468 | //---------------------------------------------------------------- |
469 | // Assignment operator |
470 | //------------------------------------------------------------------- |
471 | ClpNonLinearCost & |
472 | ClpNonLinearCost::operator=(const ClpNonLinearCost& rhs) |
473 | { |
474 | if (this != &rhs) { |
475 | numberRows_ = rhs.numberRows_; |
476 | numberColumns_ = rhs.numberColumns_; |
477 | delete [] start_; |
478 | delete [] whichRange_; |
479 | delete [] offset_; |
480 | delete [] lower_; |
481 | delete [] cost_; |
482 | delete [] infeasible_; |
483 | delete [] status_; |
484 | delete [] bound_; |
485 | delete [] cost2_; |
486 | start_ = NULL; |
487 | whichRange_ = NULL; |
488 | lower_ = NULL; |
489 | cost_ = NULL; |
490 | infeasible_ = NULL; |
491 | status_ = NULL; |
492 | bound_ = NULL; |
493 | cost2_ = NULL; |
494 | method_ = rhs.method_; |
495 | if (numberRows_) { |
496 | int numberTotal = numberRows_ + numberColumns_; |
497 | if (CLP_METHOD1) { |
498 | start_ = new int [numberTotal+1]; |
499 | CoinMemcpyN(rhs.start_, (numberTotal + 1), start_); |
500 | whichRange_ = new int [numberTotal]; |
501 | CoinMemcpyN(rhs.whichRange_, numberTotal, whichRange_); |
502 | offset_ = new int [numberTotal]; |
503 | CoinMemcpyN(rhs.offset_, numberTotal, offset_); |
504 | int numberEntries = start_[numberTotal]; |
505 | lower_ = new double [numberEntries]; |
506 | CoinMemcpyN(rhs.lower_, numberEntries, lower_); |
507 | cost_ = new double [numberEntries]; |
508 | CoinMemcpyN(rhs.cost_, numberEntries, cost_); |
509 | infeasible_ = new unsigned int[(numberEntries+31)>>5]; |
510 | CoinMemcpyN(rhs.infeasible_, ((numberEntries + 31) >> 5), infeasible_); |
511 | } |
512 | if (CLP_METHOD2) { |
513 | bound_ = CoinCopyOfArray(rhs.bound_, numberTotal); |
514 | cost2_ = CoinCopyOfArray(rhs.cost2_, numberTotal); |
515 | status_ = CoinCopyOfArray(rhs.status_, numberTotal); |
516 | } |
517 | } |
518 | model_ = rhs.model_; |
519 | numberInfeasibilities_ = rhs.numberInfeasibilities_; |
520 | changeCost_ = rhs.changeCost_; |
521 | feasibleCost_ = rhs.feasibleCost_; |
522 | infeasibilityWeight_ = rhs.infeasibilityWeight_; |
523 | largestInfeasibility_ = rhs.largestInfeasibility_; |
524 | sumInfeasibilities_ = rhs.sumInfeasibilities_; |
525 | averageTheta_ = rhs.averageTheta_; |
526 | convex_ = rhs.convex_; |
527 | bothWays_ = rhs.bothWays_; |
528 | } |
529 | return *this; |
530 | } |
531 | // Changes infeasible costs and computes number and cost of infeas |
532 | // We will need to re-think objective offsets later |
533 | // We will also need a 2 bit per variable array for some |
534 | // purpose which will come to me later |
535 | void |
536 | ClpNonLinearCost::checkInfeasibilities(double oldTolerance) |
537 | { |
538 | numberInfeasibilities_ = 0; |
539 | double infeasibilityCost = model_->infeasibilityCost(); |
540 | changeCost_ = 0.0; |
541 | largestInfeasibility_ = 0.0; |
542 | sumInfeasibilities_ = 0.0; |
543 | double primalTolerance = model_->currentPrimalTolerance(); |
544 | int iSequence; |
545 | double * solution = model_->solutionRegion(); |
546 | double * upper = model_->upperRegion(); |
547 | double * lower = model_->lowerRegion(); |
548 | double * cost = model_->costRegion(); |
549 | bool toNearest = oldTolerance <= 0.0; |
550 | feasibleCost_ = 0.0; |
551 | //bool checkCosts = (infeasibilityWeight_ != infeasibilityCost); |
552 | infeasibilityWeight_ = infeasibilityCost; |
553 | int numberTotal = numberColumns_ + numberRows_; |
554 | //#define NONLIN_DEBUG |
555 | #ifdef NONLIN_DEBUG |
556 | double * saveSolution = NULL; |
557 | double * saveLower = NULL; |
558 | double * saveUpper = NULL; |
559 | unsigned char * saveStatus = NULL; |
560 | if (method_ == 3) { |
561 | // Save solution as we will be checking |
562 | saveSolution = CoinCopyOfArray(solution, numberTotal); |
563 | saveLower = CoinCopyOfArray(lower, numberTotal); |
564 | saveUpper = CoinCopyOfArray(upper, numberTotal); |
565 | saveStatus = CoinCopyOfArray(model_->statusArray(), numberTotal); |
566 | } |
567 | #else |
568 | assert (method_ != 3); |
569 | #endif |
570 | if (CLP_METHOD1) { |
571 | // nonbasic should be at a valid bound |
572 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
573 | double lowerValue; |
574 | double upperValue; |
575 | double value = solution[iSequence]; |
576 | int iRange; |
577 | // get correct place |
578 | int start = start_[iSequence]; |
579 | int end = start_[iSequence+1] - 1; |
580 | // correct costs for this infeasibility weight |
581 | // If free then true cost will be first |
582 | double thisFeasibleCost = cost_[start]; |
583 | if (infeasible(start)) { |
584 | thisFeasibleCost = cost_[start+1]; |
585 | cost_[start] = thisFeasibleCost - infeasibilityCost; |
586 | } |
587 | if (infeasible(end - 1)) { |
588 | thisFeasibleCost = cost_[end-2]; |
589 | cost_[end-1] = thisFeasibleCost + infeasibilityCost; |
590 | } |
591 | for (iRange = start; iRange < end; iRange++) { |
592 | if (value < lower_[iRange+1] + primalTolerance) { |
593 | // put in better range if infeasible |
594 | if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) |
595 | iRange++; |
596 | whichRange_[iSequence] = iRange; |
597 | break; |
598 | } |
599 | } |
600 | assert(iRange < end); |
601 | lowerValue = lower_[iRange]; |
602 | upperValue = lower_[iRange+1]; |
603 | ClpSimplex::Status status = model_->getStatus(iSequence); |
604 | if (upperValue == lowerValue && status != ClpSimplex::isFixed) { |
605 | if (status != ClpSimplex::basic) { |
606 | model_->setStatus(iSequence, ClpSimplex::isFixed); |
607 | status = ClpSimplex::isFixed; |
608 | } |
609 | } |
610 | //#define PRINT_DETAIL7 2 |
611 | #if PRINT_DETAIL7>1 |
612 | printf("NL %d sol %g bounds %g %g\n" , |
613 | iSequence,solution[iSequence], |
614 | lowerValue,upperValue); |
615 | #endif |
616 | switch(status) { |
617 | |
618 | case ClpSimplex::basic: |
619 | case ClpSimplex::superBasic: |
620 | // iRange is in correct place |
621 | // slot in here |
622 | if (infeasible(iRange)) { |
623 | if (lower_[iRange] < -1.0e50) { |
624 | //cost_[iRange] = cost_[iRange+1]-infeasibilityCost; |
625 | // possibly below |
626 | lowerValue = lower_[iRange+1]; |
627 | if (value - lowerValue < -primalTolerance) { |
628 | value = lowerValue - value - primalTolerance; |
629 | #ifndef NDEBUG |
630 | if(value > 1.0e15) |
631 | printf("nonlincostb %d %g %g %g\n" , |
632 | iSequence, lowerValue, solution[iSequence], lower_[iRange+2]); |
633 | #endif |
634 | #if PRINT_DETAIL7 |
635 | printf("**NL %d sol %g below %g\n" , |
636 | iSequence,solution[iSequence], |
637 | lowerValue); |
638 | #endif |
639 | sumInfeasibilities_ += value; |
640 | largestInfeasibility_ = CoinMax(largestInfeasibility_, value); |
641 | changeCost_ -= lowerValue * |
642 | (cost_[iRange] - cost[iSequence]); |
643 | numberInfeasibilities_++; |
644 | } |
645 | } else { |
646 | //cost_[iRange] = cost_[iRange-1]+infeasibilityCost; |
647 | // possibly above |
648 | upperValue = lower_[iRange]; |
649 | if (value - upperValue > primalTolerance) { |
650 | value = value - upperValue - primalTolerance; |
651 | #ifndef NDEBUG |
652 | if(value > 1.0e15) |
653 | printf("nonlincostu %d %g %g %g\n" , |
654 | iSequence, lower_[iRange-1], solution[iSequence], upperValue); |
655 | #endif |
656 | #if PRINT_DETAIL7 |
657 | printf("**NL %d sol %g above %g\n" , |
658 | iSequence,solution[iSequence], |
659 | upperValue); |
660 | #endif |
661 | sumInfeasibilities_ += value; |
662 | largestInfeasibility_ = CoinMax(largestInfeasibility_, value); |
663 | changeCost_ -= upperValue * |
664 | (cost_[iRange] - cost[iSequence]); |
665 | numberInfeasibilities_++; |
666 | } |
667 | } |
668 | } |
669 | //lower[iSequence] = lower_[iRange]; |
670 | //upper[iSequence] = lower_[iRange+1]; |
671 | //cost[iSequence] = cost_[iRange]; |
672 | break; |
673 | case ClpSimplex::isFree: |
674 | //if (toNearest) |
675 | //solution[iSequence] = 0.0; |
676 | break; |
677 | case ClpSimplex::atUpperBound: |
678 | if (!toNearest) { |
679 | // With increasing tolerances - we may be at wrong place |
680 | if (fabs(value - upperValue) > oldTolerance * 1.0001) { |
681 | if (fabs(value - lowerValue) <= oldTolerance * 1.0001) { |
682 | if (fabs(value - lowerValue) > primalTolerance) |
683 | solution[iSequence] = lowerValue; |
684 | model_->setStatus(iSequence, ClpSimplex::atLowerBound); |
685 | } else { |
686 | model_->setStatus(iSequence, ClpSimplex::superBasic); |
687 | } |
688 | } else if (fabs(value - upperValue) > primalTolerance) { |
689 | solution[iSequence] = upperValue; |
690 | } |
691 | } else { |
692 | // Set to nearest and make at upper bound |
693 | int kRange; |
694 | iRange = -1; |
695 | double nearest = COIN_DBL_MAX; |
696 | for (kRange = start; kRange < end; kRange++) { |
697 | if (fabs(lower_[kRange] - value) < nearest) { |
698 | nearest = fabs(lower_[kRange] - value); |
699 | iRange = kRange; |
700 | } |
701 | } |
702 | assert (iRange >= 0); |
703 | iRange--; |
704 | whichRange_[iSequence] = iRange; |
705 | solution[iSequence] = lower_[iRange+1]; |
706 | } |
707 | break; |
708 | case ClpSimplex::atLowerBound: |
709 | if (!toNearest) { |
710 | // With increasing tolerances - we may be at wrong place |
711 | // below stops compiler error with gcc 3.2!!! |
712 | if (iSequence == -119) |
713 | printf("ZZ %g %g %g %g\n" , lowerValue, value, upperValue, oldTolerance); |
714 | if (fabs(value - lowerValue) > oldTolerance * 1.0001) { |
715 | if (fabs(value - upperValue) <= oldTolerance * 1.0001) { |
716 | if (fabs(value - upperValue) > primalTolerance) |
717 | solution[iSequence] = upperValue; |
718 | model_->setStatus(iSequence, ClpSimplex::atUpperBound); |
719 | } else { |
720 | model_->setStatus(iSequence, ClpSimplex::superBasic); |
721 | } |
722 | } else if (fabs(value - lowerValue) > primalTolerance) { |
723 | solution[iSequence] = lowerValue; |
724 | } |
725 | } else { |
726 | // Set to nearest and make at lower bound |
727 | int kRange; |
728 | iRange = -1; |
729 | double nearest = COIN_DBL_MAX; |
730 | for (kRange = start; kRange < end; kRange++) { |
731 | if (fabs(lower_[kRange] - value) < nearest) { |
732 | nearest = fabs(lower_[kRange] - value); |
733 | iRange = kRange; |
734 | } |
735 | } |
736 | assert (iRange >= 0); |
737 | whichRange_[iSequence] = iRange; |
738 | solution[iSequence] = lower_[iRange]; |
739 | } |
740 | break; |
741 | case ClpSimplex::isFixed: |
742 | if (toNearest) { |
743 | // Set to true fixed |
744 | for (iRange = start; iRange < end; iRange++) { |
745 | if (lower_[iRange] == lower_[iRange+1]) |
746 | break; |
747 | } |
748 | if (iRange == end) { |
749 | // Odd - but make sensible |
750 | // Set to nearest and make at lower bound |
751 | int kRange; |
752 | iRange = -1; |
753 | double nearest = COIN_DBL_MAX; |
754 | for (kRange = start; kRange < end; kRange++) { |
755 | if (fabs(lower_[kRange] - value) < nearest) { |
756 | nearest = fabs(lower_[kRange] - value); |
757 | iRange = kRange; |
758 | } |
759 | } |
760 | assert (iRange >= 0); |
761 | whichRange_[iSequence] = iRange; |
762 | if (lower_[iRange] != lower_[iRange+1]) |
763 | model_->setStatus(iSequence, ClpSimplex::atLowerBound); |
764 | else |
765 | model_->setStatus(iSequence, ClpSimplex::atUpperBound); |
766 | } |
767 | solution[iSequence] = lower_[iRange]; |
768 | } |
769 | break; |
770 | } |
771 | lower[iSequence] = lower_[iRange]; |
772 | upper[iSequence] = lower_[iRange+1]; |
773 | cost[iSequence] = cost_[iRange]; |
774 | feasibleCost_ += thisFeasibleCost * solution[iSequence]; |
775 | //assert (iRange==whichRange_[iSequence]); |
776 | } |
777 | } |
778 | #ifdef NONLIN_DEBUG |
779 | double saveCost = feasibleCost_; |
780 | if (method_ == 3) { |
781 | feasibleCost_ = 0.0; |
782 | // Put back solution as we will be checking |
783 | unsigned char * statusA = model_->statusArray(); |
784 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
785 | double value = solution[iSequence]; |
786 | solution[iSequence] = saveSolution[iSequence]; |
787 | saveSolution[iSequence] = value; |
788 | value = lower[iSequence]; |
789 | lower[iSequence] = saveLower[iSequence]; |
790 | saveLower[iSequence] = value; |
791 | value = upper[iSequence]; |
792 | upper[iSequence] = saveUpper[iSequence]; |
793 | saveUpper[iSequence] = value; |
794 | unsigned char value2 = statusA[iSequence]; |
795 | statusA[iSequence] = saveStatus[iSequence]; |
796 | saveStatus[iSequence] = value2; |
797 | } |
798 | } |
799 | #endif |
800 | if (CLP_METHOD2) { |
801 | //#define CLP_NON_JUST_BASIC |
802 | #ifndef CLP_NON_JUST_BASIC |
803 | // nonbasic should be at a valid bound |
804 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
805 | #else |
806 | const int * pivotVariable = model_->pivotVariable(); |
807 | for (int i=0;i<numberRows_;i++) { |
808 | int iSequence = pivotVariable[i]; |
809 | #endif |
810 | double value = solution[iSequence]; |
811 | unsigned char iStatus = status_[iSequence]; |
812 | assert (currentStatus(iStatus) == CLP_SAME); |
813 | double lowerValue = lower[iSequence]; |
814 | double upperValue = upper[iSequence]; |
815 | double costValue = cost2_[iSequence]; |
816 | double trueCost = costValue; |
817 | int iWhere = originalStatus(iStatus); |
818 | if (iWhere == CLP_BELOW_LOWER) { |
819 | lowerValue = upperValue; |
820 | upperValue = bound_[iSequence]; |
821 | costValue -= infeasibilityCost; |
822 | } else if (iWhere == CLP_ABOVE_UPPER) { |
823 | upperValue = lowerValue; |
824 | lowerValue = bound_[iSequence]; |
825 | costValue += infeasibilityCost; |
826 | } |
827 | // get correct place |
828 | int newWhere = CLP_FEASIBLE; |
829 | ClpSimplex::Status status = model_->getStatus(iSequence); |
830 | if (upperValue == lowerValue && status != ClpSimplex::isFixed) { |
831 | if (status != ClpSimplex::basic) { |
832 | model_->setStatus(iSequence, ClpSimplex::isFixed); |
833 | status = ClpSimplex::isFixed; |
834 | } |
835 | } |
836 | switch(status) { |
837 | |
838 | case ClpSimplex::basic: |
839 | case ClpSimplex::superBasic: |
840 | if (value - upperValue <= primalTolerance) { |
841 | if (value - lowerValue >= -primalTolerance) { |
842 | // feasible |
843 | //newWhere=CLP_FEASIBLE; |
844 | } else { |
845 | // below |
846 | newWhere = CLP_BELOW_LOWER; |
847 | assert (fabs(lowerValue) < 1.0e100); |
848 | double infeasibility = lowerValue - value - primalTolerance; |
849 | sumInfeasibilities_ += infeasibility; |
850 | largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); |
851 | costValue = trueCost - infeasibilityCost; |
852 | changeCost_ -= lowerValue * (costValue - cost[iSequence]); |
853 | numberInfeasibilities_++; |
854 | } |
855 | } else { |
856 | // above |
857 | newWhere = CLP_ABOVE_UPPER; |
858 | double infeasibility = value - upperValue - primalTolerance; |
859 | sumInfeasibilities_ += infeasibility; |
860 | largestInfeasibility_ = CoinMax(largestInfeasibility_, infeasibility); |
861 | costValue = trueCost + infeasibilityCost; |
862 | changeCost_ -= upperValue * (costValue - cost[iSequence]); |
863 | numberInfeasibilities_++; |
864 | } |
865 | break; |
866 | case ClpSimplex::isFree: |
867 | break; |
868 | case ClpSimplex::atUpperBound: |
869 | if (!toNearest) { |
870 | // With increasing tolerances - we may be at wrong place |
871 | if (fabs(value - upperValue) > oldTolerance * 1.0001) { |
872 | if (fabs(value - lowerValue) <= oldTolerance * 1.0001) { |
873 | if (fabs(value - lowerValue) > primalTolerance) { |
874 | solution[iSequence] = lowerValue; |
875 | value = lowerValue; |
876 | } |
877 | model_->setStatus(iSequence, ClpSimplex::atLowerBound); |
878 | } else { |
879 | if (value < upperValue) { |
880 | if (value > lowerValue) { |
881 | model_->setStatus(iSequence, ClpSimplex::superBasic); |
882 | } else { |
883 | // set to lower bound as infeasible |
884 | solution[iSequence] = lowerValue; |
885 | value = lowerValue; |
886 | model_->setStatus(iSequence, ClpSimplex::atLowerBound); |
887 | } |
888 | } else { |
889 | // set to upper bound as infeasible |
890 | solution[iSequence] = upperValue; |
891 | value = upperValue; |
892 | } |
893 | } |
894 | } else if (fabs(value - upperValue) > primalTolerance) { |
895 | solution[iSequence] = upperValue; |
896 | value = upperValue; |
897 | } |
898 | } else { |
899 | // Set to nearest and make at bound |
900 | if (fabs(value - lowerValue) < fabs(value - upperValue)) { |
901 | solution[iSequence] = lowerValue; |
902 | value = lowerValue; |
903 | model_->setStatus(iSequence, ClpSimplex::atLowerBound); |
904 | } else { |
905 | solution[iSequence] = upperValue; |
906 | value = upperValue; |
907 | } |
908 | } |
909 | break; |
910 | case ClpSimplex::atLowerBound: |
911 | if (!toNearest) { |
912 | // With increasing tolerances - we may be at wrong place |
913 | if (fabs(value - lowerValue) > oldTolerance * 1.0001) { |
914 | if (fabs(value - upperValue) <= oldTolerance * 1.0001) { |
915 | if (fabs(value - upperValue) > primalTolerance) { |
916 | solution[iSequence] = upperValue; |
917 | value = upperValue; |
918 | } |
919 | model_->setStatus(iSequence, ClpSimplex::atUpperBound); |
920 | } else { |
921 | if (value < upperValue) { |
922 | if (value > lowerValue) { |
923 | model_->setStatus(iSequence, ClpSimplex::superBasic); |
924 | } else { |
925 | // set to lower bound as infeasible |
926 | solution[iSequence] = lowerValue; |
927 | value = lowerValue; |
928 | } |
929 | } else { |
930 | // set to upper bound as infeasible |
931 | solution[iSequence] = upperValue; |
932 | value = upperValue; |
933 | model_->setStatus(iSequence, ClpSimplex::atUpperBound); |
934 | } |
935 | } |
936 | } else if (fabs(value - lowerValue) > primalTolerance) { |
937 | solution[iSequence] = lowerValue; |
938 | value = lowerValue; |
939 | } |
940 | } else { |
941 | // Set to nearest and make at bound |
942 | if (fabs(value - lowerValue) < fabs(value - upperValue)) { |
943 | solution[iSequence] = lowerValue; |
944 | value = lowerValue; |
945 | } else { |
946 | solution[iSequence] = upperValue; |
947 | value = upperValue; |
948 | model_->setStatus(iSequence, ClpSimplex::atUpperBound); |
949 | } |
950 | } |
951 | break; |
952 | case ClpSimplex::isFixed: |
953 | solution[iSequence] = lowerValue; |
954 | value = lowerValue; |
955 | break; |
956 | } |
957 | #ifdef NONLIN_DEBUG |
958 | double lo = saveLower[iSequence]; |
959 | double up = saveUpper[iSequence]; |
960 | double cc = cost[iSequence]; |
961 | unsigned char ss = saveStatus[iSequence]; |
962 | unsigned char snow = model_->statusArray()[iSequence]; |
963 | #endif |
964 | if (iWhere != newWhere) { |
965 | setOriginalStatus(status_[iSequence], newWhere); |
966 | if (newWhere == CLP_BELOW_LOWER) { |
967 | bound_[iSequence] = upperValue; |
968 | upperValue = lowerValue; |
969 | lowerValue = -COIN_DBL_MAX; |
970 | costValue = trueCost - infeasibilityCost; |
971 | } else if (newWhere == CLP_ABOVE_UPPER) { |
972 | bound_[iSequence] = lowerValue; |
973 | lowerValue = upperValue; |
974 | upperValue = COIN_DBL_MAX; |
975 | costValue = trueCost + infeasibilityCost; |
976 | } else { |
977 | costValue = trueCost; |
978 | } |
979 | lower[iSequence] = lowerValue; |
980 | upper[iSequence] = upperValue; |
981 | } |
982 | // always do as other things may change |
983 | cost[iSequence] = costValue; |
984 | #ifdef NONLIN_DEBUG |
985 | if (method_ == 3) { |
986 | assert (ss == snow); |
987 | assert (cc == cost[iSequence]); |
988 | assert (lo == lower[iSequence]); |
989 | assert (up == upper[iSequence]); |
990 | assert (value == saveSolution[iSequence]); |
991 | } |
992 | #endif |
993 | feasibleCost_ += trueCost * value; |
994 | } |
995 | } |
996 | #ifdef NONLIN_DEBUG |
997 | if (method_ == 3) |
998 | assert (fabs(saveCost - feasibleCost_) < 0.001 * (1.0 + CoinMax(fabs(saveCost), fabs(feasibleCost_)))); |
999 | delete [] saveSolution; |
1000 | delete [] saveLower; |
1001 | delete [] saveUpper; |
1002 | delete [] saveStatus; |
1003 | #endif |
1004 | //feasibleCost_ /= (model_->rhsScale()*model_->objScale()); |
1005 | } |
1006 | // Puts feasible bounds into lower and upper |
1007 | void |
1008 | ClpNonLinearCost::feasibleBounds() |
1009 | { |
1010 | if (CLP_METHOD2) { |
1011 | int iSequence; |
1012 | double * upper = model_->upperRegion(); |
1013 | double * lower = model_->lowerRegion(); |
1014 | double * cost = model_->costRegion(); |
1015 | int numberTotal = numberColumns_ + numberRows_; |
1016 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
1017 | unsigned char iStatus = status_[iSequence]; |
1018 | assert (currentStatus(iStatus) == CLP_SAME); |
1019 | double lowerValue = lower[iSequence]; |
1020 | double upperValue = upper[iSequence]; |
1021 | double costValue = cost2_[iSequence]; |
1022 | int iWhere = originalStatus(iStatus); |
1023 | if (iWhere == CLP_BELOW_LOWER) { |
1024 | lowerValue = upperValue; |
1025 | upperValue = bound_[iSequence]; |
1026 | assert (fabs(lowerValue) < 1.0e100); |
1027 | } else if (iWhere == CLP_ABOVE_UPPER) { |
1028 | upperValue = lowerValue; |
1029 | lowerValue = bound_[iSequence]; |
1030 | } |
1031 | setOriginalStatus(status_[iSequence], CLP_FEASIBLE); |
1032 | lower[iSequence] = lowerValue; |
1033 | upper[iSequence] = upperValue; |
1034 | cost[iSequence] = costValue; |
1035 | } |
1036 | } |
1037 | } |
1038 | /* Goes through one bound for each variable. |
1039 | If array[i]*multiplier>0 goes down, otherwise up. |
1040 | The indices are row indices and need converting to sequences |
1041 | */ |
1042 | void |
1043 | ClpNonLinearCost::goThru(int numberInArray, double multiplier, |
1044 | const int * index, const double * array, |
1045 | double * rhs) |
1046 | { |
1047 | assert (model_ != NULL); |
1048 | abort(); |
1049 | const int * pivotVariable = model_->pivotVariable(); |
1050 | if (CLP_METHOD1) { |
1051 | for (int i = 0; i < numberInArray; i++) { |
1052 | int iRow = index[i]; |
1053 | int iSequence = pivotVariable[iRow]; |
1054 | double alpha = multiplier * array[iRow]; |
1055 | // get where in bound sequence |
1056 | int iRange = whichRange_[iSequence]; |
1057 | iRange += offset_[iSequence]; //add temporary bias |
1058 | double value = model_->solution(iSequence); |
1059 | if (alpha > 0.0) { |
1060 | // down one |
1061 | iRange--; |
1062 | assert(iRange >= start_[iSequence]); |
1063 | rhs[iRow] = value - lower_[iRange]; |
1064 | } else { |
1065 | // up one |
1066 | iRange++; |
1067 | assert(iRange < start_[iSequence+1] - 1); |
1068 | rhs[iRow] = lower_[iRange+1] - value; |
1069 | } |
1070 | offset_[iSequence] = iRange - whichRange_[iSequence]; |
1071 | } |
1072 | } |
1073 | #ifdef NONLIN_DEBUG |
1074 | double * saveRhs = NULL; |
1075 | if (method_ == 3) { |
1076 | int numberRows = model_->numberRows(); |
1077 | saveRhs = CoinCopyOfArray(rhs, numberRows); |
1078 | } |
1079 | #endif |
1080 | if (CLP_METHOD2) { |
1081 | const double * solution = model_->solutionRegion(); |
1082 | const double * upper = model_->upperRegion(); |
1083 | const double * lower = model_->lowerRegion(); |
1084 | for (int i = 0; i < numberInArray; i++) { |
1085 | int iRow = index[i]; |
1086 | int iSequence = pivotVariable[iRow]; |
1087 | double alpha = multiplier * array[iRow]; |
1088 | double value = solution[iSequence]; |
1089 | unsigned char iStatus = status_[iSequence]; |
1090 | int iWhere = currentStatus(iStatus); |
1091 | if (iWhere == CLP_SAME) |
1092 | iWhere = originalStatus(iStatus); |
1093 | if (iWhere == CLP_FEASIBLE) { |
1094 | if (alpha > 0.0) { |
1095 | // going below |
1096 | iWhere = CLP_BELOW_LOWER; |
1097 | rhs[iRow] = value - lower[iSequence]; |
1098 | } else { |
1099 | // going above |
1100 | iWhere = CLP_ABOVE_UPPER; |
1101 | rhs[iRow] = upper[iSequence] - value; |
1102 | } |
1103 | } else if(iWhere == CLP_BELOW_LOWER) { |
1104 | assert (alpha < 0); |
1105 | // going feasible |
1106 | iWhere = CLP_FEASIBLE; |
1107 | rhs[iRow] = upper[iSequence] - value; |
1108 | } else { |
1109 | assert (iWhere == CLP_ABOVE_UPPER); |
1110 | // going feasible |
1111 | iWhere = CLP_FEASIBLE; |
1112 | rhs[iRow] = value - lower[iSequence]; |
1113 | } |
1114 | #ifdef NONLIN_DEBUG |
1115 | if (method_ == 3) |
1116 | assert (rhs[iRow] == saveRhs[iRow]); |
1117 | #endif |
1118 | setCurrentStatus(status_[iSequence], iWhere); |
1119 | } |
1120 | } |
1121 | #ifdef NONLIN_DEBUG |
1122 | delete [] saveRhs; |
1123 | #endif |
1124 | } |
1125 | /* Takes off last iteration (i.e. offsets closer to 0) |
1126 | */ |
1127 | void |
1128 | ClpNonLinearCost::goBack(int numberInArray, const int * index, |
1129 | double * rhs) |
1130 | { |
1131 | assert (model_ != NULL); |
1132 | abort(); |
1133 | const int * pivotVariable = model_->pivotVariable(); |
1134 | if (CLP_METHOD1) { |
1135 | for (int i = 0; i < numberInArray; i++) { |
1136 | int iRow = index[i]; |
1137 | int iSequence = pivotVariable[iRow]; |
1138 | // get where in bound sequence |
1139 | int iRange = whichRange_[iSequence]; |
1140 | // get closer to original |
1141 | if (offset_[iSequence] > 0) { |
1142 | offset_[iSequence]--; |
1143 | assert (offset_[iSequence] >= 0); |
1144 | iRange += offset_[iSequence]; //add temporary bias |
1145 | double value = model_->solution(iSequence); |
1146 | // up one |
1147 | assert(iRange < start_[iSequence+1] - 1); |
1148 | rhs[iRow] = lower_[iRange+1] - value; // was earlier lower_[iRange] |
1149 | } else { |
1150 | offset_[iSequence]++; |
1151 | assert (offset_[iSequence] <= 0); |
1152 | iRange += offset_[iSequence]; //add temporary bias |
1153 | double value = model_->solution(iSequence); |
1154 | // down one |
1155 | assert(iRange >= start_[iSequence]); |
1156 | rhs[iRow] = value - lower_[iRange]; // was earlier lower_[iRange+1] |
1157 | } |
1158 | } |
1159 | } |
1160 | #ifdef NONLIN_DEBUG |
1161 | double * saveRhs = NULL; |
1162 | if (method_ == 3) { |
1163 | int numberRows = model_->numberRows(); |
1164 | saveRhs = CoinCopyOfArray(rhs, numberRows); |
1165 | } |
1166 | #endif |
1167 | if (CLP_METHOD2) { |
1168 | const double * solution = model_->solutionRegion(); |
1169 | const double * upper = model_->upperRegion(); |
1170 | const double * lower = model_->lowerRegion(); |
1171 | for (int i = 0; i < numberInArray; i++) { |
1172 | int iRow = index[i]; |
1173 | int iSequence = pivotVariable[iRow]; |
1174 | double value = solution[iSequence]; |
1175 | unsigned char iStatus = status_[iSequence]; |
1176 | int iWhere = currentStatus(iStatus); |
1177 | int original = originalStatus(iStatus); |
1178 | assert (iWhere != CLP_SAME); |
1179 | if (iWhere == CLP_FEASIBLE) { |
1180 | if (original == CLP_BELOW_LOWER) { |
1181 | // going below |
1182 | iWhere = CLP_BELOW_LOWER; |
1183 | rhs[iRow] = lower[iSequence] - value; |
1184 | } else { |
1185 | // going above |
1186 | iWhere = CLP_ABOVE_UPPER; |
1187 | rhs[iRow] = value - upper[iSequence]; |
1188 | } |
1189 | } else if(iWhere == CLP_BELOW_LOWER) { |
1190 | // going feasible |
1191 | iWhere = CLP_FEASIBLE; |
1192 | rhs[iRow] = value - upper[iSequence]; |
1193 | } else { |
1194 | // going feasible |
1195 | iWhere = CLP_FEASIBLE; |
1196 | rhs[iRow] = lower[iSequence] - value; |
1197 | } |
1198 | #ifdef NONLIN_DEBUG |
1199 | if (method_ == 3) |
1200 | assert (rhs[iRow] == saveRhs[iRow]); |
1201 | #endif |
1202 | setCurrentStatus(status_[iSequence], iWhere); |
1203 | } |
1204 | } |
1205 | #ifdef NONLIN_DEBUG |
1206 | delete [] saveRhs; |
1207 | #endif |
1208 | } |
1209 | void |
1210 | ClpNonLinearCost::goBackAll(const CoinIndexedVector * update) |
1211 | { |
1212 | assert (model_ != NULL); |
1213 | const int * pivotVariable = model_->pivotVariable(); |
1214 | int number = update->getNumElements(); |
1215 | const int * index = update->getIndices(); |
1216 | if (CLP_METHOD1) { |
1217 | for (int i = 0; i < number; i++) { |
1218 | int iRow = index[i]; |
1219 | int iSequence = pivotVariable[iRow]; |
1220 | offset_[iSequence] = 0; |
1221 | } |
1222 | #ifdef CLP_DEBUG |
1223 | for (i = 0; i < numberRows_ + numberColumns_; i++) |
1224 | assert(!offset_[i]); |
1225 | #endif |
1226 | } |
1227 | if (CLP_METHOD2) { |
1228 | for (int i = 0; i < number; i++) { |
1229 | int iRow = index[i]; |
1230 | int iSequence = pivotVariable[iRow]; |
1231 | setSameStatus(status_[iSequence]); |
1232 | } |
1233 | } |
1234 | } |
1235 | void |
1236 | ClpNonLinearCost::checkInfeasibilities(int numberInArray, const int * index) |
1237 | { |
1238 | assert (model_ != NULL); |
1239 | double primalTolerance = model_->currentPrimalTolerance(); |
1240 | const int * pivotVariable = model_->pivotVariable(); |
1241 | if (CLP_METHOD1) { |
1242 | for (int i = 0; i < numberInArray; i++) { |
1243 | int iRow = index[i]; |
1244 | int iSequence = pivotVariable[iRow]; |
1245 | // get where in bound sequence |
1246 | int iRange; |
1247 | int currentRange = whichRange_[iSequence]; |
1248 | double value = model_->solution(iSequence); |
1249 | int start = start_[iSequence]; |
1250 | int end = start_[iSequence+1] - 1; |
1251 | for (iRange = start; iRange < end; iRange++) { |
1252 | if (value < lower_[iRange+1] + primalTolerance) { |
1253 | // put in better range |
1254 | if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) |
1255 | iRange++; |
1256 | break; |
1257 | } |
1258 | } |
1259 | assert(iRange < end); |
1260 | assert(model_->getStatus(iSequence) == ClpSimplex::basic); |
1261 | double & lower = model_->lowerAddress(iSequence); |
1262 | double & upper = model_->upperAddress(iSequence); |
1263 | double & cost = model_->costAddress(iSequence); |
1264 | whichRange_[iSequence] = iRange; |
1265 | if (iRange != currentRange) { |
1266 | if (infeasible(iRange)) |
1267 | numberInfeasibilities_++; |
1268 | if (infeasible(currentRange)) |
1269 | numberInfeasibilities_--; |
1270 | } |
1271 | lower = lower_[iRange]; |
1272 | upper = lower_[iRange+1]; |
1273 | cost = cost_[iRange]; |
1274 | } |
1275 | } |
1276 | if (CLP_METHOD2) { |
1277 | double * solution = model_->solutionRegion(); |
1278 | double * upper = model_->upperRegion(); |
1279 | double * lower = model_->lowerRegion(); |
1280 | double * cost = model_->costRegion(); |
1281 | for (int i = 0; i < numberInArray; i++) { |
1282 | int iRow = index[i]; |
1283 | int iSequence = pivotVariable[iRow]; |
1284 | double value = solution[iSequence]; |
1285 | unsigned char iStatus = status_[iSequence]; |
1286 | assert (currentStatus(iStatus) == CLP_SAME); |
1287 | double lowerValue = lower[iSequence]; |
1288 | double upperValue = upper[iSequence]; |
1289 | double costValue = cost2_[iSequence]; |
1290 | int iWhere = originalStatus(iStatus); |
1291 | if (iWhere == CLP_BELOW_LOWER) { |
1292 | lowerValue = upperValue; |
1293 | upperValue = bound_[iSequence]; |
1294 | numberInfeasibilities_--; |
1295 | assert (fabs(lowerValue) < 1.0e100); |
1296 | } else if (iWhere == CLP_ABOVE_UPPER) { |
1297 | upperValue = lowerValue; |
1298 | lowerValue = bound_[iSequence]; |
1299 | numberInfeasibilities_--; |
1300 | } |
1301 | // get correct place |
1302 | int newWhere = CLP_FEASIBLE; |
1303 | if (value - upperValue <= primalTolerance) { |
1304 | if (value - lowerValue >= -primalTolerance) { |
1305 | // feasible |
1306 | //newWhere=CLP_FEASIBLE; |
1307 | } else { |
1308 | // below |
1309 | newWhere = CLP_BELOW_LOWER; |
1310 | assert (fabs(lowerValue) < 1.0e100); |
1311 | costValue -= infeasibilityWeight_; |
1312 | numberInfeasibilities_++; |
1313 | } |
1314 | } else { |
1315 | // above |
1316 | newWhere = CLP_ABOVE_UPPER; |
1317 | costValue += infeasibilityWeight_; |
1318 | numberInfeasibilities_++; |
1319 | } |
1320 | if (iWhere != newWhere) { |
1321 | setOriginalStatus(status_[iSequence], newWhere); |
1322 | if (newWhere == CLP_BELOW_LOWER) { |
1323 | bound_[iSequence] = upperValue; |
1324 | upperValue = lowerValue; |
1325 | lowerValue = -COIN_DBL_MAX; |
1326 | } else if (newWhere == CLP_ABOVE_UPPER) { |
1327 | bound_[iSequence] = lowerValue; |
1328 | lowerValue = upperValue; |
1329 | upperValue = COIN_DBL_MAX; |
1330 | } |
1331 | lower[iSequence] = lowerValue; |
1332 | upper[iSequence] = upperValue; |
1333 | cost[iSequence] = costValue; |
1334 | } |
1335 | } |
1336 | } |
1337 | } |
1338 | /* Puts back correct infeasible costs for each variable |
1339 | The input indices are row indices and need converting to sequences |
1340 | for costs. |
1341 | On input array is empty (but indices exist). On exit just |
1342 | changed costs will be stored as normal CoinIndexedVector |
1343 | */ |
1344 | void |
1345 | ClpNonLinearCost::checkChanged(int numberInArray, CoinIndexedVector * update) |
1346 | { |
1347 | assert (model_ != NULL); |
1348 | double primalTolerance = model_->currentPrimalTolerance(); |
1349 | const int * pivotVariable = model_->pivotVariable(); |
1350 | int number = 0; |
1351 | int * index = update->getIndices(); |
1352 | double * work = update->denseVector(); |
1353 | if (CLP_METHOD1) { |
1354 | for (int i = 0; i < numberInArray; i++) { |
1355 | int iRow = index[i]; |
1356 | int iSequence = pivotVariable[iRow]; |
1357 | // get where in bound sequence |
1358 | int iRange; |
1359 | double value = model_->solution(iSequence); |
1360 | int start = start_[iSequence]; |
1361 | int end = start_[iSequence+1] - 1; |
1362 | for (iRange = start; iRange < end; iRange++) { |
1363 | if (value < lower_[iRange+1] + primalTolerance) { |
1364 | // put in better range |
1365 | if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) |
1366 | iRange++; |
1367 | break; |
1368 | } |
1369 | } |
1370 | assert(iRange < end); |
1371 | assert(model_->getStatus(iSequence) == ClpSimplex::basic); |
1372 | int jRange = whichRange_[iSequence]; |
1373 | if (iRange != jRange) { |
1374 | // changed |
1375 | work[iRow] = cost_[jRange] - cost_[iRange]; |
1376 | index[number++] = iRow; |
1377 | double & lower = model_->lowerAddress(iSequence); |
1378 | double & upper = model_->upperAddress(iSequence); |
1379 | double & cost = model_->costAddress(iSequence); |
1380 | whichRange_[iSequence] = iRange; |
1381 | if (infeasible(iRange)) |
1382 | numberInfeasibilities_++; |
1383 | if (infeasible(jRange)) |
1384 | numberInfeasibilities_--; |
1385 | lower = lower_[iRange]; |
1386 | upper = lower_[iRange+1]; |
1387 | cost = cost_[iRange]; |
1388 | } |
1389 | } |
1390 | } |
1391 | if (CLP_METHOD2) { |
1392 | double * solution = model_->solutionRegion(); |
1393 | double * upper = model_->upperRegion(); |
1394 | double * lower = model_->lowerRegion(); |
1395 | double * cost = model_->costRegion(); |
1396 | for (int i = 0; i < numberInArray; i++) { |
1397 | int iRow = index[i]; |
1398 | int iSequence = pivotVariable[iRow]; |
1399 | double value = solution[iSequence]; |
1400 | unsigned char iStatus = status_[iSequence]; |
1401 | assert (currentStatus(iStatus) == CLP_SAME); |
1402 | double lowerValue = lower[iSequence]; |
1403 | double upperValue = upper[iSequence]; |
1404 | double costValue = cost2_[iSequence]; |
1405 | int iWhere = originalStatus(iStatus); |
1406 | if (iWhere == CLP_BELOW_LOWER) { |
1407 | lowerValue = upperValue; |
1408 | upperValue = bound_[iSequence]; |
1409 | numberInfeasibilities_--; |
1410 | assert (fabs(lowerValue) < 1.0e100); |
1411 | } else if (iWhere == CLP_ABOVE_UPPER) { |
1412 | upperValue = lowerValue; |
1413 | lowerValue = bound_[iSequence]; |
1414 | numberInfeasibilities_--; |
1415 | } |
1416 | // get correct place |
1417 | int newWhere = CLP_FEASIBLE; |
1418 | if (value - upperValue <= primalTolerance) { |
1419 | if (value - lowerValue >= -primalTolerance) { |
1420 | // feasible |
1421 | //newWhere=CLP_FEASIBLE; |
1422 | } else { |
1423 | // below |
1424 | newWhere = CLP_BELOW_LOWER; |
1425 | costValue -= infeasibilityWeight_; |
1426 | numberInfeasibilities_++; |
1427 | assert (fabs(lowerValue) < 1.0e100); |
1428 | } |
1429 | } else { |
1430 | // above |
1431 | newWhere = CLP_ABOVE_UPPER; |
1432 | costValue += infeasibilityWeight_; |
1433 | numberInfeasibilities_++; |
1434 | } |
1435 | if (iWhere != newWhere) { |
1436 | work[iRow] = cost[iSequence] - costValue; |
1437 | index[number++] = iRow; |
1438 | setOriginalStatus(status_[iSequence], newWhere); |
1439 | if (newWhere == CLP_BELOW_LOWER) { |
1440 | bound_[iSequence] = upperValue; |
1441 | upperValue = lowerValue; |
1442 | lowerValue = -COIN_DBL_MAX; |
1443 | } else if (newWhere == CLP_ABOVE_UPPER) { |
1444 | bound_[iSequence] = lowerValue; |
1445 | lowerValue = upperValue; |
1446 | upperValue = COIN_DBL_MAX; |
1447 | } |
1448 | lower[iSequence] = lowerValue; |
1449 | upper[iSequence] = upperValue; |
1450 | cost[iSequence] = costValue; |
1451 | } |
1452 | } |
1453 | } |
1454 | update->setNumElements(number); |
1455 | } |
1456 | /* Sets bounds and cost for one variable - returns change in cost*/ |
1457 | double |
1458 | ClpNonLinearCost::setOne(int iSequence, double value) |
1459 | { |
1460 | assert (model_ != NULL); |
1461 | double primalTolerance = model_->currentPrimalTolerance(); |
1462 | // difference in cost |
1463 | double difference = 0.0; |
1464 | if (CLP_METHOD1) { |
1465 | // get where in bound sequence |
1466 | int iRange; |
1467 | int currentRange = whichRange_[iSequence]; |
1468 | int start = start_[iSequence]; |
1469 | int end = start_[iSequence+1] - 1; |
1470 | if (!bothWays_) { |
1471 | // If fixed try and get feasible |
1472 | if (lower_[start+1] == lower_[start+2] && fabs(value - lower_[start+1]) < 1.001 * primalTolerance) { |
1473 | iRange = start + 1; |
1474 | } else { |
1475 | for (iRange = start; iRange < end; iRange++) { |
1476 | if (value <= lower_[iRange+1] + primalTolerance) { |
1477 | // put in better range |
1478 | if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) |
1479 | iRange++; |
1480 | break; |
1481 | } |
1482 | } |
1483 | } |
1484 | } else { |
1485 | // leave in current if possible |
1486 | iRange = whichRange_[iSequence]; |
1487 | if (value < lower_[iRange] - primalTolerance || value > lower_[iRange+1] + primalTolerance) { |
1488 | for (iRange = start; iRange < end; iRange++) { |
1489 | if (value < lower_[iRange+1] + primalTolerance) { |
1490 | // put in better range |
1491 | if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) |
1492 | iRange++; |
1493 | break; |
1494 | } |
1495 | } |
1496 | } |
1497 | } |
1498 | assert(iRange < end); |
1499 | whichRange_[iSequence] = iRange; |
1500 | if (iRange != currentRange) { |
1501 | if (infeasible(iRange)) |
1502 | numberInfeasibilities_++; |
1503 | if (infeasible(currentRange)) |
1504 | numberInfeasibilities_--; |
1505 | } |
1506 | double & lower = model_->lowerAddress(iSequence); |
1507 | double & upper = model_->upperAddress(iSequence); |
1508 | double & cost = model_->costAddress(iSequence); |
1509 | lower = lower_[iRange]; |
1510 | upper = lower_[iRange+1]; |
1511 | ClpSimplex::Status status = model_->getStatus(iSequence); |
1512 | if (upper == lower) { |
1513 | if (status != ClpSimplex::basic) { |
1514 | model_->setStatus(iSequence, ClpSimplex::isFixed); |
1515 | status = ClpSimplex::basic; // so will skip |
1516 | } |
1517 | } |
1518 | switch(status) { |
1519 | |
1520 | case ClpSimplex::basic: |
1521 | case ClpSimplex::superBasic: |
1522 | case ClpSimplex::isFree: |
1523 | break; |
1524 | case ClpSimplex::atUpperBound: |
1525 | case ClpSimplex::atLowerBound: |
1526 | case ClpSimplex::isFixed: |
1527 | // set correctly |
1528 | if (fabs(value - lower) <= primalTolerance * 1.001) { |
1529 | model_->setStatus(iSequence, ClpSimplex::atLowerBound); |
1530 | } else if (fabs(value - upper) <= primalTolerance * 1.001) { |
1531 | model_->setStatus(iSequence, ClpSimplex::atUpperBound); |
1532 | } else { |
1533 | // set superBasic |
1534 | model_->setStatus(iSequence, ClpSimplex::superBasic); |
1535 | } |
1536 | break; |
1537 | } |
1538 | difference = cost - cost_[iRange]; |
1539 | cost = cost_[iRange]; |
1540 | } |
1541 | if (CLP_METHOD2) { |
1542 | double * upper = model_->upperRegion(); |
1543 | double * lower = model_->lowerRegion(); |
1544 | double * cost = model_->costRegion(); |
1545 | unsigned char iStatus = status_[iSequence]; |
1546 | assert (currentStatus(iStatus) == CLP_SAME); |
1547 | double lowerValue = lower[iSequence]; |
1548 | double upperValue = upper[iSequence]; |
1549 | double costValue = cost2_[iSequence]; |
1550 | int iWhere = originalStatus(iStatus); |
1551 | if (iWhere == CLP_BELOW_LOWER) { |
1552 | lowerValue = upperValue; |
1553 | upperValue = bound_[iSequence]; |
1554 | numberInfeasibilities_--; |
1555 | assert (fabs(lowerValue) < 1.0e100); |
1556 | } else if (iWhere == CLP_ABOVE_UPPER) { |
1557 | upperValue = lowerValue; |
1558 | lowerValue = bound_[iSequence]; |
1559 | numberInfeasibilities_--; |
1560 | } |
1561 | // get correct place |
1562 | int newWhere = CLP_FEASIBLE; |
1563 | if (value - upperValue <= primalTolerance) { |
1564 | if (value - lowerValue >= -primalTolerance) { |
1565 | // feasible |
1566 | //newWhere=CLP_FEASIBLE; |
1567 | } else { |
1568 | // below |
1569 | newWhere = CLP_BELOW_LOWER; |
1570 | costValue -= infeasibilityWeight_; |
1571 | numberInfeasibilities_++; |
1572 | assert (fabs(lowerValue) < 1.0e100); |
1573 | } |
1574 | } else { |
1575 | // above |
1576 | newWhere = CLP_ABOVE_UPPER; |
1577 | costValue += infeasibilityWeight_; |
1578 | numberInfeasibilities_++; |
1579 | } |
1580 | if (iWhere != newWhere) { |
1581 | difference = cost[iSequence] - costValue; |
1582 | setOriginalStatus(status_[iSequence], newWhere); |
1583 | if (newWhere == CLP_BELOW_LOWER) { |
1584 | bound_[iSequence] = upperValue; |
1585 | upperValue = lowerValue; |
1586 | lowerValue = -COIN_DBL_MAX; |
1587 | } else if (newWhere == CLP_ABOVE_UPPER) { |
1588 | bound_[iSequence] = lowerValue; |
1589 | lowerValue = upperValue; |
1590 | upperValue = COIN_DBL_MAX; |
1591 | } |
1592 | lower[iSequence] = lowerValue; |
1593 | upper[iSequence] = upperValue; |
1594 | cost[iSequence] = costValue; |
1595 | } |
1596 | ClpSimplex::Status status = model_->getStatus(iSequence); |
1597 | if (upperValue == lowerValue) { |
1598 | if (status != ClpSimplex::basic) { |
1599 | model_->setStatus(iSequence, ClpSimplex::isFixed); |
1600 | status = ClpSimplex::basic; // so will skip |
1601 | } |
1602 | } |
1603 | switch(status) { |
1604 | |
1605 | case ClpSimplex::basic: |
1606 | case ClpSimplex::superBasic: |
1607 | case ClpSimplex::isFree: |
1608 | break; |
1609 | case ClpSimplex::atUpperBound: |
1610 | case ClpSimplex::atLowerBound: |
1611 | case ClpSimplex::isFixed: |
1612 | // set correctly |
1613 | if (fabs(value - lowerValue) <= primalTolerance * 1.001) { |
1614 | model_->setStatus(iSequence, ClpSimplex::atLowerBound); |
1615 | } else if (fabs(value - upperValue) <= primalTolerance * 1.001) { |
1616 | model_->setStatus(iSequence, ClpSimplex::atUpperBound); |
1617 | } else { |
1618 | // set superBasic |
1619 | model_->setStatus(iSequence, ClpSimplex::superBasic); |
1620 | } |
1621 | break; |
1622 | } |
1623 | } |
1624 | changeCost_ += value * difference; |
1625 | return difference; |
1626 | } |
1627 | /* Sets bounds and infeasible cost and true cost for one variable |
1628 | This is for gub and column generation etc */ |
1629 | void |
1630 | ClpNonLinearCost::setOne(int sequence, double solutionValue, double lowerValue, double upperValue, |
1631 | double costValue) |
1632 | { |
1633 | if (CLP_METHOD1) { |
1634 | int iRange = -1; |
1635 | int start = start_[sequence]; |
1636 | double infeasibilityCost = model_->infeasibilityCost(); |
1637 | cost_[start] = costValue - infeasibilityCost; |
1638 | lower_[start+1] = lowerValue; |
1639 | cost_[start+1] = costValue; |
1640 | lower_[start+2] = upperValue; |
1641 | cost_[start+2] = costValue + infeasibilityCost; |
1642 | double primalTolerance = model_->currentPrimalTolerance(); |
1643 | if (solutionValue - lowerValue >= -primalTolerance) { |
1644 | if (solutionValue - upperValue <= primalTolerance) { |
1645 | iRange = start + 1; |
1646 | } else { |
1647 | iRange = start + 2; |
1648 | } |
1649 | } else { |
1650 | iRange = start; |
1651 | } |
1652 | model_->costRegion()[sequence] = cost_[iRange]; |
1653 | whichRange_[sequence] = iRange; |
1654 | } |
1655 | if (CLP_METHOD2) { |
1656 | abort(); // may never work |
1657 | } |
1658 | |
1659 | } |
1660 | /* Sets bounds and cost for outgoing variable |
1661 | may change value |
1662 | Returns direction */ |
1663 | int |
1664 | ClpNonLinearCost::setOneOutgoing(int iSequence, double & value) |
1665 | { |
1666 | assert (model_ != NULL); |
1667 | double primalTolerance = model_->currentPrimalTolerance(); |
1668 | // difference in cost |
1669 | double difference = 0.0; |
1670 | int direction = 0; |
1671 | if (CLP_METHOD1) { |
1672 | // get where in bound sequence |
1673 | int iRange; |
1674 | int currentRange = whichRange_[iSequence]; |
1675 | int start = start_[iSequence]; |
1676 | int end = start_[iSequence+1] - 1; |
1677 | // Set perceived direction out |
1678 | if (value <= lower_[currentRange] + 1.001 * primalTolerance) { |
1679 | direction = 1; |
1680 | } else if (value >= lower_[currentRange+1] - 1.001 * primalTolerance) { |
1681 | direction = -1; |
1682 | } else { |
1683 | // odd |
1684 | direction = 0; |
1685 | } |
1686 | // If fixed try and get feasible |
1687 | if (lower_[start+1] == lower_[start+2] && fabs(value - lower_[start+1]) < 1.001 * primalTolerance) { |
1688 | iRange = start + 1; |
1689 | } else { |
1690 | // See if exact |
1691 | for (iRange = start; iRange < end; iRange++) { |
1692 | if (value == lower_[iRange+1]) { |
1693 | // put in better range |
1694 | if (infeasible(iRange) && iRange == start) |
1695 | iRange++; |
1696 | break; |
1697 | } |
1698 | } |
1699 | if (iRange == end) { |
1700 | // not exact |
1701 | for (iRange = start; iRange < end; iRange++) { |
1702 | if (value <= lower_[iRange+1] + primalTolerance) { |
1703 | // put in better range |
1704 | if (value >= lower_[iRange+1] - primalTolerance && infeasible(iRange) && iRange == start) |
1705 | iRange++; |
1706 | break; |
1707 | } |
1708 | } |
1709 | } |
1710 | } |
1711 | assert(iRange < end); |
1712 | whichRange_[iSequence] = iRange; |
1713 | if (iRange != currentRange) { |
1714 | if (infeasible(iRange)) |
1715 | numberInfeasibilities_++; |
1716 | if (infeasible(currentRange)) |
1717 | numberInfeasibilities_--; |
1718 | } |
1719 | double & lower = model_->lowerAddress(iSequence); |
1720 | double & upper = model_->upperAddress(iSequence); |
1721 | double & cost = model_->costAddress(iSequence); |
1722 | lower = lower_[iRange]; |
1723 | upper = lower_[iRange+1]; |
1724 | if (upper == lower) { |
1725 | value = upper; |
1726 | } else { |
1727 | // set correctly |
1728 | if (fabs(value - lower) <= primalTolerance * 1.001) { |
1729 | value = CoinMin(value, lower + primalTolerance); |
1730 | } else if (fabs(value - upper) <= primalTolerance * 1.001) { |
1731 | value = CoinMax(value, upper - primalTolerance); |
1732 | } else { |
1733 | //printf("*** variable wandered off bound %g %g %g!\n", |
1734 | // lower,value,upper); |
1735 | if (value - lower <= upper - value) |
1736 | value = lower + primalTolerance; |
1737 | else |
1738 | value = upper - primalTolerance; |
1739 | } |
1740 | } |
1741 | difference = cost - cost_[iRange]; |
1742 | cost = cost_[iRange]; |
1743 | } |
1744 | if (CLP_METHOD2) { |
1745 | double * upper = model_->upperRegion(); |
1746 | double * lower = model_->lowerRegion(); |
1747 | double * cost = model_->costRegion(); |
1748 | unsigned char iStatus = status_[iSequence]; |
1749 | assert (currentStatus(iStatus) == CLP_SAME); |
1750 | double lowerValue = lower[iSequence]; |
1751 | double upperValue = upper[iSequence]; |
1752 | double costValue = cost2_[iSequence]; |
1753 | // Set perceived direction out |
1754 | if (value <= lowerValue + 1.001 * primalTolerance) { |
1755 | direction = 1; |
1756 | } else if (value >= upperValue - 1.001 * primalTolerance) { |
1757 | direction = -1; |
1758 | } else { |
1759 | // odd |
1760 | direction = 0; |
1761 | } |
1762 | int iWhere = originalStatus(iStatus); |
1763 | if (iWhere == CLP_BELOW_LOWER) { |
1764 | lowerValue = upperValue; |
1765 | upperValue = bound_[iSequence]; |
1766 | numberInfeasibilities_--; |
1767 | assert (fabs(lowerValue) < 1.0e100); |
1768 | } else if (iWhere == CLP_ABOVE_UPPER) { |
1769 | upperValue = lowerValue; |
1770 | lowerValue = bound_[iSequence]; |
1771 | numberInfeasibilities_--; |
1772 | } |
1773 | // get correct place |
1774 | // If fixed give benefit of doubt |
1775 | if (lowerValue == upperValue) |
1776 | value = lowerValue; |
1777 | int newWhere = CLP_FEASIBLE; |
1778 | if (value - upperValue <= primalTolerance) { |
1779 | if (value - lowerValue >= -primalTolerance) { |
1780 | // feasible |
1781 | //newWhere=CLP_FEASIBLE; |
1782 | } else { |
1783 | // below |
1784 | newWhere = CLP_BELOW_LOWER; |
1785 | costValue -= infeasibilityWeight_; |
1786 | numberInfeasibilities_++; |
1787 | assert (fabs(lowerValue) < 1.0e100); |
1788 | } |
1789 | } else { |
1790 | // above |
1791 | newWhere = CLP_ABOVE_UPPER; |
1792 | costValue += infeasibilityWeight_; |
1793 | numberInfeasibilities_++; |
1794 | } |
1795 | if (iWhere != newWhere) { |
1796 | difference = cost[iSequence] - costValue; |
1797 | setOriginalStatus(status_[iSequence], newWhere); |
1798 | if (newWhere == CLP_BELOW_LOWER) { |
1799 | bound_[iSequence] = upperValue; |
1800 | upper[iSequence] = lowerValue; |
1801 | lower[iSequence] = -COIN_DBL_MAX; |
1802 | } else if (newWhere == CLP_ABOVE_UPPER) { |
1803 | bound_[iSequence] = lowerValue; |
1804 | lower[iSequence] = upperValue; |
1805 | upper[iSequence] = COIN_DBL_MAX; |
1806 | } else { |
1807 | lower[iSequence] = lowerValue; |
1808 | upper[iSequence] = upperValue; |
1809 | } |
1810 | cost[iSequence] = costValue; |
1811 | } |
1812 | // set correctly |
1813 | if (fabs(value - lowerValue) <= primalTolerance * 1.001) { |
1814 | value = CoinMin(value, lowerValue + primalTolerance); |
1815 | } else if (fabs(value - upperValue) <= primalTolerance * 1.001) { |
1816 | value = CoinMax(value, upperValue - primalTolerance); |
1817 | } else { |
1818 | //printf("*** variable wandered off bound %g %g %g!\n", |
1819 | // lowerValue,value,upperValue); |
1820 | if (value - lowerValue <= upperValue - value) |
1821 | value = lowerValue + primalTolerance; |
1822 | else |
1823 | value = upperValue - primalTolerance; |
1824 | } |
1825 | } |
1826 | changeCost_ += value * difference; |
1827 | return direction; |
1828 | } |
1829 | // Returns nearest bound |
1830 | double |
1831 | ClpNonLinearCost::nearest(int iSequence, double solutionValue) |
1832 | { |
1833 | assert (model_ != NULL); |
1834 | double nearest = 0.0; |
1835 | if (CLP_METHOD1) { |
1836 | // get where in bound sequence |
1837 | int iRange; |
1838 | int start = start_[iSequence]; |
1839 | int end = start_[iSequence+1]; |
1840 | int jRange = -1; |
1841 | nearest = COIN_DBL_MAX; |
1842 | for (iRange = start; iRange < end; iRange++) { |
1843 | if (fabs(solutionValue - lower_[iRange]) < nearest) { |
1844 | jRange = iRange; |
1845 | nearest = fabs(solutionValue - lower_[iRange]); |
1846 | } |
1847 | } |
1848 | assert(jRange < end); |
1849 | nearest = lower_[jRange]; |
1850 | } |
1851 | if (CLP_METHOD2) { |
1852 | const double * upper = model_->upperRegion(); |
1853 | const double * lower = model_->lowerRegion(); |
1854 | double lowerValue = lower[iSequence]; |
1855 | double upperValue = upper[iSequence]; |
1856 | int iWhere = originalStatus(status_[iSequence]); |
1857 | if (iWhere == CLP_BELOW_LOWER) { |
1858 | lowerValue = upperValue; |
1859 | upperValue = bound_[iSequence]; |
1860 | assert (fabs(lowerValue) < 1.0e100); |
1861 | } else if (iWhere == CLP_ABOVE_UPPER) { |
1862 | upperValue = lowerValue; |
1863 | lowerValue = bound_[iSequence]; |
1864 | } |
1865 | if (fabs(solutionValue - lowerValue) < fabs(solutionValue - upperValue)) |
1866 | nearest = lowerValue; |
1867 | else |
1868 | nearest = upperValue; |
1869 | } |
1870 | return nearest; |
1871 | } |
1872 | /// Feasible cost with offset and direction (i.e. for reporting) |
1873 | double |
1874 | ClpNonLinearCost::feasibleReportCost() const |
1875 | { |
1876 | double value; |
1877 | model_->getDblParam(ClpObjOffset, value); |
1878 | return (feasibleCost_ + model_->objectiveAsObject()->nonlinearOffset()) * model_->optimizationDirection() / |
1879 | (model_->objectiveScale() * model_->rhsScale()) - value; |
1880 | } |
1881 | // Get rid of real costs (just for moment) |
1882 | void |
1883 | ClpNonLinearCost::zapCosts() |
1884 | { |
1885 | int iSequence; |
1886 | double infeasibilityCost = model_->infeasibilityCost(); |
1887 | // zero out all costs |
1888 | int numberTotal = numberColumns_ + numberRows_; |
1889 | if (CLP_METHOD1) { |
1890 | int n = start_[numberTotal]; |
1891 | memset(cost_, 0, n * sizeof(double)); |
1892 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
1893 | int start = start_[iSequence]; |
1894 | int end = start_[iSequence+1] - 1; |
1895 | // correct costs for this infeasibility weight |
1896 | if (infeasible(start)) { |
1897 | cost_[start] = -infeasibilityCost; |
1898 | } |
1899 | if (infeasible(end - 1)) { |
1900 | cost_[end-1] = infeasibilityCost; |
1901 | } |
1902 | } |
1903 | } |
1904 | if (CLP_METHOD2) { |
1905 | } |
1906 | } |
1907 | #ifdef VALIDATE |
1908 | // For debug |
1909 | void |
1910 | ClpNonLinearCost::validate() |
1911 | { |
1912 | double primalTolerance = model_->currentPrimalTolerance(); |
1913 | int iSequence; |
1914 | const double * solution = model_->solutionRegion(); |
1915 | const double * upper = model_->upperRegion(); |
1916 | const double * lower = model_->lowerRegion(); |
1917 | const double * cost = model_->costRegion(); |
1918 | double infeasibilityCost = model_->infeasibilityCost(); |
1919 | int numberTotal = numberRows_ + numberColumns_; |
1920 | int numberInfeasibilities = 0; |
1921 | double sumInfeasibilities = 0.0; |
1922 | |
1923 | for (iSequence = 0; iSequence < numberTotal; iSequence++) { |
1924 | double value = solution[iSequence]; |
1925 | int iStatus = status_[iSequence]; |
1926 | assert (currentStatus(iStatus) == CLP_SAME); |
1927 | double lowerValue = lower[iSequence]; |
1928 | double upperValue = upper[iSequence]; |
1929 | double costValue = cost2_[iSequence]; |
1930 | int iWhere = originalStatus(iStatus); |
1931 | if (iWhere == CLP_BELOW_LOWER) { |
1932 | lowerValue = upperValue; |
1933 | upperValue = bound_[iSequence]; |
1934 | assert (fabs(lowerValue) < 1.0e100); |
1935 | costValue -= infeasibilityCost; |
1936 | assert (value <= lowerValue - primalTolerance); |
1937 | numberInfeasibilities++; |
1938 | sumInfeasibilities += lowerValue - value - primalTolerance; |
1939 | assert (model_->getStatus(iSequence) == ClpSimplex::basic); |
1940 | } else if (iWhere == CLP_ABOVE_UPPER) { |
1941 | upperValue = lowerValue; |
1942 | lowerValue = bound_[iSequence]; |
1943 | costValue += infeasibilityCost; |
1944 | assert (value >= upperValue + primalTolerance); |
1945 | numberInfeasibilities++; |
1946 | sumInfeasibilities += value - upperValue - primalTolerance; |
1947 | assert (model_->getStatus(iSequence) == ClpSimplex::basic); |
1948 | } else { |
1949 | assert (value >= lowerValue - primalTolerance && value <= upperValue + primalTolerance); |
1950 | } |
1951 | assert (lowerValue == saveLowerV[iSequence]); |
1952 | assert (upperValue == saveUpperV[iSequence]); |
1953 | assert (costValue == cost[iSequence]); |
1954 | } |
1955 | if (numberInfeasibilities) |
1956 | printf("JJ %d infeasibilities summing to %g\n" , |
1957 | numberInfeasibilities, sumInfeasibilities); |
1958 | } |
1959 | #endif |
1960 | |