1 /* $Id: ClpSimplexDual.cpp 2468 2019-05-03 04:31:14Z 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 /* Notes on implementation of dual simplex algorithm.
7
8 When dual feasible:
9
10 If primal feasible, we are optimal. Otherwise choose an infeasible
11 basic variable to leave basis (normally going to nearest bound) (B). We
12 now need to find an incoming variable which will leave problem
13 dual feasible so we get the row of the tableau corresponding to
14 the basic variable (with the correct sign depending if basic variable
15 above or below feasibility region - as that affects whether reduced
16 cost on outgoing variable has to be positive or negative).
17
18 We now perform a ratio test to determine which incoming variable will
19 preserve dual feasibility (C). If no variable found then problem
20 is infeasible (in primal sense). If there is a variable, we then
21 perform pivot and repeat. Trivial?
22
23 -------------------------------------------
24
25 A) How do we get dual feasible? If all variables have bounds then
26 it is trivial to get feasible by putting non-basic variables to
27 correct bounds. OSL did not have a phase 1/phase 2 approach but
28 instead effectively put fake bounds on variables and this is the
29 approach here, although I had hoped to make it cleaner.
30
31 If there is a weight of X on getting dual feasible:
32 Non-basic variables with negative reduced costs are put to
33 lesser of their upper bound and their lower bound + X.
34 Similarly, mutatis mutandis, for positive reduced costs.
35
36 Free variables should normally be in basis, otherwise I have
37 coding which may be able to come out (and may not be correct).
38
39 In OSL, this weight was changed heuristically, here at present
40 it is only increased if problem looks finished. If problem is
41 feasible I check for unboundedness. If not unbounded we
42 could play with going into primal. As long as weights increase
43 any algorithm would be finite.
44
45 B) Which outgoing variable to choose is a virtual base class.
46 For difficult problems steepest edge is preferred while for
47 very easy (large) problems we will need partial scan.
48
49 C) Sounds easy, but this is hardest part of algorithm.
50 1) Instead of stopping at first choice, we may be able
51 to flip that variable to other bound and if objective
52 still improving choose again. These mini iterations can
53 increase speed by orders of magnitude but we may need to
54 go to more of a bucket choice of variable rather than looking
55 at them one by one (for speed).
56 2) Accuracy. Reduced costs may be of wrong sign but less than
57 tolerance. Pivoting on these makes objective go backwards.
58 OSL modified cost so a zero move was made, Gill et al
59 (in primal analogue) modified so a strictly positive move was
60 made. It is not quite as neat in dual but that is what we
61 try and do. The two problems are that re-factorizations can
62 change reduced costs above and below tolerances and that when
63 finished we need to reset costs and try again.
64 3) Degeneracy. Gill et al helps but may not be enough. We
65 may need more. Also it can improve speed a lot if we perturb
66 the costs significantly.
67
68 References:
69 Forrest and Goldfarb, Steepest-edge simplex algorithms for
70 linear programming - Mathematical Programming 1992
71 Forrest and Tomlin, Implementing the simplex method for
72 the Optimization Subroutine Library - IBM Systems Journal 1992
73 Gill, Murray, Saunders, Wright A Practical Anti-Cycling
74 Procedure for Linear and Nonlinear Programming SOL report 1988
75
76
77 TODO:
78
79 a) Better recovery procedures. At present I never check on forward
80 progress. There is checkpoint/restart with reducing
81 re-factorization frequency, but this is only on singular
82 factorizations.
83 b) Fast methods for large easy problems (and also the option for
84 the code to automatically choose which method).
85 c) We need to be able to stop in various ways for OSI - this
86 is fairly easy.
87
88 */
89 #ifdef COIN_DEVELOP
90 #undef COIN_DEVELOP
91 #define COIN_DEVELOP 2
92 #endif
93
94 #include "CoinPragma.hpp"
95
96 #include <math.h>
97
98 #include "CoinHelperFunctions.hpp"
99 #include "ClpHelperFunctions.hpp"
100 #if ABOCA_LITE
101 // 2 is owner of abcState_
102 #define ABCSTATE_LITE 2
103 #endif
104 //#define FAKE_CILK
105 #include "ClpSimplexDual.hpp"
106 #include "ClpEventHandler.hpp"
107 #include "ClpFactorization.hpp"
108 #include "CoinPackedMatrix.hpp"
109 #include "CoinIndexedVector.hpp"
110 #include "CoinFloatEqual.hpp"
111 #include "ClpDualRowDantzig.hpp"
112 #include "ClpMessage.hpp"
113 #include "ClpLinearObjective.hpp"
114 #include <cfloat>
115 #include <cassert>
116 #include <string>
117 #include <stdio.h>
118 #include <iostream>
119 //#define CLP_DEBUG 1
120 // To force to follow another run put logfile name here and define
121 //#define FORCE_FOLLOW
122 #ifdef FORCE_FOLLOW
123 static FILE *fpFollow = NULL;
124 static char *forceFile = "old.log";
125 static int force_in = -1;
126 static int force_out = -1;
127 static int force_iteration = 0;
128 #endif
129 //#define VUB
130 #ifdef VUB
131 extern int *vub;
132 extern int *toVub;
133 extern int *nextDescendent;
134 #endif
135 #ifdef NDEBUG
136 #define NDEBUG_CLP
137 #endif
138 #ifndef CLP_INVESTIGATE
139 #define NDEBUG_CLP
140 #endif
141 // dual
142
143 /* *** Method
144 This is a vanilla version of dual simplex.
145
146 It tries to be a single phase approach with a weight of 1.0 being
147 given to getting optimal and a weight of dualBound_ being
148 given to getting dual feasible. In this version I have used the
149 idea that this weight can be thought of as a fake bound. If the
150 distance between the lower and upper bounds on a variable is less
151 than the feasibility weight then we are always better off flipping
152 to other bound to make dual feasible. If the distance is greater
153 then we make up a fake bound dualBound_ away from one bound.
154 If we end up optimal or primal infeasible, we check to see if
155 bounds okay. If so we have finished, if not we increase dualBound_
156 and continue (after checking if unbounded). I am undecided about
157 free variables - there is coding but I am not sure about it. At
158 present I put them in basis anyway.
159
160 The code is designed to take advantage of sparsity so arrays are
161 seldom zeroed out from scratch or gone over in their entirety.
162 The only exception is a full scan to find outgoing variable. This
163 will be changed to keep an updated list of infeasibilities (or squares
164 if steepest edge). Also on easy problems we don't need full scan - just
165 pick first reasonable.
166
167 One problem is how to tackle degeneracy and accuracy. At present
168 I am using the modification of costs which I put in OSL and which was
169 extended by Gill et al. I am still not sure of the exact details.
170
171 The flow of dual is three while loops as follows:
172
173 while (not finished) {
174
175 while (not clean solution) {
176
177 Factorize and/or clean up solution by flipping variables so
178 dual feasible. If looks finished check fake dual bounds.
179 Repeat until status is iterating (-1) or finished (0,1,2)
180
181 }
182
183 while (status==-1) {
184
185 Iterate until no pivot in or out or time to re-factorize.
186
187 Flow is:
188
189 choose pivot row (outgoing variable). if none then
190 we are primal feasible so looks as if done but we need to
191 break and check bounds etc.
192
193 Get pivot row in tableau
194
195 Choose incoming column. If we don't find one then we look
196 primal infeasible so break and check bounds etc. (Also the
197 pivot tolerance is larger after any iterations so that may be
198 reason)
199
200 If we do find incoming column, we may have to adjust costs to
201 keep going forwards (anti-degeneracy). Check pivot will be stable
202 and if unstable throw away iteration (we will need to implement
203 flagging of basic variables sometime) and break to re-factorize.
204 If minor error re-factorize after iteration.
205
206 Update everything (this may involve flipping variables to stay
207 dual feasible.
208
209 }
210
211 }
212
213 At present we never check we are going forwards. I overdid that in
214 OSL so will try and make a last resort.
215
216 Needs partial scan pivot out option.
217 Needs dantzig, uninitialized and full steepest edge options (can still
218 use partial scan)
219
220 May need other anti-degeneracy measures, especially if we try and use
221 loose tolerances as a way to solve in fewer iterations.
222
223 I like idea of dynamic scaling. This gives opportunity to decouple
224 different implications of scaling for accuracy, iteration count and
225 feasibility tolerance.
226
227 */
228 #define CLEAN_FIXED 0
229 // Startup part of dual (may be extended to other algorithms)
startupSolve(int ifValuesPass,double * saveDuals,int startFinishOptions)230 int ClpSimplexDual::startupSolve(int ifValuesPass, double *saveDuals, int startFinishOptions)
231 {
232 // If values pass then save given duals round check solution
233 // sanity check
234 // initialize - no values pass and algorithm_ is -1
235 // put in standard form (and make row copy)
236 // create modifiable copies of model rim and do optional scaling
237 // If problem looks okay
238 // Do initial factorization
239 // If user asked for perturbation - do it
240 numberFake_ = 0; // Number of variables at fake bounds
241 numberChanged_ = 0; // Number of variables with changed costs
242 if (!startup(0 /* ? fix valuesPass */, startFinishOptions)) {
243 int usePrimal = 0;
244 // looks okay
245 // Superbasic variables not allowed
246 // If values pass then scale pi
247 if (ifValuesPass) {
248 if (problemStatus_ && perturbation_ < 100)
249 usePrimal = perturb();
250 int i;
251 if (scalingFlag_ > 0) {
252 for (i = 0; i < numberRows_; i++) {
253 dual_[i] = saveDuals[i] * inverseRowScale_[i];
254 }
255 } else {
256 CoinMemcpyN(saveDuals, numberRows_, dual_);
257 }
258 // now create my duals
259 for (i = 0; i < numberRows_; i++) {
260 // slack
261 double value = dual_[i];
262 value += rowObjectiveWork_[i];
263 saveDuals[i + numberColumns_] = value;
264 }
265 CoinMemcpyN(objectiveWork_, numberColumns_, saveDuals);
266 transposeTimes(-1.0, dual_, saveDuals);
267 // make reduced costs okay
268 for (i = 0; i < numberColumns_; i++) {
269 if (getStatus(i) == atLowerBound) {
270 if (saveDuals[i] < 0.0) {
271 //if (saveDuals[i]<-1.0e-3)
272 //printf("bad dj at lb %d %g\n",i,saveDuals[i]);
273 saveDuals[i] = 0.0;
274 }
275 } else if (getStatus(i) == atUpperBound) {
276 if (saveDuals[i] > 0.0) {
277 //if (saveDuals[i]>1.0e-3)
278 //printf("bad dj at ub %d %g\n",i,saveDuals[i]);
279 saveDuals[i] = 0.0;
280 }
281 }
282 }
283 CoinMemcpyN(saveDuals, (numberColumns_ + numberRows_), dj_);
284 // set up possible ones
285 for (i = 0; i < numberRows_ + numberColumns_; i++)
286 clearPivoted(i);
287 int iRow;
288 for (iRow = 0; iRow < numberRows_; iRow++) {
289 int iPivot = pivotVariable_[iRow];
290 if (fabs(saveDuals[iPivot]) > dualTolerance_) {
291 if (getStatus(iPivot) != isFree)
292 setPivoted(iPivot);
293 }
294 }
295 } else if ((specialOptions_ & 1024) != 0 && CLEAN_FIXED) {
296 // set up possible ones
297 for (int i = 0; i < numberRows_ + numberColumns_; i++)
298 clearPivoted(i);
299 int iRow;
300 for (iRow = 0; iRow < numberRows_; iRow++) {
301 int iPivot = pivotVariable_[iRow];
302 if (iPivot < numberColumns_ && lower_[iPivot] == upper_[iPivot]) {
303 setPivoted(iPivot);
304 }
305 }
306 }
307
308 double objectiveChange;
309 assert(!numberFake_);
310 assert(numberChanged_ == 0);
311 if (!numberFake_) // if nonzero then adjust
312 changeBounds(1, NULL, objectiveChange);
313
314 if (!ifValuesPass) {
315 // Check optimal
316 if (!numberDualInfeasibilities_ && !numberPrimalInfeasibilities_)
317 problemStatus_ = 0;
318 }
319 if (problemStatus_ < 0 && perturbation_ < 100) {
320 bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0;
321 if (!inCbcOrOther)
322 usePrimal = perturb();
323 // Can't get here if values pass
324 gutsOfSolution(NULL, NULL);
325 #ifdef CLP_INVESTIGATE
326 if (numberDualInfeasibilities_)
327 printf("ZZZ %d primal %d dual - sumdinf %g\n",
328 numberPrimalInfeasibilities_,
329 numberDualInfeasibilities_, sumDualInfeasibilities_);
330 #endif
331 if (handler_->logLevel() > 2) {
332 handler_->message(CLP_SIMPLEX_STATUS, messages_)
333 << numberIterations_ << objectiveValue();
334 handler_->printing(sumPrimalInfeasibilities_ > 0.0)
335 << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_;
336 handler_->printing(sumDualInfeasibilities_ > 0.0)
337 << sumDualInfeasibilities_ << numberDualInfeasibilities_;
338 handler_->printing(numberDualInfeasibilitiesWithoutFree_
339 < numberDualInfeasibilities_)
340 << numberDualInfeasibilitiesWithoutFree_;
341 handler_->message() << CoinMessageEol;
342 }
343 if (inCbcOrOther) {
344 if (numberPrimalInfeasibilities_) {
345 usePrimal = perturb();
346 if (perturbation_ >= 101) {
347 computeDuals(NULL);
348 //gutsOfSolution(NULL,NULL);
349 checkDualSolution(); // recompute objective
350 }
351 } else if (numberDualInfeasibilities_) {
352 problemStatus_ = 10;
353 if ((moreSpecialOptions_ & 32) != 0 && false)
354 problemStatus_ = 0; // say optimal!!
355 #if COIN_DEVELOP > 2
356
357 printf("returning at %d\n", __LINE__);
358 #endif
359 return 1; // to primal
360 }
361 }
362 } else if (!ifValuesPass) {
363 gutsOfSolution(NULL, NULL);
364 // double check
365 if (numberDualInfeasibilities_ || numberPrimalInfeasibilities_)
366 problemStatus_ = -1;
367 }
368 if (usePrimal) {
369 problemStatus_ = 10;
370 #if COIN_DEVELOP > 2
371 printf("returning to use primal (no obj) at %d\n", __LINE__);
372 #endif
373 }
374 return usePrimal;
375 } else {
376 return 1;
377 }
378 }
finishSolve(int startFinishOptions)379 void ClpSimplexDual::finishSolve(int startFinishOptions)
380 {
381 assert(problemStatus_ || !sumPrimalInfeasibilities_);
382
383 // clean up
384 finish(startFinishOptions);
385 }
386 //#define CLP_REPORT_PROGRESS
387 #ifdef CLP_REPORT_PROGRESS
388 static int ixxxxxx = 0;
389 static int ixxyyyy = 90;
390 #endif
391 #ifdef CLP_INVESTIGATE_SERIAL
392 static int z_reason[7] = { 0, 0, 0, 0, 0, 0, 0 };
393 static int z_thinks = -1;
394 #endif
gutsOfDual(int ifValuesPass,double * & saveDuals,int initialStatus,ClpDataSave & data)395 void ClpSimplexDual::gutsOfDual(int ifValuesPass, double *&saveDuals, int initialStatus,
396 ClpDataSave &data)
397 {
398 #ifdef CLP_INVESTIGATE_SERIAL
399 z_reason[0]++;
400 z_thinks = -1;
401 int nPivots = 9999;
402 #endif
403 double largestPrimalError = 0.0;
404 double largestDualError = 0.0;
405 double smallestPrimalInfeasibility = COIN_DBL_MAX;
406 int numberRayTries = 0;
407 // Start can skip some things in transposeTimes
408 specialOptions_ |= 131072;
409 int lastCleaned = 0; // last time objective or bounds cleaned up
410
411 // This says whether to restore things etc
412 // startup will have factorized so can skip
413 int factorType = 0;
414 // Start check for cycles
415 progress_.startCheck();
416 // Say change made on first iteration
417 changeMade_ = 1;
418 // Say last objective infinite
419 //lastObjectiveValue_=-COIN_DBL_MAX;
420 progressFlag_ = 0;
421 /*
422 Status of problem:
423 0 - optimal
424 1 - infeasible
425 2 - unbounded
426 -1 - iterating
427 -2 - factorization wanted
428 -3 - redo checking without factorization
429 -4 - looks infeasible
430 */
431 while (problemStatus_ < 0) {
432 int iRow, iColumn;
433 // clear
434 for (iRow = 0; iRow < 4; iRow++) {
435 rowArray_[iRow]->clear();
436 }
437
438 for (iColumn = 0; iColumn < SHORT_REGION; iColumn++) {
439 columnArray_[iColumn]->clear();
440 }
441
442 // give matrix (and model costs and bounds a chance to be
443 // refreshed (normally null)
444 matrix_->refresh(this);
445 // If getting nowhere - why not give it a kick
446 // does not seem to work too well - do some more work
447 if (perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (moreSpecialOptions_ & 1048576) == 0
448 && initialStatus != 10) {
449 perturb();
450 // Can't get here if values pass
451 gutsOfSolution(NULL, NULL);
452 if (handler_->logLevel() > 2) {
453 handler_->message(CLP_SIMPLEX_STATUS, messages_)
454 << numberIterations_ << objectiveValue();
455 handler_->printing(sumPrimalInfeasibilities_ > 0.0)
456 << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_;
457 handler_->printing(sumDualInfeasibilities_ > 0.0)
458 << sumDualInfeasibilities_ << numberDualInfeasibilities_;
459 handler_->printing(numberDualInfeasibilitiesWithoutFree_
460 < numberDualInfeasibilities_)
461 << numberDualInfeasibilitiesWithoutFree_;
462 handler_->message() << CoinMessageEol;
463 }
464 }
465 // see if in Cbc etc
466 bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0;
467 #if 0
468 bool gotoPrimal = false;
469 if (inCbcOrOther && numberIterations_ > disasterArea_ + numberRows_ &&
470 numberDualInfeasibilitiesWithoutFree_ && largestDualError_ > 1.0e-1) {
471 if (!disasterArea_) {
472 printf("trying all slack\n");
473 // try all slack basis
474 allSlackBasis(true);
475 disasterArea_ = 2 * numberRows_;
476 } else {
477 printf("going to primal\n");
478 // go to primal
479 gotoPrimal = true;
480 allSlackBasis(true);
481 }
482 }
483 #endif
484 bool disaster = false;
485 if (disasterArea_ && inCbcOrOther && disasterArea_->check()) {
486 disasterArea_->saveInfo();
487 disaster = true;
488 }
489 // may factorize, checks if problem finished
490 statusOfProblemInDual(lastCleaned, factorType, saveDuals, data,
491 ifValuesPass);
492 smallestPrimalInfeasibility = CoinMin(smallestPrimalInfeasibility,
493 sumPrimalInfeasibilities_);
494 if (sumPrimalInfeasibilities_ > 1.0e5 && sumPrimalInfeasibilities_ > 1.0e5 * smallestPrimalInfeasibility && (moreSpecialOptions_ & 256) == 0 && ((progress_.lastObjective(0) < -1.0e10 && -progress_.lastObjective(1) > -1.0e5) || sumPrimalInfeasibilities_ > 1.0e10 * smallestPrimalInfeasibility) && problemStatus_ < 0) {
495 // problems - try primal
496 problemStatus_ = 10;
497 // mark as large infeasibility cost wanted
498 sumPrimalInfeasibilities_ = -123456789.0;
499 //for (int i=0;i<numberRows_+numberColumns_;i++) {
500 //if (fabs(cost_[i]*solution_[i])>1.0e4)
501 // printf("col %d cost %g sol %g bounds %g %g\n",
502 // i,cost_[i],solution_[i],lower_[i],upper_[i]);
503 //}
504 } else if ((specialOptions_ & (32 | 2097152)) != 0 && problemStatus_ == 1 && !ray_ && !numberRayTries && numberIterations_) {
505 numberRayTries = 1;
506 problemStatus_ = -1;
507 }
508 largestPrimalError = CoinMax(largestPrimalError, largestPrimalError_);
509 largestDualError = CoinMax(largestDualError, largestDualError_);
510 if (disaster)
511 problemStatus_ = 3;
512 // If values pass then do easy ones on first time
513 if (ifValuesPass && progress_.lastIterationNumber(0) < 0 && saveDuals) {
514 doEasyOnesInValuesPass(saveDuals);
515 }
516
517 // Say good factorization
518 factorType = 1;
519 if (data.sparseThreshold_) {
520 // use default at present
521 factorization_->sparseThreshold(0);
522 factorization_->goSparse();
523 }
524
525 // exit if victory declared
526 if (problemStatus_ >= 0)
527 break;
528
529 // test for maximum iterations
530 if (hitMaximumIterations() || (ifValuesPass == 2 && !saveDuals)) {
531 problemStatus_ = 3;
532 break;
533 }
534 if (ifValuesPass && !saveDuals) {
535 // end of values pass
536 ifValuesPass = 0;
537 int status = eventHandler_->event(ClpEventHandler::endOfValuesPass);
538 if (status >= 0) {
539 problemStatus_ = 5;
540 secondaryStatus_ = ClpEventHandler::endOfValuesPass;
541 break;
542 }
543 }
544 // Check event
545 {
546 int status = eventHandler_->event(ClpEventHandler::endOfFactorization);
547 if (status >= 0) {
548 problemStatus_ = 5;
549 secondaryStatus_ = ClpEventHandler::endOfFactorization;
550 break;
551 }
552 }
553 // If looks odd try other way
554 if ((moreSpecialOptions_ & 256) == 0 && fabs(objectiveValue_) > 1.0e20 && sumDualInfeasibilities_ > 1.0
555 && problemStatus_ < 0) {
556 problemStatus_ = 10;
557 break;
558 }
559 // Do iterations
560 int returnCode = whileIterating(saveDuals, ifValuesPass);
561 if (problemStatus_ == 1 && (progressFlag_ & 8) != 0 && fabs(objectiveValue_) > 1.0e10)
562 problemStatus_ = 10; // infeasible - but has looked feasible
563 #ifdef CLP_INVESTIGATE_SERIAL
564 nPivots = factorization_->pivots();
565 #endif
566 if (!problemStatus_ && factorization_->pivots())
567 computeDuals(NULL); // need to compute duals
568 if (returnCode == -2)
569 factorType = 3;
570 }
571 #ifdef CLP_INVESTIGATE_SERIAL
572 // NOTE - can fail if parallel
573 if (z_thinks != -1) {
574 assert(z_thinks < 4);
575 if ((!factorization_->pivots() && nPivots < 20) && z_thinks >= 0 && z_thinks < 2)
576 z_thinks += 4;
577 z_reason[1 + z_thinks]++;
578 }
579 if ((z_reason[0] % 1000) == 0) {
580 printf("Reason");
581 for (int i = 0; i < 7; i++)
582 printf(" %d", z_reason[i]);
583 printf("\n");
584 }
585 #endif
586 // Stop can skip some things in transposeTimes
587 specialOptions_ &= ~131072;
588 largestPrimalError_ = largestPrimalError;
589 largestDualError_ = largestDualError;
590 }
dual(int ifValuesPass,int startFinishOptions)591 int ClpSimplexDual::dual(int ifValuesPass, int startFinishOptions)
592 {
593 //handler_->setLogLevel(63);
594 //yprintf("STARTing dual %d rows\n",numberRows_);
595 bestObjectiveValue_ = -COIN_DBL_MAX;
596 algorithm_ = -1;
597 moreSpecialOptions_ &= ~16; // clear check replaceColumn accuracy
598 delete[] ray_;
599 ray_ = NULL;
600 // save data
601 ClpDataSave data = saveData();
602 double *saveDuals = NULL;
603 int saveDont = dontFactorizePivots_;
604 if ((specialOptions_ & 2048) == 0)
605 dontFactorizePivots_ = 0;
606 else if (!dontFactorizePivots_)
607 dontFactorizePivots_ = 20;
608 if (ifValuesPass) {
609 saveDuals = new double[numberRows_ + numberColumns_];
610 CoinMemcpyN(dual_, numberRows_, saveDuals);
611 }
612 if (alphaAccuracy_ != -1.0)
613 alphaAccuracy_ = 1.0;
614 minimumPrimalTolerance_ = primalTolerance();
615 int returnCode = startupSolve(ifValuesPass, saveDuals, startFinishOptions);
616 // Save so can see if doing after primal
617 int initialStatus = problemStatus_;
618 if (!returnCode && !numberDualInfeasibilities_ && !numberPrimalInfeasibilities_ && perturbation_ < 101) {
619 returnCode = 1; // to skip gutsOfDual
620 problemStatus_ = 0;
621 } else if (maximumIterations() == 0) {
622 returnCode = 1; // to skip gutsOfDual
623 problemStatus_ = 3;
624 }
625
626 if (!returnCode)
627 gutsOfDual(ifValuesPass, saveDuals, initialStatus, data);
628 if (!problemStatus_) {
629 // see if cutoff reached
630 double limit = 0.0;
631 getDblParam(ClpDualObjectiveLimit, limit);
632 if (fabs(limit) < 1.0e30 && objectiveValue() * optimizationDirection_ > limit + 1.0e-7 + 1.0e-8 * fabs(limit)) {
633 // actually infeasible on objective
634 problemStatus_ = 1;
635 secondaryStatus_ = 1;
636 }
637 }
638 // If infeasible but primal errors - try primal
639 if (problemStatus_ == 1 && numberPrimalInfeasibilities_) {
640 bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0;
641 double factor = (!inCbcOrOther) ? 1.0 : 0.3;
642 double averageInfeasibility = sumPrimalInfeasibilities_ / static_cast< double >(numberPrimalInfeasibilities_);
643 if (averageInfeasibility < factor * largestPrimalError_)
644 problemStatus_ = 10;
645 }
646
647 if (problemStatus_ == 10)
648 startFinishOptions |= 1;
649 finishSolve(startFinishOptions);
650 delete[] saveDuals;
651
652 // Restore any saved stuff
653 restoreData(data);
654 dontFactorizePivots_ = saveDont;
655 if (problemStatus_ == 3)
656 objectiveValue_ = CoinMax(bestObjectiveValue_, objectiveValue_ - bestPossibleImprovement_);
657 return problemStatus_;
658 }
659 // old way
660 #if 0
661 int ClpSimplexDual::dual (int ifValuesPass , int startFinishOptions)
662 {
663 algorithm_ = -1;
664
665 // save data
666 ClpDataSave data = saveData();
667 // Save so can see if doing after primal
668 int initialStatus = problemStatus_;
669
670 // If values pass then save given duals round check solution
671 double * saveDuals = NULL;
672 if (ifValuesPass) {
673 saveDuals = new double [numberRows_+numberColumns_];
674 CoinMemcpyN(dual_, numberRows_, saveDuals);
675 }
676 // sanity check
677 // initialize - no values pass and algorithm_ is -1
678 // put in standard form (and make row copy)
679 // create modifiable copies of model rim and do optional scaling
680 // If problem looks okay
681 // Do initial factorization
682 // If user asked for perturbation - do it
683 if (!startup(0, startFinishOptions)) {
684 // looks okay
685 // Superbasic variables not allowed
686 // If values pass then scale pi
687 if (ifValuesPass) {
688 if (problemStatus_ && perturbation_ < 100)
689 perturb();
690 int i;
691 if (scalingFlag_ > 0) {
692 for (i = 0; i < numberRows_; i++) {
693 dual_[i] = saveDuals[i] * inverseRowScale_[i];
694 }
695 } else {
696 CoinMemcpyN(saveDuals, numberRows_, dual_);
697 }
698 // now create my duals
699 for (i = 0; i < numberRows_; i++) {
700 // slack
701 double value = dual_[i];
702 value += rowObjectiveWork_[i];
703 saveDuals[i+numberColumns_] = value;
704 }
705 CoinMemcpyN(objectiveWork_, numberColumns_, saveDuals);
706 transposeTimes(-1.0, dual_, saveDuals);
707 // make reduced costs okay
708 for (i = 0; i < numberColumns_; i++) {
709 if (getStatus(i) == atLowerBound) {
710 if (saveDuals[i] < 0.0) {
711 //if (saveDuals[i]<-1.0e-3)
712 //printf("bad dj at lb %d %g\n",i,saveDuals[i]);
713 saveDuals[i] = 0.0;
714 }
715 } else if (getStatus(i) == atUpperBound) {
716 if (saveDuals[i] > 0.0) {
717 //if (saveDuals[i]>1.0e-3)
718 //printf("bad dj at ub %d %g\n",i,saveDuals[i]);
719 saveDuals[i] = 0.0;
720 }
721 }
722 }
723 CoinMemcpyN(saveDuals, numberColumns_ + numberRows_, dj_);
724 // set up possible ones
725 for (i = 0; i < numberRows_ + numberColumns_; i++)
726 clearPivoted(i);
727 int iRow;
728 for (iRow = 0; iRow < numberRows_; iRow++) {
729 int iPivot = pivotVariable_[iRow];
730 if (fabs(saveDuals[iPivot]) > dualTolerance_) {
731 if (getStatus(iPivot) != isFree)
732 setPivoted(iPivot);
733 }
734 }
735 } else if ((specialOptions_ & 1024) != 0 && CLEAN_FIXED) {
736 // set up possible ones
737 for (int i = 0; i < numberRows_ + numberColumns_; i++)
738 clearPivoted(i);
739 int iRow;
740 for (iRow = 0; iRow < numberRows_; iRow++) {
741 int iPivot = pivotVariable_[iRow];
742 if (iPivot < numberColumns_ && lower_[iPivot] == upper_[iPivot]) {
743 setPivoted(iPivot);
744 }
745 }
746 }
747
748 double objectiveChange;
749 numberFake_ = 0; // Number of variables at fake bounds
750 numberChanged_ = 0; // Number of variables with changed costs
751 changeBounds(1, NULL, objectiveChange);
752
753 int lastCleaned = 0; // last time objective or bounds cleaned up
754
755 if (!ifValuesPass) {
756 // Check optimal
757 if (!numberDualInfeasibilities_ && !numberPrimalInfeasibilities_)
758 problemStatus_ = 0;
759 }
760 if (problemStatus_ < 0 && perturbation_ < 100) {
761 perturb();
762 // Can't get here if values pass
763 gutsOfSolution(NULL, NULL);
764 if (handler_->logLevel() > 2) {
765 handler_->message(CLP_SIMPLEX_STATUS, messages_)
766 << numberIterations_ << objectiveValue();
767 handler_->printing(sumPrimalInfeasibilities_ > 0.0)
768 << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_;
769 handler_->printing(sumDualInfeasibilities_ > 0.0)
770 << sumDualInfeasibilities_ << numberDualInfeasibilities_;
771 handler_->printing(numberDualInfeasibilitiesWithoutFree_
772 < numberDualInfeasibilities_)
773 << numberDualInfeasibilitiesWithoutFree_;
774 handler_->message() << CoinMessageEol;
775 }
776 }
777
778 // This says whether to restore things etc
779 // startup will have factorized so can skip
780 int factorType = 0;
781 // Start check for cycles
782 progress_.startCheck();
783 // Say change made on first iteration
784 changeMade_ = 1;
785 /*
786 Status of problem:
787 0 - optimal
788 1 - infeasible
789 2 - unbounded
790 -1 - iterating
791 -2 - factorization wanted
792 -3 - redo checking without factorization
793 -4 - looks infeasible
794 */
795 while (problemStatus_ < 0) {
796 int iRow, iColumn;
797 // clear
798 for (iRow = 0; iRow < 4; iRow++) {
799 rowArray_[iRow]->clear();
800 }
801
802 for (iColumn = 0; iColumn < SHORT_REGION; iColumn++) {
803 columnArray_[iColumn]->clear();
804 }
805
806 // give matrix (and model costs and bounds a chance to be
807 // refreshed (normally null)
808 matrix_->refresh(this);
809 // If getting nowhere - why not give it a kick
810 // does not seem to work too well - do some more work
811 if (perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (moreSpecialOptions_&1048576)==0
812 && initialStatus != 10) {
813 perturb();
814 // Can't get here if values pass
815 gutsOfSolution(NULL, NULL);
816 if (handler_->logLevel() > 2) {
817 handler_->message(CLP_SIMPLEX_STATUS, messages_)
818 << numberIterations_ << objectiveValue();
819 handler_->printing(sumPrimalInfeasibilities_ > 0.0)
820 << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_;
821 handler_->printing(sumDualInfeasibilities_ > 0.0)
822 << sumDualInfeasibilities_ << numberDualInfeasibilities_;
823 handler_->printing(numberDualInfeasibilitiesWithoutFree_
824 < numberDualInfeasibilities_)
825 << numberDualInfeasibilitiesWithoutFree_;
826 handler_->message() << CoinMessageEol;
827 }
828 }
829 // may factorize, checks if problem finished
830 statusOfProblemInDual(lastCleaned, factorType, saveDuals, data,
831 ifValuesPass);
832 // If values pass then do easy ones on first time
833 if (ifValuesPass &&
834 progress_.lastIterationNumber(0) < 0 && saveDuals) {
835 doEasyOnesInValuesPass(saveDuals);
836 }
837
838 // Say good factorization
839 factorType = 1;
840 if (data.sparseThreshold_) {
841 // use default at present
842 factorization_->sparseThreshold(0);
843 factorization_->goSparse();
844 }
845
846 // exit if victory declared
847 if (problemStatus_ >= 0)
848 break;
849
850 // test for maximum iterations
851 if (hitMaximumIterations() || (ifValuesPass == 2 && !saveDuals)) {
852 problemStatus_ = 3;
853 break;
854 }
855 if (ifValuesPass && !saveDuals) {
856 // end of values pass
857 ifValuesPass = 0;
858 int status = eventHandler_->event(ClpEventHandler::endOfValuesPass);
859 if (status >= 0) {
860 problemStatus_ = 5;
861 secondaryStatus_ = ClpEventHandler::endOfValuesPass;
862 break;
863 }
864 }
865 // Check event
866 {
867 int status = eventHandler_->event(ClpEventHandler::endOfFactorization);
868 if (status >= 0) {
869 problemStatus_ = 5;
870 secondaryStatus_ = ClpEventHandler::endOfFactorization;
871 break;
872 }
873 }
874 // Do iterations
875 whileIterating(saveDuals, ifValuesPass);
876 }
877 }
878
879 assert (problemStatus_ || !sumPrimalInfeasibilities_);
880
881 // clean up
882 finish(startFinishOptions);
883 delete [] saveDuals;
884
885 // Restore any saved stuff
886 restoreData(data);
887 return problemStatus_;
888 }
889 #endif
890 //#define CHECK_ACCURACY
891 #ifdef CHECK_ACCURACY
892 static double zzzzzz[100000];
893 #endif
894 /* Reasons to come out:
895 -1 iterations etc
896 -2 inaccuracy
897 -3 slight inaccuracy (and done iterations)
898 +0 looks optimal (might be unbounded - but we will investigate)
899 +1 looks infeasible
900 +3 max iterations
901 */
whileIterating(double * & givenDuals,int ifValuesPass)902 int ClpSimplexDual::whileIterating(double *&givenDuals, int ifValuesPass)
903 {
904 #ifdef CLP_INVESTIGATE_SERIAL
905 z_thinks = -1;
906 #endif
907 #ifdef CLP_DEBUG
908 int debugIteration = -1;
909 #endif
910 {
911 int i;
912 for (i = 0; i < 4; i++) {
913 rowArray_[i]->clear();
914 }
915 for (i = 0; i < SHORT_REGION; i++) {
916 columnArray_[i]->clear();
917 }
918 }
919 #ifdef CLP_REPORT_PROGRESS
920 double *savePSol = new double[numberRows_ + numberColumns_];
921 double *saveDj = new double[numberRows_ + numberColumns_];
922 double *saveCost = new double[numberRows_ + numberColumns_];
923 unsigned char *saveStat = new unsigned char[numberRows_ + numberColumns_];
924 #endif
925 // if can't trust much and long way from optimal then relax
926 if (largestPrimalError_ > 10.0)
927 factorization_->relaxAccuracyCheck(CoinMin(1.0e2, largestPrimalError_ / 10.0));
928 else
929 factorization_->relaxAccuracyCheck(1.0);
930 // status stays at -1 while iterating, >=0 finished, -2 to invert
931 // status -3 to go to top without an invert
932 int returnCode = -1;
933 double saveSumDual = sumDualInfeasibilities_; // so we know to be careful
934
935 #if 0
936 // compute average infeasibility for backward test
937 double averagePrimalInfeasibility = sumPrimalInfeasibilities_ /
938 ((double ) (numberPrimalInfeasibilities_ + 1));
939 #endif
940
941 // Get dubious weights
942 CoinBigIndex *dubiousWeights = NULL;
943 #ifdef DUBIOUS_WEIGHTS
944 factorization_->getWeights(rowArray_[0]->getIndices());
945 dubiousWeights = matrix_->dubiousWeights(this, rowArray_[0]->getIndices());
946 #endif
947 // If values pass then get list of candidates
948 int *candidateList = NULL;
949 int numberCandidates = 0;
950 #ifdef CLP_DEBUG
951 bool wasInValuesPass = (givenDuals != NULL);
952 #endif
953 int candidate = -1;
954 if (givenDuals) {
955 assert(ifValuesPass);
956 ifValuesPass = 1;
957 candidateList = new int[numberRows_];
958 // move reduced costs across
959 CoinMemcpyN(givenDuals, numberRows_ + numberColumns_, dj_);
960 int iRow;
961 for (iRow = 0; iRow < numberRows_; iRow++) {
962 int iPivot = pivotVariable_[iRow];
963 if (flagged(iPivot))
964 continue;
965 if (fabs(dj_[iPivot]) > dualTolerance_) {
966 // for now safer to ignore free ones
967 if (lower_[iPivot] > -1.0e50 || upper_[iPivot] < 1.0e50)
968 if (pivoted(iPivot))
969 candidateList[numberCandidates++] = iRow;
970 } else {
971 clearPivoted(iPivot);
972 }
973 }
974 // and set first candidate
975 if (!numberCandidates) {
976 delete[] candidateList;
977 delete[] givenDuals;
978 givenDuals = NULL;
979 candidateList = NULL;
980 int iRow;
981 for (iRow = 0; iRow < numberRows_; iRow++) {
982 int iPivot = pivotVariable_[iRow];
983 clearPivoted(iPivot);
984 }
985 }
986 } else {
987 assert(!ifValuesPass);
988 }
989 #ifdef CHECK_ACCURACY
990 {
991 if (numberIterations_) {
992 int il = -1;
993 double largest = 1.0e-1;
994 int ilnb = -1;
995 double largestnb = 1.0e-8;
996 for (int i = 0; i < numberRows_ + numberColumns_; i++) {
997 double diff = fabs(solution_[i] - zzzzzz[i]);
998 if (diff > largest) {
999 largest = diff;
1000 il = i;
1001 }
1002 if (getColumnStatus(i) != basic) {
1003 if (diff > largestnb) {
1004 largestnb = diff;
1005 ilnb = i;
1006 }
1007 }
1008 }
1009 if (il >= 0 && ilnb < 0)
1010 printf("largest diff of %g at %d, nonbasic %g at %d\n",
1011 largest, il, largestnb, ilnb);
1012 }
1013 }
1014 #endif
1015 while (problemStatus_ == -1) {
1016 //if (numberIterations_>=101624)
1017 //resetFakeBounds(-1);
1018 #ifdef CLP_DEBUG
1019 if (givenDuals) {
1020 double value5 = 0.0;
1021 int i;
1022 for (i = 0; i < numberRows_ + numberColumns_; i++) {
1023 if (dj_[i] < -1.0e-6)
1024 if (upper_[i] < 1.0e20)
1025 value5 += dj_[i] * upper_[i];
1026 else
1027 printf("bad dj %g on %d with large upper status %d\n",
1028 dj_[i], i, status_[i] & 7);
1029 else if (dj_[i] > 1.0e-6)
1030 if (lower_[i] > -1.0e20)
1031 value5 += dj_[i] * lower_[i];
1032 else
1033 printf("bad dj %g on %d with large lower status %d\n",
1034 dj_[i], i, status_[i] & 7);
1035 }
1036 printf("Values objective Value %g\n", value5);
1037 }
1038 if ((handler_->logLevel() & 32) && wasInValuesPass) {
1039 double value5 = 0.0;
1040 int i;
1041 for (i = 0; i < numberRows_ + numberColumns_; i++) {
1042 if (dj_[i] < -1.0e-6)
1043 if (upper_[i] < 1.0e20)
1044 value5 += dj_[i] * upper_[i];
1045 else if (dj_[i] > 1.0e-6)
1046 if (lower_[i] > -1.0e20)
1047 value5 += dj_[i] * lower_[i];
1048 }
1049 printf("Values objective Value %g\n", value5);
1050 {
1051 int i;
1052 for (i = 0; i < numberRows_ + numberColumns_; i++) {
1053 int iSequence = i;
1054 double oldValue;
1055
1056 switch (getStatus(iSequence)) {
1057
1058 case basic:
1059 case ClpSimplex::isFixed:
1060 break;
1061 case isFree:
1062 case superBasic:
1063 abort();
1064 break;
1065 case atUpperBound:
1066 oldValue = dj_[iSequence];
1067 //assert (oldValue<=tolerance);
1068 assert(fabs(solution_[iSequence] - upper_[iSequence]) < 1.0e-7);
1069 break;
1070 case atLowerBound:
1071 oldValue = dj_[iSequence];
1072 //assert (oldValue>=-tolerance);
1073 assert(fabs(solution_[iSequence] - lower_[iSequence]) < 1.0e-7);
1074 break;
1075 }
1076 }
1077 }
1078 }
1079 #endif
1080 #ifdef CLP_DEBUG
1081 {
1082 int i;
1083 for (i = 0; i < 4; i++) {
1084 rowArray_[i]->checkClear();
1085 }
1086 for (i = 0; i < 2; i++) {
1087 columnArray_[i]->checkClear();
1088 }
1089 }
1090 #endif
1091 #if CLP_DEBUG > 2
1092 // very expensive
1093 if (numberIterations_ > 3063 && numberIterations_ < 30700) {
1094 //handler_->setLogLevel(63);
1095 double saveValue = objectiveValue_;
1096 double *saveRow1 = new double[numberRows_];
1097 double *saveRow2 = new double[numberRows_];
1098 CoinMemcpyN(rowReducedCost_, numberRows_, saveRow1);
1099 CoinMemcpyN(rowActivityWork_, numberRows_, saveRow2);
1100 double *saveColumn1 = new double[numberColumns_];
1101 double *saveColumn2 = new double[numberColumns_];
1102 CoinMemcpyN(reducedCostWork_, numberColumns_, saveColumn1);
1103 CoinMemcpyN(columnActivityWork_, numberColumns_, saveColumn2);
1104 gutsOfSolution(NULL, NULL);
1105 printf("xxx %d old obj %g, recomputed %g, sum dual inf %g\n",
1106 numberIterations_,
1107 saveValue, objectiveValue_, sumDualInfeasibilities_);
1108 if (saveValue > objectiveValue_ + 1.0e-2)
1109 printf("**bad**\n");
1110 CoinMemcpyN(saveRow1, numberRows_, rowReducedCost_);
1111 CoinMemcpyN(saveRow2, numberRows_, rowActivityWork_);
1112 CoinMemcpyN(saveColumn1, numberColumns_, reducedCostWork_);
1113 CoinMemcpyN(saveColumn2, numberColumns_, columnActivityWork_);
1114 delete[] saveRow1;
1115 delete[] saveRow2;
1116 delete[] saveColumn1;
1117 delete[] saveColumn2;
1118 objectiveValue_ = saveValue;
1119 }
1120 #endif
1121 #if 0
1122 // if (factorization_->pivots()){
1123 {
1124 int iPivot;
1125 double * array = rowArray_[3]->denseVector();
1126 int i;
1127 for (iPivot = 0; iPivot < numberRows_; iPivot++) {
1128 int iSequence = pivotVariable_[iPivot];
1129 unpack(rowArray_[3], iSequence);
1130 factorization_->updateColumn(rowArray_[2], rowArray_[3]);
1131 assert (fabs(array[iPivot] - 1.0) < 1.0e-4);
1132 array[iPivot] = 0.0;
1133 for (i = 0; i < numberRows_; i++)
1134 assert (fabs(array[i]) < 1.0e-4);
1135 rowArray_[3]->clear();
1136 }
1137 }
1138 #endif
1139 #ifdef CLP_DEBUG
1140 {
1141 int iSequence, number = numberRows_ + numberColumns_;
1142 for (iSequence = 0; iSequence < number; iSequence++) {
1143 double lowerValue = lower_[iSequence];
1144 double upperValue = upper_[iSequence];
1145 double value = solution_[iSequence];
1146 if (getStatus(iSequence) != basic && getStatus(iSequence) != isFree) {
1147 assert(lowerValue > -1.0e20);
1148 assert(upperValue < 1.0e20);
1149 }
1150 switch (getStatus(iSequence)) {
1151
1152 case basic:
1153 break;
1154 case isFree:
1155 case superBasic:
1156 break;
1157 case atUpperBound:
1158 assert(fabs(value - upperValue) <= primalTolerance_);
1159 break;
1160 case atLowerBound:
1161 case ClpSimplex::isFixed:
1162 assert(fabs(value - lowerValue) <= primalTolerance_);
1163 break;
1164 }
1165 }
1166 }
1167 if (numberIterations_ == debugIteration) {
1168 printf("dodgy iteration coming up\n");
1169 }
1170 #endif
1171 #if 0
1172 printf("checking nz\n");
1173 for (int i = 0; i < 3; i++) {
1174 if (!rowArray_[i]->getNumElements())
1175 rowArray_[i]->checkClear();
1176 if (columnArray_[i])
1177 columnArray_[i]->checkClean();
1178 }
1179 #endif
1180 // choose row to go out
1181 // dualRow will go to virtual row pivot choice algorithm
1182 // make sure values pass off if it should be
1183 if (numberCandidates)
1184 candidate = candidateList[--numberCandidates];
1185 else
1186 candidate = -1;
1187 dualRow(candidate);
1188 if (pivotRow_ >= 0) {
1189 #if ABOCA_LITE_FACTORIZATION
1190 int numberThreads = abcState();
1191 if (numberThreads)
1192 cilk_spawn factorization_->replaceColumn1(columnArray_[1],
1193 pivotRow_);
1194 #endif
1195 // we found a pivot row
1196 if (handler_->detail(CLP_SIMPLEX_PIVOTROW, messages_) < 100) {
1197 handler_->message(CLP_SIMPLEX_PIVOTROW, messages_)
1198 << pivotRow_
1199 << CoinMessageEol;
1200 }
1201 // check accuracy of weights
1202 dualRowPivot_->checkAccuracy();
1203 // Get good size for pivot
1204 // Allow first few iterations to take tiny
1205 double acceptablePivot = 1.0e-1 * acceptablePivot_;
1206 if (numberIterations_ > 100)
1207 acceptablePivot = acceptablePivot_;
1208 if (factorization_->pivots() > 10 || (factorization_->pivots() && saveSumDual))
1209 acceptablePivot = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict
1210 else if (factorization_->pivots() > 5)
1211 acceptablePivot = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict
1212 else if (factorization_->pivots())
1213 acceptablePivot = acceptablePivot_; // relax
1214 // But factorizations complain if <1.0e-8
1215 //acceptablePivot=CoinMax(acceptablePivot,1.0e-8);
1216 double bestPossiblePivot = 1.0;
1217 // get sign for finding row of tableau
1218 if (candidate < 0) {
1219 // normal iteration
1220 // create as packed
1221 double direction = directionOut_;
1222 rowArray_[0]->createPacked(1, &pivotRow_, &direction);
1223 factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]);
1224 // Allow to do dualColumn0
1225 if (numberThreads_ < -1)
1226 spareIntArray_[0] = 1;
1227 spareDoubleArray_[0] = acceptablePivot;
1228 rowArray_[3]->clear();
1229 sequenceIn_ = -1;
1230 // put row of tableau in rowArray[0] and columnArray[0]
1231 assert(!rowArray_[1]->getNumElements());
1232 if (!scaledMatrix_) {
1233 if ((moreSpecialOptions_ & 8) != 0 && !rowScale_)
1234 spareIntArray_[0] = 1;
1235 matrix_->transposeTimes(this, -1.0,
1236 rowArray_[0], rowArray_[1], columnArray_[0]);
1237 } else {
1238 double *saveR = rowScale_;
1239 double *saveC = columnScale_;
1240 rowScale_ = NULL;
1241 columnScale_ = NULL;
1242 if ((moreSpecialOptions_ & 8) != 0)
1243 spareIntArray_[0] = 1;
1244 scaledMatrix_->transposeTimes(this, -1.0,
1245 rowArray_[0], rowArray_[1], columnArray_[0]);
1246 rowScale_ = saveR;
1247 columnScale_ = saveC;
1248 }
1249 #ifdef CLP_REPORT_PROGRESS
1250 memcpy(savePSol, solution_, (numberColumns_ + numberRows_) * sizeof(double));
1251 memcpy(saveDj, dj_, (numberColumns_ + numberRows_) * sizeof(double));
1252 memcpy(saveCost, cost_, (numberColumns_ + numberRows_) * sizeof(double));
1253 memcpy(saveStat, status_, (numberColumns_ + numberRows_) * sizeof(char));
1254 #endif
1255 // do ratio test for normal iteration
1256 bestPossiblePivot = dualColumn(rowArray_[0], columnArray_[0], rowArray_[3],
1257 #ifdef LONG_REGION_2
1258 rowArray_[2],
1259 #else
1260 columnArray_[1],
1261 #endif
1262 acceptablePivot, dubiousWeights);
1263 if (sequenceIn_ < 0 && acceptablePivot > acceptablePivot_)
1264 acceptablePivot_ = -fabs(acceptablePivot_); // stop early exit
1265 #if CAN_HAVE_ZERO_OBJ > 1
1266 if ((specialOptions_ & 16777216) != 0)
1267 theta_ = 0.0;
1268 #endif
1269 } else {
1270 // Make sure direction plausible
1271 CoinAssert(upperOut_ < 1.0e50 || lowerOut_ > -1.0e50);
1272 // If in integer cleanup do direction using duals
1273 // may be wrong way round
1274 if (ifValuesPass == 2) {
1275 if (dual_[pivotRow_] > 0.0) {
1276 // this will give a -1 in pivot row (as slacks are -1.0)
1277 directionOut_ = 1;
1278 } else {
1279 directionOut_ = -1;
1280 }
1281 }
1282 if (directionOut_ < 0 && fabs(valueOut_ - upperOut_) > dualBound_ + primalTolerance_) {
1283 if (fabs(valueOut_ - upperOut_) > fabs(valueOut_ - lowerOut_))
1284 directionOut_ = 1;
1285 } else if (directionOut_ > 0 && fabs(valueOut_ - lowerOut_) > dualBound_ + primalTolerance_) {
1286 if (fabs(valueOut_ - upperOut_) < fabs(valueOut_ - lowerOut_))
1287 directionOut_ = -1;
1288 }
1289 double direction = directionOut_;
1290 rowArray_[0]->createPacked(1, &pivotRow_, &direction);
1291 factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]);
1292 // put row of tableau in rowArray[0] and columnArray[0]
1293 if (!scaledMatrix_) {
1294 matrix_->transposeTimes(this, -1.0,
1295 rowArray_[0], rowArray_[3], columnArray_[0]);
1296 } else {
1297 double *saveR = rowScale_;
1298 double *saveC = columnScale_;
1299 rowScale_ = NULL;
1300 columnScale_ = NULL;
1301 scaledMatrix_->transposeTimes(this, -1.0,
1302 rowArray_[0], rowArray_[3], columnArray_[0]);
1303 rowScale_ = saveR;
1304 columnScale_ = saveC;
1305 }
1306 acceptablePivot *= 10.0;
1307 // do ratio test
1308 if (ifValuesPass == 1) {
1309 checkPossibleValuesMove(rowArray_[0], columnArray_[0],
1310 acceptablePivot);
1311 } else {
1312 checkPossibleCleanup(rowArray_[0], columnArray_[0],
1313 acceptablePivot);
1314 if (sequenceIn_ < 0) {
1315 rowArray_[0]->clear();
1316 columnArray_[0]->clear();
1317 continue; // can't do anything
1318 }
1319 }
1320
1321 // recompute true dualOut_
1322 if (directionOut_ < 0) {
1323 dualOut_ = valueOut_ - upperOut_;
1324 } else {
1325 dualOut_ = lowerOut_ - valueOut_;
1326 }
1327 // check what happened if was values pass
1328 // may want to move part way i.e. movement
1329 bool normalIteration = (sequenceIn_ != sequenceOut_);
1330
1331 clearPivoted(sequenceOut_); // make sure won't be done again
1332 // see if end of values pass
1333 if (!numberCandidates) {
1334 int iRow;
1335 delete[] candidateList;
1336 delete[] givenDuals;
1337 candidate = -2; // -2 signals end
1338 givenDuals = NULL;
1339 candidateList = NULL;
1340 ifValuesPass = 1;
1341 for (iRow = 0; iRow < numberRows_; iRow++) {
1342 int iPivot = pivotVariable_[iRow];
1343 //assert (fabs(dj_[iPivot]),1.0e-5);
1344 clearPivoted(iPivot);
1345 }
1346 }
1347 if (!normalIteration) {
1348 //rowArray_[0]->cleanAndPackSafe(1.0e-60);
1349 //columnArray_[0]->cleanAndPackSafe(1.0e-60);
1350 updateDualsInValuesPass(rowArray_[0], columnArray_[0], theta_);
1351 if (candidate == -2)
1352 problemStatus_ = -2;
1353 continue; // skip rest of iteration
1354 } else {
1355 // recompute dualOut_
1356 if (directionOut_ < 0) {
1357 dualOut_ = valueOut_ - upperOut_;
1358 } else {
1359 dualOut_ = lowerOut_ - valueOut_;
1360 }
1361 }
1362 }
1363 if (sequenceIn_ >= 0) {
1364 // normal iteration
1365 // update the incoming column
1366 double btranAlpha = -alpha_ * directionOut_; // for check
1367 unpackPacked(rowArray_[1]);
1368 // moved into updateWeights - factorization_->updateColumnFT(rowArray_[2],rowArray_[1]);
1369 // and update dual weights (can do in parallel - with extra array)
1370 alpha_ = dualRowPivot_->updateWeights(rowArray_[0],
1371 rowArray_[2],
1372 rowArray_[3],
1373 rowArray_[1]);
1374 // see if update stable
1375 #ifdef CLP_DEBUG
1376 if ((handler_->logLevel() & 32))
1377 printf("btran alpha %g, ftran alpha %g\n", btranAlpha, alpha_);
1378 #endif
1379 double checkValue = 1.0e-7;
1380 // if can't trust much and long way from optimal then relax
1381 if (largestPrimalError_ > 10.0)
1382 checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_);
1383 if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > checkValue * (1.0 + fabs(alpha_))) {
1384 handler_->message(CLP_DUAL_CHECK, messages_)
1385 << btranAlpha
1386 << alpha_
1387 << CoinMessageEol;
1388 if (factorization_->pivots()) {
1389 dualRowPivot_->unrollWeights();
1390 problemStatus_ = -2; // factorize now
1391 rowArray_[0]->clear();
1392 rowArray_[1]->clear();
1393 columnArray_[0]->clear();
1394 returnCode = -2;
1395 break;
1396 } else {
1397 // take on more relaxed criterion
1398 double test;
1399 if (fabs(btranAlpha) < 1.0e-8 || fabs(alpha_) < 1.0e-8)
1400 test = 1.0e-1 * fabs(alpha_);
1401 else
1402 test = 1.0e-4 * (1.0 + fabs(alpha_));
1403 if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > test) {
1404 dualRowPivot_->unrollWeights();
1405 // need to reject something
1406 char x = isColumn(sequenceOut_) ? 'C' : 'R';
1407 handler_->message(CLP_SIMPLEX_FLAG, messages_)
1408 << x << sequenceWithin(sequenceOut_)
1409 << CoinMessageEol;
1410 #ifdef COIN_DEVELOP
1411 printf("flag a %g %g\n", btranAlpha, alpha_);
1412 #endif
1413 //#define FEB_TRY
1414 #if 1
1415 // Make safer?
1416 factorization_->saferTolerances(-0.99, -1.03);
1417 #endif
1418 setFlagged(sequenceOut_);
1419 progress_.clearBadTimes();
1420 lastBadIteration_ = numberIterations_; // say be more cautious
1421 rowArray_[0]->clear();
1422 rowArray_[1]->clear();
1423 columnArray_[0]->clear();
1424 if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha) < 1.0e-8 && numberIterations_ > 100) {
1425 //printf("I think should declare infeasible\n");
1426 problemStatus_ = 1;
1427 returnCode = 1;
1428 break;
1429 }
1430 continue;
1431 }
1432 }
1433 }
1434 // update duals BEFORE replaceColumn so can do updateColumn
1435 double objectiveChange = 0.0;
1436 // do duals first as variables may flip bounds
1437 // rowArray_[0] and columnArray_[0] may have flips
1438 // so use rowArray_[3] for work array from here on
1439 int nswapped = 0;
1440 //rowArray_[0]->cleanAndPackSafe(1.0e-60);
1441 //columnArray_[0]->cleanAndPackSafe(1.0e-60);
1442 if (candidate == -1) {
1443 #if CLP_CAN_HAVE_ZERO_OBJ > 1
1444 if ((specialOptions_ & 16777216) == 0) {
1445 #endif
1446 // make sure incoming doesn't count
1447 Status saveStatus = getStatus(sequenceIn_);
1448 setStatus(sequenceIn_, basic);
1449 nswapped = updateDualsInDual(rowArray_[0], columnArray_[0],
1450 rowArray_[2], theta_,
1451 objectiveChange, false);
1452 setStatus(sequenceIn_, saveStatus);
1453 #if CLP_CAN_HAVE_ZERO_OBJ > 1
1454 } else {
1455 rowArray_[0]->clear();
1456 rowArray_[2]->clear();
1457 columnArray_[0]->clear();
1458 }
1459 #endif
1460 } else {
1461 updateDualsInValuesPass(rowArray_[0], columnArray_[0], theta_);
1462 }
1463 double oldDualOut = dualOut_;
1464 // which will change basic solution
1465 if (nswapped) {
1466 if (rowArray_[2]->getNumElements()) {
1467 factorization_->updateColumn(rowArray_[3], rowArray_[2]);
1468 dualRowPivot_->updatePrimalSolution(rowArray_[2],
1469 1.0, objectiveChange);
1470 }
1471 // recompute dualOut_
1472 valueOut_ = solution_[sequenceOut_];
1473 if (directionOut_ < 0) {
1474 dualOut_ = valueOut_ - upperOut_;
1475 } else {
1476 dualOut_ = lowerOut_ - valueOut_;
1477 }
1478 #if 0
1479 if (dualOut_ < 0.0) {
1480 #ifdef CLP_DEBUG
1481 if (handler_->logLevel() & 32) {
1482 printf(" dualOut_ %g %g save %g\n", dualOut_, averagePrimalInfeasibility, saveDualOut);
1483 printf("values %g %g %g %g %g %g %g\n", lowerOut_, valueOut_, upperOut_,
1484 objectiveChange,);
1485 }
1486 #endif
1487 if (upperOut_ == lowerOut_)
1488 dualOut_ = 0.0;
1489 }
1490 if(dualOut_ < -CoinMax(1.0e-12 * averagePrimalInfeasibility, 1.0e-8)
1491 && factorization_->pivots() > 100 &&
1492 getStatus(sequenceIn_) != isFree) {
1493 // going backwards - factorize
1494 dualRowPivot_->unrollWeights();
1495 problemStatus_ = -2; // factorize now
1496 returnCode = -2;
1497 break;
1498 }
1499 #endif
1500 }
1501 // amount primal will move
1502 double movement = -dualOut_ * directionOut_ / alpha_;
1503 double movementOld = oldDualOut * directionOut_ / alpha_;
1504 // so objective should increase by fabs(dj)*movement
1505 // but we already have objective change - so check will be good
1506 if (objectiveChange + fabs(movementOld * dualIn_) < -CoinMax(1.0e-5, 1.0e-12 * fabs(objectiveValue_))) {
1507 #ifdef CLP_DEBUG
1508 if (handler_->logLevel() & 32)
1509 printf("movement %g, swap change %g, rest %g * %g\n",
1510 objectiveChange + fabs(movement * dualIn_),
1511 objectiveChange, movement, dualIn_);
1512 #endif
1513 if (factorization_->pivots()) {
1514 // going backwards - factorize
1515 dualRowPivot_->unrollWeights();
1516 problemStatus_ = -2; // factorize now
1517 returnCode = -2;
1518 break;
1519 }
1520 }
1521 // if stable replace in basis
1522 int updateStatus = 123456789;
1523 #if ABOCA_LITE_FACTORIZATION
1524 if (numberThreads)
1525 cilk_sync;
1526 if (columnArray_[1]->getNumElements())
1527 updateStatus = factorization_->replaceColumn2(columnArray_[1],
1528 pivotRow_, alpha_);
1529 if (updateStatus == 123456789)
1530 #endif
1531 updateStatus = factorization_->replaceColumn(this,
1532 rowArray_[2],
1533 rowArray_[1],
1534 pivotRow_,
1535 alpha_,
1536 (moreSpecialOptions_ & 16) != 0,
1537 acceptablePivot);
1538 // If looks like bad pivot - refactorize
1539 if (fabs(dualOut_) > 1.0e50)
1540 updateStatus = 2;
1541 // if no pivots, bad update but reasonable alpha - take and invert
1542 if (updateStatus == 2 && !factorization_->pivots() && fabs(alpha_) > 1.0e-5)
1543 updateStatus = 4;
1544 if (updateStatus == 1 || updateStatus == 4) {
1545 // slight error
1546 if (factorization_->pivots() > 5 || updateStatus == 4) {
1547 problemStatus_ = -2; // factorize now
1548 returnCode = -3;
1549 }
1550 } else if (updateStatus == 2) {
1551 // major error
1552 dualRowPivot_->unrollWeights();
1553 // later we may need to unwind more e.g. fake bounds
1554 if (factorization_->pivots() && ((moreSpecialOptions_ & 16) == 0 || factorization_->pivots() > 4)) {
1555 problemStatus_ = -2; // factorize now
1556 returnCode = -2;
1557 moreSpecialOptions_ |= 16;
1558 double pivotTolerance = factorization_->pivotTolerance();
1559 if (pivotTolerance < 0.4 && factorization_->pivots() < 100) {
1560 factorization_->pivotTolerance(1.05 * pivotTolerance);
1561 #ifdef CLP_USEFUL_PRINTOUT
1562 printf("Changing pivot tolerance from %g to %g as ftran/btran error %g/%g\n",
1563 pivotTolerance, factorization_->pivotTolerance(),
1564 alpha_, btranAlpha);
1565 #endif
1566 }
1567 break;
1568 } else {
1569 // need to reject something
1570 char x = isColumn(sequenceOut_) ? 'C' : 'R';
1571 handler_->message(CLP_SIMPLEX_FLAG, messages_)
1572 << x << sequenceWithin(sequenceOut_)
1573 << CoinMessageEol;
1574 #ifdef COIN_DEVELOP
1575 printf("flag b %g\n", alpha_);
1576 #endif
1577 setFlagged(sequenceOut_);
1578 progress_.clearBadTimes();
1579 lastBadIteration_ = numberIterations_; // say be more cautious
1580 rowArray_[0]->clear();
1581 rowArray_[1]->clear();
1582 columnArray_[0]->clear();
1583 // make sure dual feasible
1584 // look at all rows and columns
1585 double objectiveChange = 0.0;
1586 updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1],
1587 0.0, objectiveChange, true);
1588 rowArray_[1]->clear();
1589 columnArray_[0]->clear();
1590 continue;
1591 }
1592 } else if (updateStatus == 3) {
1593 // out of memory
1594 // increase space if not many iterations
1595 if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200)
1596 factorization_->areaFactor(
1597 factorization_->areaFactor() * 1.1);
1598 problemStatus_ = -2; // factorize now
1599 } else if (updateStatus == 5) {
1600 problemStatus_ = -2; // factorize now
1601 }
1602 // update primal solution
1603 if (theta_ < 0.0 && candidate == -1) {
1604 #ifdef CLP_DEBUG
1605 if (handler_->logLevel() & 32)
1606 printf("negative theta %g\n", theta_);
1607 #endif
1608 theta_ = 0.0;
1609 }
1610 // do actual flips
1611 flipBounds(rowArray_[0], columnArray_[0]);
1612 //rowArray_[1]->expand();
1613 dualRowPivot_->updatePrimalSolution(rowArray_[1],
1614 movement,
1615 objectiveChange);
1616 #ifdef CLP_DEBUG
1617 double oldobj = objectiveValue_;
1618 #endif
1619 // modify dualout
1620 dualOut_ /= alpha_;
1621 dualOut_ *= -directionOut_;
1622 //setStatus(sequenceIn_,basic);
1623 dj_[sequenceIn_] = 0.0;
1624 double oldValue = valueIn_;
1625 if (directionIn_ == -1) {
1626 // as if from upper bound
1627 valueIn_ = upperIn_ + dualOut_;
1628 } else {
1629 // as if from lower bound
1630 valueIn_ = lowerIn_ + dualOut_;
1631 }
1632 objectiveChange += cost_[sequenceIn_] * (valueIn_ - oldValue);
1633 // outgoing
1634 // set dj to zero unless values pass
1635 if (directionOut_ > 0) {
1636 valueOut_ = lowerOut_;
1637 if (candidate == -1)
1638 dj_[sequenceOut_] = theta_;
1639 } else {
1640 valueOut_ = upperOut_;
1641 if (candidate == -1)
1642 dj_[sequenceOut_] = -theta_;
1643 }
1644 solution_[sequenceOut_] = valueOut_;
1645 int whatNext = housekeeping(objectiveChange);
1646 #if 0
1647 for (int i=0;i<numberRows_+numberColumns_;i++) {
1648 if (getStatus(i)==atLowerBound) {
1649 assert (dj_[i]>-1.0e-5);
1650 assert (solution_[i]<=lower_[i]+1.0e-5);
1651 } else if (getStatus(i)==atUpperBound) {
1652 assert (dj_[i]<1.0e-5);
1653 assert (solution_[i]>=upper_[i]-1.0e-5);
1654 }
1655 }
1656 #endif
1657 #ifdef CLP_REPORT_PROGRESS
1658 if (ixxxxxx > ixxyyyy - 5) {
1659 handler_->setLogLevel(63);
1660 int nTotal = numberColumns_ + numberRows_;
1661 double oldObj = 0.0;
1662 double newObj = 0.0;
1663 for (int i = 0; i < nTotal; i++) {
1664 if (savePSol[i])
1665 oldObj += savePSol[i] * saveCost[i];
1666 if (solution_[i])
1667 newObj += solution_[i] * cost_[i];
1668 bool printIt = false;
1669 if (cost_[i] != saveCost[i])
1670 printIt = true;
1671 if (status_[i] != saveStat[i])
1672 printIt = true;
1673 if (printIt)
1674 printf("%d old %d cost %g sol %g, new %d cost %g sol %g\n",
1675 i, saveStat[i], saveCost[i], savePSol[i],
1676 status_[i], cost_[i], solution_[i]);
1677 // difference
1678 savePSol[i] = solution_[i] - savePSol[i];
1679 }
1680 printf("pivots %d, old obj %g new %g\n",
1681 factorization_->pivots(),
1682 oldObj, newObj);
1683 memset(saveDj, 0, numberRows_ * sizeof(double));
1684 times(1.0, savePSol, saveDj);
1685 double largest = 1.0e-6;
1686 int k = -1;
1687 for (int i = 0; i < numberRows_; i++) {
1688 saveDj[i] -= savePSol[i + numberColumns_];
1689 if (fabs(saveDj[i]) > largest) {
1690 largest = fabs(saveDj[i]);
1691 k = i;
1692 }
1693 }
1694 if (k >= 0)
1695 printf("Not null %d %g\n", k, largest);
1696 }
1697 #endif
1698 #ifdef VUB
1699 {
1700 if ((sequenceIn_ < numberColumns_ && vub[sequenceIn_] >= 0) || toVub[sequenceIn_] >= 0 || (sequenceOut_ < numberColumns_ && vub[sequenceOut_] >= 0) || toVub[sequenceOut_] >= 0) {
1701 int inSequence = sequenceIn_;
1702 int inVub = -1;
1703 if (sequenceIn_ < numberColumns_)
1704 inVub = vub[sequenceIn_];
1705 int inBack = toVub[inSequence];
1706 int inSlack = -1;
1707 if (inSequence >= numberColumns_ && inBack >= 0) {
1708 inSlack = inSequence - numberColumns_;
1709 inSequence = inBack;
1710 inBack = toVub[inSequence];
1711 }
1712 if (inVub >= 0)
1713 printf("Vub %d in ", inSequence);
1714 if (inBack >= 0 && inSlack < 0)
1715 printf("%d (descendent of %d) in ", inSequence, inBack);
1716 if (inSlack >= 0)
1717 printf("slack for row %d -> %d (descendent of %d) in ", inSlack, inSequence, inBack);
1718 int outSequence = sequenceOut_;
1719 int outVub = -1;
1720 if (sequenceOut_ < numberColumns_)
1721 outVub = vub[sequenceOut_];
1722 int outBack = toVub[outSequence];
1723 int outSlack = -1;
1724 if (outSequence >= numberColumns_ && outBack >= 0) {
1725 outSlack = outSequence - numberColumns_;
1726 outSequence = outBack;
1727 outBack = toVub[outSequence];
1728 }
1729 if (outVub >= 0)
1730 printf("Vub %d out ", outSequence);
1731 if (outBack >= 0 && outSlack < 0)
1732 printf("%d (descendent of %d) out ", outSequence, outBack);
1733 if (outSlack >= 0)
1734 printf("slack for row %d -> %d (descendent of %d) out ", outSlack, outSequence, outBack);
1735 printf("\n");
1736 }
1737 }
1738 #endif
1739 #if 0
1740 if (numberIterations_ > 206033)
1741 handler_->setLogLevel(63);
1742 if (numberIterations_ > 210567)
1743 exit(77);
1744 #endif
1745 if (!givenDuals && ifValuesPass && ifValuesPass != 2) {
1746 handler_->message(CLP_END_VALUES_PASS, messages_)
1747 << numberIterations_;
1748 whatNext = 1;
1749 }
1750 #ifdef CHECK_ACCURACY
1751 if (whatNext) {
1752 CoinMemcpyN(solution_, (numberRows_ + numberColumns_), zzzzzz);
1753 }
1754 #endif
1755 //if (numberIterations_==1890)
1756 //whatNext=1;
1757 //if (numberIterations_>2000)
1758 //exit(77);
1759 // and set bounds correctly
1760 originalBound(sequenceIn_);
1761 changeBound(sequenceOut_);
1762 #ifdef CLP_DEBUG
1763 if (objectiveValue_ < oldobj - 1.0e-5 && (handler_->logLevel() & 16))
1764 printf("obj backwards %g %g\n", objectiveValue_, oldobj);
1765 #endif
1766 #if 0
1767 {
1768 for (int i = 0; i < numberRows_ + numberColumns_; i++) {
1769 FakeBound bound = getFakeBound(i);
1770 if (bound == ClpSimplexDual::upperFake) {
1771 assert (upper_[i] < 1.0e20);
1772 } else if (bound == ClpSimplexDual::lowerFake) {
1773 assert (lower_[i] > -1.0e20);
1774 } else if (bound == ClpSimplexDual::bothFake) {
1775 assert (upper_[i] < 1.0e20);
1776 assert (lower_[i] > -1.0e20);
1777 }
1778 }
1779 }
1780 #endif
1781 if (whatNext == 1 || candidate == -2) {
1782 problemStatus_ = -2; // refactorize
1783 } else if (whatNext == 2) {
1784 // maximum iterations or equivalent
1785 problemStatus_ = 3;
1786 returnCode = 3;
1787 break;
1788 }
1789 // Check event
1790 {
1791 int status = eventHandler_->event(ClpEventHandler::endOfIteration);
1792 if (status >= 0) {
1793 problemStatus_ = 5;
1794 secondaryStatus_ = ClpEventHandler::endOfIteration;
1795 returnCode = 4;
1796 break;
1797 }
1798 }
1799 } else {
1800 #ifdef CLP_INVESTIGATE_SERIAL
1801 z_thinks = 1;
1802 #endif
1803 // no incoming column is valid
1804 spareIntArray_[3] = pivotRow_;
1805 pivotRow_ = -1;
1806 #ifdef CLP_DEBUG
1807 if (handler_->logLevel() & 32)
1808 printf("** no column pivot\n");
1809 #endif
1810 delete[] ray_;
1811 ray_ = NULL;
1812 if ((factorization_->pivots() < 2
1813 || ((specialOptions_ & 2097152) != 0 && factorization_->pivots() < 50))
1814 && acceptablePivot_ <= 1.0e-8 && acceptablePivot_ > 0.0) {
1815 //&&goodAccuracy()) {
1816 // If not in branch and bound etc save ray
1817 if ((specialOptions_ & (1024 | 4096)) == 0 || (specialOptions_ & (32 | 2097152)) != 0) {
1818 // create ray anyway
1819 ray_ = new double[numberRows_];
1820 rowArray_[0]->expand(); // in case packed
1821 const double *array = rowArray_[0]->denseVector();
1822 for (int i = 0; i < numberRows_; i++)
1823 ray_[i] = array[i];
1824 #ifdef PRINT_RAY_METHOD
1825 {
1826 double *farkas = new double[2 * numberColumns_ + numberRows_];
1827 int nBasic = 0;
1828 int nPlusLower = 0;
1829 int nPlusFixedLower = 0;
1830 int nMinusLower = 0;
1831 int nMinusFixedLower = 0;
1832 int nPlusUpper = 0;
1833 int nPlusFixedUpper = 0;
1834 int nMinusUpper = 0;
1835 int nMinusFixedUpper = 0;
1836 memset(farkas, 0, (2 * numberColumns_ + numberRows_) * sizeof(double));
1837 transposeTimes(-1.0, ray_, farkas);
1838 for (int i = 0; i < numberRows_; i++) {
1839 if (fabs(ray_[i]) > 1.0e-7) {
1840 if (getRowStatus(i) == basic) {
1841 nBasic++;
1842 } else if (getRowStatus(i) == atLowerBound) {
1843 if (ray_[i] > 0.0)
1844 nPlusLower++;
1845 else
1846 nMinusLower++;
1847 } else if (getRowStatus(i) == atUpperBound) {
1848 if (ray_[i] > 0.0)
1849 nPlusUpper++;
1850 else
1851 nMinusUpper++;
1852 } else {
1853 // fixed slack
1854 }
1855 }
1856 }
1857 printf("Slacks %d basic lower +,- %d,%d upper +,- %d,%d\n",
1858 nBasic, nPlusLower, nMinusLower, nPlusUpper, nMinusLower);
1859 for (int i = 0; i < numberColumns_; i++) {
1860 if (fabs(farkas[i]) > 1.0e-7) {
1861 if (getColumnStatus(i) == basic) {
1862 nBasic++;
1863 } else if (getColumnStatus(i) == atLowerBound) {
1864 if (farkas[i] > 0.0)
1865 nPlusLower++;
1866 else
1867 nMinusLower++;
1868 } else if (getColumnStatus(i) == atUpperBound) {
1869 if (farkas[i] > 0.0)
1870 nPlusUpper++;
1871 else
1872 nMinusUpper++;
1873 } else {
1874 if (!lower_[i]) {
1875 if (farkas[i] > 0.0) {
1876 nPlusFixedLower++;
1877 } else {
1878 nMinusFixedLower++;
1879 }
1880 } else {
1881 if (farkas[i] > 0.0) {
1882 nPlusFixedUpper++;
1883 } else {
1884 nMinusFixedUpper++;
1885 }
1886 }
1887 }
1888 }
1889 }
1890 printf("End %d basic lower +,- %d,%d upper +,- %d,%d fixed %d,%d %d,%d\n",
1891 nBasic, nPlusLower, nMinusLower, nPlusUpper, nMinusUpper,
1892 nPlusFixedLower, nMinusFixedLower, nPlusFixedUpper, nMinusFixedUpper);
1893 printf("Dual creating infeasibility ray direction out %d - pivRow %d seqOut %d lower %g,val %g,upper %g\n",
1894 directionOut_, spareIntArray_[3], sequenceOut_, lowerOut_, valueOut_, upperOut_);
1895 delete[] farkas;
1896 }
1897 #endif
1898 } else {
1899 ray_ = NULL;
1900 }
1901 // If we have just factorized and infeasibility reasonable say infeas
1902 double dualTest = ((specialOptions_ & 4096) != 0) ? 1.0e8 : 1.0e13;
1903 // but if none at fake bounds
1904 if (!checkFakeBounds())
1905 dualTest = 0.0;
1906 if (((specialOptions_ & 4096) != 0 || bestPossiblePivot < 1.0e-11) && dualBound_ > dualTest) {
1907 double testValue = 1.0e-4;
1908 if (!factorization_->pivots() && numberPrimalInfeasibilities_ == 1)
1909 testValue = 1.0e-6;
1910 if (valueOut_ > upperOut_ + testValue || valueOut_ < lowerOut_ - testValue
1911 || (specialOptions_ & 64) == 0) {
1912 // say infeasible
1913 problemStatus_ = 1;
1914 // unless primal feasible!!!!
1915 //printf("%d %g %d %g\n",numberPrimalInfeasibilities_,sumPrimalInfeasibilities_,
1916 // numberDualInfeasibilities_,sumDualInfeasibilities_);
1917 //#define TEST_CLP_NODE
1918 #ifndef TEST_CLP_NODE
1919 // Should be correct - but ...
1920 int numberFake = numberAtFakeBound();
1921 double sumPrimal = (!numberFake) ? 2.0e5 : sumPrimalInfeasibilities_;
1922 if (sumPrimalInfeasibilities_ < 1.0e-3 || sumDualInfeasibilities_ > 1.0e-5 || (sumPrimal < 1.0e5 && (specialOptions_ & 1024) != 0 && factorization_->pivots())) {
1923 if (sumPrimal > 50.0 && factorization_->pivots() > 2) {
1924 problemStatus_ = -4;
1925 #ifdef COIN_DEVELOP
1926 printf("status to -4 at %d - primalinf %g pivots %d\n",
1927 __LINE__, sumPrimalInfeasibilities_,
1928 factorization_->pivots());
1929 #endif
1930 } else {
1931 problemStatus_ = 10;
1932 #if COIN_DEVELOP > 1
1933 printf("returning at %d - primal %d %g - dual %d %g fake %d weight %g - pivs %d - options (1024-16384) %d %d %d %d %d\n",
1934 __LINE__, numberPrimalInfeasibilities_,
1935 sumPrimalInfeasibilities_,
1936 numberDualInfeasibilities_, sumDualInfeasibilities_,
1937 numberFake_, dualBound_, factorization_->pivots(),
1938 (specialOptions_ & 1024) != 0 ? 1 : 0,
1939 (specialOptions_ & 2048) != 0 ? 1 : 0,
1940 (specialOptions_ & 4096) != 0 ? 1 : 0,
1941 (specialOptions_ & 8192) != 0 ? 1 : 0,
1942 (specialOptions_ & 16384) != 0 ? 1 : 0);
1943 #endif
1944 // Get rid of objective
1945 if ((specialOptions_ & 16384) == 0 &&
1946 (moreSpecialOptions_ & 256) == 0)
1947 objective_ = new ClpLinearObjective(NULL, numberColumns_);
1948 }
1949 }
1950 #else
1951 if (sumPrimalInfeasibilities_ < 1.0e-3 || sumDualInfeasibilities_ > 1.0e-6) {
1952 #ifdef COIN_DEVELOP
1953 printf("at %d - primal %d %g - dual %d %g fake %d weight %g - pivs %d\n",
1954 __LINE__, numberPrimalInfeasibilities_,
1955 sumPrimalInfeasibilities_,
1956 numberDualInfeasibilities_, sumDualInfeasibilities_,
1957 numberFake_, dualBound_, factorization_->pivots());
1958 #endif
1959 if ((specialOptions_ & 1024) != 0 && factorization_->pivots()) {
1960 problemStatus_ = 10;
1961 #if COIN_DEVELOP > 1
1962 printf("returning at %d\n", __LINE__);
1963 #endif
1964 // Get rid of objective
1965 if ((specialOptions_ & 16384) == 0 &&
1966 (moreSpecialOptions_ & 256) == 0)
1967 objective_ = new ClpLinearObjective(NULL, numberColumns_);
1968 }
1969 }
1970 #endif
1971 rowArray_[0]->clear();
1972 columnArray_[0]->clear();
1973 returnCode = 1;
1974 break;
1975 }
1976 }
1977 // If special option set - put off as long as possible
1978 if ((specialOptions_ & 64) == 0 || (moreSpecialOptions_ & 64) != 0) {
1979 if (factorization_->pivots() == 0)
1980 problemStatus_ = -4; //say looks infeasible
1981 } else {
1982 // flag
1983 char x = isColumn(sequenceOut_) ? 'C' : 'R';
1984 handler_->message(CLP_SIMPLEX_FLAG, messages_)
1985 << x << sequenceWithin(sequenceOut_)
1986 << CoinMessageEol;
1987 #ifdef COIN_DEVELOP
1988 printf("flag c\n");
1989 #endif
1990 setFlagged(sequenceOut_);
1991 if (!factorization_->pivots()) {
1992 rowArray_[0]->clear();
1993 columnArray_[0]->clear();
1994 continue;
1995 }
1996 }
1997 }
1998 acceptablePivot_ = fabs(acceptablePivot_);
1999 if (factorization_->pivots() < 5 && acceptablePivot_ > 1.0e-8)
2000 acceptablePivot_ = 1.0e-8;
2001 rowArray_[0]->clear();
2002 columnArray_[0]->clear();
2003 returnCode = 1;
2004 break;
2005 }
2006 } else {
2007 #ifdef CLP_INVESTIGATE_SERIAL
2008 z_thinks = 0;
2009 #endif
2010 // no pivot row
2011 #ifdef CLP_DEBUG
2012 if (handler_->logLevel() & 32)
2013 printf("** no row pivot\n");
2014 #endif
2015 // If in branch and bound try and get rid of fixed variables
2016 if ((specialOptions_ & 1024) != 0 && CLEAN_FIXED) {
2017 assert(!candidateList);
2018 candidateList = new int[numberRows_];
2019 int iRow;
2020 for (iRow = 0; iRow < numberRows_; iRow++) {
2021 int iPivot = pivotVariable_[iRow];
2022 if (flagged(iPivot) || !pivoted(iPivot))
2023 continue;
2024 assert(iPivot < numberColumns_ && lower_[iPivot] == upper_[iPivot]);
2025 candidateList[numberCandidates++] = iRow;
2026 }
2027 // and set first candidate
2028 if (!numberCandidates) {
2029 delete[] candidateList;
2030 candidateList = NULL;
2031 int iRow;
2032 for (iRow = 0; iRow < numberRows_; iRow++) {
2033 int iPivot = pivotVariable_[iRow];
2034 clearPivoted(iPivot);
2035 }
2036 } else {
2037 ifValuesPass = 2;
2038 continue;
2039 }
2040 }
2041 int numberPivots = factorization_->pivots();
2042 bool specialCase;
2043 int useNumberFake;
2044 returnCode = 0;
2045 if (numberPivots <= CoinMax(dontFactorizePivots_, 20) && (specialOptions_ & 2048) != 0 && (true || !numberChanged_ || perturbation_ == 101)
2046 && dualBound_ >= 1.0e8) {
2047 specialCase = true;
2048 // as dual bound high - should be okay
2049 useNumberFake = 0;
2050 } else {
2051 specialCase = false;
2052 useNumberFake = numberFake_;
2053 }
2054 if (!numberPivots || specialCase) {
2055 if (numberPrimalInfeasibilities_ && problemStatus_ == -1)
2056 problemStatus_ = -4;
2057 // may have crept through - so may be optimal
2058 // check any flagged variables
2059 int iRow;
2060 for (iRow = 0; iRow < numberRows_; iRow++) {
2061 int iPivot = pivotVariable_[iRow];
2062 if (flagged(iPivot))
2063 break;
2064 }
2065 if (iRow < numberRows_ && numberPivots) {
2066 // try factorization
2067 returnCode = -2;
2068 }
2069
2070 if (useNumberFake || numberDualInfeasibilities_) {
2071 // may be dual infeasible
2072 if ((specialOptions_ & 1024) == 0)
2073 problemStatus_ = -5;
2074 else if (!useNumberFake && numberPrimalInfeasibilities_
2075 && !numberPivots)
2076 problemStatus_ = 1;
2077 } else {
2078 if (iRow < numberRows_) {
2079 #ifdef COIN_DEVELOP
2080 std::cout << "Flagged variables at end - infeasible?" << std::endl;
2081 printf("Probably infeasible - pivot was %g\n", alpha_);
2082 #endif
2083 //if (fabs(alpha_)<1.0e-4) {
2084 //problemStatus_=1;
2085 //} else {
2086 #ifdef CLP_DEBUG
2087 abort();
2088 #endif
2089 //}
2090 problemStatus_ = -5;
2091 } else {
2092 problemStatus_ = 0;
2093 #ifndef CLP_CHECK_NUMBER_PIVOTS
2094 #define CLP_CHECK_NUMBER_PIVOTS 10
2095 #endif
2096 #if CLP_CHECK_NUMBER_PIVOTS < 20
2097 if (numberPivots > CLP_CHECK_NUMBER_PIVOTS) {
2098 #ifndef NDEBUG_CLP
2099 int nTotal = numberRows_ + numberColumns_;
2100 double *comp = CoinCopyOfArray(solution_, nTotal);
2101 #endif
2102 computePrimals(rowActivityWork_, columnActivityWork_);
2103 #ifndef NDEBUG_CLP
2104 double largest = 1.0e-5;
2105 int bad = -1;
2106 for (int i = 0; i < nTotal; i++) {
2107 double value = solution_[i];
2108 double larger = CoinMax(fabs(value), fabs(comp[i]));
2109 double tol = 1.0e-5 + 1.0e-5 * larger;
2110 double diff = fabs(value - comp[i]);
2111 if (diff - tol > largest) {
2112 bad = i;
2113 largest = diff - tol;
2114 }
2115 }
2116 if (bad >= 0)
2117 COIN_DETAIL_PRINT(printf("bad %d old %g new %g\n", bad, comp[bad], solution_[bad]));
2118 #endif
2119 checkPrimalSolution(rowActivityWork_, columnActivityWork_);
2120 if (numberPrimalInfeasibilities_) {
2121 #ifdef CLP_INVESTIGATE
2122 printf("XXX Infeas ? %d inf summing to %g\n", numberPrimalInfeasibilities_,
2123 sumPrimalInfeasibilities_);
2124 #endif
2125 problemStatus_ = -1;
2126 returnCode = -2;
2127 }
2128 #ifndef NDEBUG_CLP
2129 memcpy(solution_, comp, nTotal * sizeof(double));
2130 delete[] comp;
2131 #endif
2132 }
2133 #endif
2134 if (!problemStatus_) {
2135 // make it look OK
2136 numberPrimalInfeasibilities_ = 0;
2137 sumPrimalInfeasibilities_ = 0.0;
2138 numberDualInfeasibilities_ = 0;
2139 sumDualInfeasibilities_ = 0.0;
2140 // May be perturbed
2141 if (perturbation_ == 101 || numberChanged_) {
2142 numberChanged_ = 0; // Number of variables with changed costs
2143 perturbation_ = 102; // stop any perturbations
2144 //double changeCost;
2145 //changeBounds(1,NULL,changeCost);
2146 createRim4(false);
2147 // make sure duals are current
2148 computeDuals(givenDuals);
2149 checkDualSolution();
2150 progress_.modifyObjective(-COIN_DBL_MAX);
2151 if (numberDualInfeasibilities_) {
2152 problemStatus_ = 10; // was -3;
2153 } else {
2154 computeObjectiveValue(true);
2155 }
2156 } else if (numberPivots) {
2157 computeObjectiveValue(true);
2158 }
2159 if (numberPivots < -1000) {
2160 // objective may be wrong
2161 objectiveValue_ = innerProduct(cost_, numberColumns_ + numberRows_, solution_);
2162 objectiveValue_ += objective_->nonlinearOffset();
2163 objectiveValue_ /= (objectiveScale_ * rhsScale_);
2164 if ((specialOptions_ & 16384) == 0) {
2165 // and dual_ may be wrong (i.e. for fixed or basic)
2166 CoinIndexedVector *arrayVector = rowArray_[1];
2167 arrayVector->clear();
2168 int iRow;
2169 double *array = arrayVector->denseVector();
2170 /* Use dual_ instead of array
2171 Even though dual_ is only numberRows_ long this is
2172 okay as gets permuted to longer rowArray_[2]
2173 */
2174 arrayVector->setDenseVector(dual_);
2175 int *index = arrayVector->getIndices();
2176 int number = 0;
2177 for (iRow = 0; iRow < numberRows_; iRow++) {
2178 int iPivot = pivotVariable_[iRow];
2179 double value = cost_[iPivot];
2180 dual_[iRow] = value;
2181 if (value) {
2182 index[number++] = iRow;
2183 }
2184 }
2185 arrayVector->setNumElements(number);
2186 // Extended duals before "updateTranspose"
2187 matrix_->dualExpanded(this, arrayVector, NULL, 0);
2188 // Btran basic costs
2189 rowArray_[2]->clear();
2190 factorization_->updateColumnTranspose(rowArray_[2], arrayVector);
2191 // and return vector
2192 arrayVector->setDenseVector(array);
2193 }
2194 }
2195 sumPrimalInfeasibilities_ = 0.0;
2196 }
2197 if ((specialOptions_ & (1024 + 16384)) != 0 && !problemStatus_) {
2198 CoinIndexedVector *arrayVector = rowArray_[1];
2199 arrayVector->clear();
2200 double *rhs = arrayVector->denseVector();
2201 times(1.0, solution_, rhs);
2202 #ifdef CHECK_ACCURACY
2203 bool bad = false;
2204 #endif
2205 bool bad2 = false;
2206 int i;
2207 for (i = 0; i < numberRows_; i++) {
2208 if (rhs[i] < rowLowerWork_[i] - primalTolerance_ || rhs[i] > rowUpperWork_[i] + primalTolerance_) {
2209 bad2 = true;
2210 #ifdef CHECK_ACCURACY
2211 printf("row %d out of bounds %g, %g correct %g bad %g\n", i,
2212 rowLowerWork_[i], rowUpperWork_[i],
2213 rhs[i], rowActivityWork_[i]);
2214 #endif
2215 } else if (fabs(rhs[i] - rowActivityWork_[i]) > 1.0e-3) {
2216 #ifdef CHECK_ACCURACY
2217 bad = true;
2218 printf("row %d correct %g bad %g\n", i, rhs[i], rowActivityWork_[i]);
2219 #endif
2220 }
2221 rhs[i] = 0.0;
2222 }
2223 for (i = 0; i < numberColumns_; i++) {
2224 if (solution_[i] < columnLowerWork_[i] - primalTolerance_ || solution_[i] > columnUpperWork_[i] + primalTolerance_) {
2225 bad2 = true;
2226 #ifdef CHECK_ACCURACY
2227 printf("column %d out of bounds %g, %g correct %g bad %g\n", i,
2228 columnLowerWork_[i], columnUpperWork_[i],
2229 solution_[i], columnActivityWork_[i]);
2230 #endif
2231 }
2232 }
2233 if (bad2) {
2234 problemStatus_ = -3;
2235 returnCode = -2;
2236 // Force to re-factorize early next time
2237 int numberPivots = factorization_->pivots();
2238 forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1);
2239 }
2240 }
2241 }
2242 }
2243 } else {
2244 problemStatus_ = -3;
2245 returnCode = -2;
2246 // Force to re-factorize early next time
2247 int numberPivots = factorization_->pivots();
2248 forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1);
2249 }
2250 break;
2251 }
2252 }
2253 if (givenDuals) {
2254 CoinMemcpyN(dj_, numberRows_ + numberColumns_, givenDuals);
2255 // get rid of any values pass array
2256 delete[] candidateList;
2257 }
2258 delete[] dubiousWeights;
2259 #ifdef CLP_REPORT_PROGRESS
2260 if (ixxxxxx > ixxyyyy - 5) {
2261 int nTotal = numberColumns_ + numberRows_;
2262 double oldObj = 0.0;
2263 double newObj = 0.0;
2264 for (int i = 0; i < nTotal; i++) {
2265 if (savePSol[i])
2266 oldObj += savePSol[i] * saveCost[i];
2267 if (solution_[i])
2268 newObj += solution_[i] * cost_[i];
2269 bool printIt = false;
2270 if (cost_[i] != saveCost[i])
2271 printIt = true;
2272 if (status_[i] != saveStat[i])
2273 printIt = true;
2274 if (printIt)
2275 printf("%d old %d cost %g sol %g, new %d cost %g sol %g\n",
2276 i, saveStat[i], saveCost[i], savePSol[i],
2277 status_[i], cost_[i], solution_[i]);
2278 // difference
2279 savePSol[i] = solution_[i] - savePSol[i];
2280 }
2281 printf("exit pivots %d, old obj %g new %g\n",
2282 factorization_->pivots(),
2283 oldObj, newObj);
2284 memset(saveDj, 0, numberRows_ * sizeof(double));
2285 times(1.0, savePSol, saveDj);
2286 double largest = 1.0e-6;
2287 int k = -1;
2288 for (int i = 0; i < numberRows_; i++) {
2289 saveDj[i] -= savePSol[i + numberColumns_];
2290 if (fabs(saveDj[i]) > largest) {
2291 largest = fabs(saveDj[i]);
2292 k = i;
2293 }
2294 }
2295 if (k >= 0)
2296 printf("Not null %d %g\n", k, largest);
2297 }
2298 delete[] savePSol;
2299 delete[] saveDj;
2300 delete[] saveCost;
2301 delete[] saveStat;
2302 #endif
2303 return returnCode;
2304 }
2305 #if ABOCA_LITE
2306 static void
updateDualBit(clpTempInfo & info)2307 updateDualBit(clpTempInfo &info)
2308 {
2309 int numberInfeasibilities = 0;
2310 double tolerance = info.tolerance;
2311 double theta = info.theta;
2312 double *COIN_RESTRICT reducedCost = info.reducedCost;
2313 const double *COIN_RESTRICT lower = info.lower;
2314 const double *COIN_RESTRICT upper = info.upper;
2315 double *COIN_RESTRICT work = info.work;
2316 int number = info.numberToDo;
2317 int *COIN_RESTRICT which = info.which;
2318 const unsigned char *COIN_RESTRICT statusArray = info.status;
2319 double multiplier[] = { -1.0, 1.0 };
2320 for (int i = 0; i < number; i++) {
2321 int iSequence = which[i];
2322 double alphaI = work[i];
2323 work[i] = 0.0;
2324
2325 int iStatus = (statusArray[iSequence] & 3) - 1;
2326 if (iStatus) {
2327 double value = reducedCost[iSequence] - theta * alphaI;
2328 reducedCost[iSequence] = value;
2329 //printf("xx %d %.18g\n",iSequence,reducedCost[iSequence]);
2330 double mult = multiplier[iStatus - 1];
2331 value *= mult;
2332 // skip if free
2333 if (value < -tolerance && iStatus > 0) {
2334 // flipping bounds
2335 double movement = mult * (upper[iSequence] - lower[iSequence]);
2336 work[numberInfeasibilities] = movement;
2337 which[numberInfeasibilities++] = iSequence;
2338 }
2339 }
2340 }
2341 info.numberInfeasibilities = numberInfeasibilities;
2342 }
2343 #endif
2344 /* The duals are updated by the given arrays.
2345 Returns number of infeasibilities.
2346 rowArray and columnarray will have flipped
2347 The output vector has movement (row length array) */
updateDualsInDual(CoinIndexedVector * rowArray,CoinIndexedVector * columnArray,CoinIndexedVector * outputArray,double theta,double & objectiveChange,bool fullRecompute)2348 int ClpSimplexDual::updateDualsInDual(CoinIndexedVector *rowArray,
2349 CoinIndexedVector *columnArray,
2350 CoinIndexedVector *outputArray,
2351 double theta,
2352 double &objectiveChange,
2353 bool fullRecompute)
2354 {
2355
2356 outputArray->clear();
2357
2358 int numberInfeasibilities = 0;
2359 int numberRowInfeasibilities = 0;
2360
2361 // get a tolerance
2362 double tolerance = dualTolerance_;
2363 // we can't really trust infeasibilities if there is dual error
2364 double error = CoinMin(1.0e-2, largestDualError_);
2365 // allow tolerance at least slightly bigger than standard
2366 tolerance = tolerance + error;
2367
2368 double changeObj = 0.0;
2369
2370 // Coding is very similar but we can save a bit by splitting
2371 // Do rows
2372 if (!fullRecompute) {
2373 int i;
2374 double *COIN_RESTRICT reducedCost = djRegion(0);
2375 const double *COIN_RESTRICT lower = lowerRegion(0);
2376 const double *COIN_RESTRICT upper = upperRegion(0);
2377 const double *COIN_RESTRICT cost = costRegion(0);
2378 double *COIN_RESTRICT work;
2379 int number;
2380 int *COIN_RESTRICT which;
2381 const unsigned char *COIN_RESTRICT statusArray = status_ + numberColumns_;
2382 assert(rowArray->packedMode());
2383 work = rowArray->denseVector();
2384 number = rowArray->getNumElements();
2385 which = rowArray->getIndices();
2386 double multiplier[] = {0.0, 0.0, -1.0, 1.0 };
2387 for (i = 0; i < number; i++) {
2388 int iSequence = which[i];
2389 double alphaI = work[i];
2390 work[i] = 0.0;
2391 int iStatus = (statusArray[iSequence] & 3) - 1;
2392 if (iStatus) {
2393 double value = reducedCost[iSequence] - theta * alphaI;
2394 // NO - can have free assert (iStatus>0);
2395 reducedCost[iSequence] = value;
2396 double mult = multiplier[iStatus + 1];
2397 value *= mult;
2398 // skip if free
2399 if (value < -tolerance) {
2400 // flipping bounds
2401 double movement = mult * (lower[iSequence] - upper[iSequence]);
2402 which[numberInfeasibilities++] = iSequence;
2403 #ifndef NDEBUG
2404 if (fabs(movement) >= 1.0e30)
2405 resetFakeBounds(-1000 - iSequence);
2406 #endif
2407 #ifdef CLP_DEBUG
2408 if ((handler_->logLevel() & 32))
2409 printf("%d %d, new dj %g, alpha %g, movement %g\n",
2410 0, iSequence, value, alphaI, movement);
2411 #endif
2412 changeObj -= movement * cost[iSequence];
2413 outputArray->quickAdd(iSequence, movement);
2414 }
2415 }
2416 }
2417 // Do columns
2418 multiplier[0] = -1.0;
2419 multiplier[1] = 1.0;
2420 reducedCost = djRegion(1);
2421 lower = lowerRegion(1);
2422 upper = upperRegion(1);
2423 cost = costRegion(1);
2424 // set number of infeasibilities in row array
2425 numberRowInfeasibilities = numberInfeasibilities;
2426 rowArray->setNumElements(numberInfeasibilities);
2427 numberInfeasibilities = 0;
2428 work = columnArray->denseVector();
2429 number = columnArray->getNumElements();
2430 which = columnArray->getIndices();
2431 if ((moreSpecialOptions_ & 8) != 0) {
2432 const unsigned char *COIN_RESTRICT statusArray = status_;
2433 #if ABOCA_LITE
2434 int numberThreads = abcState();
2435 if (numberThreads) {
2436 clpTempInfo info[ABOCA_LITE];
2437 int chunk = (number + numberThreads - 1) / numberThreads;
2438 int n = 0;
2439 int *whichX = which;
2440 for (i = 0; i < numberThreads; i++) {
2441 info[i].theta = theta;
2442 info[i].tolerance = tolerance;
2443 info[i].reducedCost = reducedCost;
2444 info[i].lower = lower;
2445 info[i].upper = upper;
2446 info[i].status = statusArray;
2447 info[i].which = which + n;
2448 info[i].work = work + n;
2449 info[i].numberToDo = CoinMin(chunk, number - n);
2450 n += chunk;
2451 }
2452 for (i = 0; i < numberThreads; i++) {
2453 cilk_spawn updateDualBit(info[i]);
2454 }
2455 cilk_sync;
2456 for (i = 0; i < numberThreads; i++) {
2457 int n = info[i].numberInfeasibilities;
2458 double *workV = info[i].work;
2459 int *whichV = info[i].which;
2460 for (int j = 0; j < n; j++) {
2461 int iSequence = whichV[j];
2462 double movement = workV[j];
2463 workV[j] = 0.0;
2464 whichX[numberInfeasibilities++] = iSequence;
2465 #ifndef NDEBUG
2466 if (fabs(movement) >= 1.0e30)
2467 resetFakeBounds(-1000 - iSequence);
2468 #endif
2469 changeObj += movement * cost[iSequence];
2470 matrix_->add(this, outputArray, iSequence, movement);
2471 }
2472 }
2473 } else {
2474 #endif
2475 for (i = 0; i < number; i++) {
2476 int iSequence = which[i];
2477 double alphaI = work[i];
2478 work[i] = 0.0;
2479
2480 int iStatus = (statusArray[iSequence] & 3) - 1;
2481 if (iStatus) {
2482 double value = reducedCost[iSequence] - theta * alphaI;
2483 assert(iStatus > 0);
2484 reducedCost[iSequence] = value;
2485 //printf("xx %d %.18g\n",iSequence,reducedCost[iSequence]);
2486 double mult = multiplier[iStatus - 1];
2487 value *= mult;
2488 // skip if free
2489 if (value < -tolerance && iStatus > 0) {
2490 // flipping bounds
2491 double movement = mult * (upper[iSequence] - lower[iSequence]);
2492 which[numberInfeasibilities++] = iSequence;
2493 #ifndef NDEBUG
2494 if (fabs(movement) >= 1.0e30)
2495 resetFakeBounds(-1000 - iSequence);
2496 #endif
2497 #ifdef CLP_DEBUG
2498 if ((handler_->logLevel() & 32))
2499 printf("%d %d, new dj %g, alpha %g, movement %g\n",
2500 1, iSequence, value, alphaI, movement);
2501 #endif
2502 changeObj += movement * cost[iSequence];
2503 matrix_->add(this, outputArray, iSequence, movement);
2504 }
2505 }
2506 }
2507 #if ABOCA_LITE
2508 }
2509 #endif
2510 } else {
2511 for (i = 0; i < number; i++) {
2512 int iSequence = which[i];
2513 double alphaI = work[i];
2514 work[i] = 0.0;
2515
2516 Status status = getStatus(iSequence);
2517 if (status == atLowerBound) {
2518 double value = reducedCost[iSequence] - theta * alphaI;
2519 reducedCost[iSequence] = value;
2520 double movement = 0.0;
2521
2522 if (value < -tolerance) {
2523 // to upper bound
2524 which[numberInfeasibilities++] = iSequence;
2525 movement = upper[iSequence] - lower[iSequence];
2526 #ifndef NDEBUG
2527 if (fabs(movement) >= 1.0e30)
2528 resetFakeBounds(-1000 - iSequence);
2529 #endif
2530 #ifdef CLP_DEBUG
2531 if ((handler_->logLevel() & 32))
2532 printf("%d %d, new dj %g, alpha %g, movement %g\n",
2533 1, iSequence, value, alphaI, movement);
2534 #endif
2535 changeObj += movement * cost[iSequence];
2536 matrix_->add(this, outputArray, iSequence, movement);
2537 }
2538 } else if (status == atUpperBound) {
2539 double value = reducedCost[iSequence] - theta * alphaI;
2540 reducedCost[iSequence] = value;
2541 double movement = 0.0;
2542
2543 if (value > tolerance) {
2544 // to lower bound (if swap)
2545 which[numberInfeasibilities++] = iSequence;
2546 movement = lower[iSequence] - upper[iSequence];
2547 #ifndef NDEBUG
2548 if (fabs(movement) >= 1.0e30)
2549 resetFakeBounds(-1000 - iSequence);
2550 #endif
2551 #ifdef CLP_DEBUG
2552 if ((handler_->logLevel() & 32))
2553 printf("%d %d, new dj %g, alpha %g, movement %g\n",
2554 1, iSequence, value, alphaI, movement);
2555 #endif
2556 changeObj += movement * cost[iSequence];
2557 matrix_->add(this, outputArray, iSequence, movement);
2558 }
2559 } else if (status == isFree) {
2560 double value = reducedCost[iSequence] - theta * alphaI;
2561 reducedCost[iSequence] = value;
2562 }
2563 }
2564 }
2565 } else {
2566 double *COIN_RESTRICT solution = solutionRegion(0);
2567 double *COIN_RESTRICT reducedCost = djRegion(0);
2568 double *COIN_RESTRICT lower = lowerRegion(0);
2569 double *COIN_RESTRICT upper = upperRegion(0);
2570 const double *COIN_RESTRICT cost = costRegion(0);
2571 int *COIN_RESTRICT which;
2572 which = rowArray->getIndices();
2573 int iSequence;
2574 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
2575 double value = reducedCost[iSequence];
2576
2577 Status status = getStatus(iSequence + numberColumns_);
2578 // more likely to be at upper bound ?
2579 if (status == atUpperBound) {
2580 double movement = 0.0;
2581 //#define NO_SWAP7
2582 if (value > tolerance) {
2583 // to lower bound (if swap)
2584 // put back alpha
2585 which[numberInfeasibilities++] = iSequence;
2586 movement = lower[iSequence] - upper[iSequence];
2587 #define TRY_SET_FAKE
2588 #ifdef TRY_SET_FAKE
2589 if (fabs(movement) > dualBound_) {
2590 FakeBound bound = getFakeBound(iSequence + numberColumns_);
2591 if (bound == ClpSimplexDual::noFake) {
2592 setFakeBound(iSequence + numberColumns_,
2593 ClpSimplexDual::lowerFake);
2594 lower[iSequence] = upper[iSequence] - dualBound_;
2595 assert(fabs(lower[iSequence]) < 1.0e30);
2596 movement = lower[iSequence] - upper[iSequence];
2597 numberFake_++;
2598 #ifndef NDEBUG
2599 } else {
2600 if (fabs(movement) >= 1.0e30)
2601 resetFakeBounds(-1000 - iSequence);
2602 #endif
2603 }
2604 }
2605 #endif
2606 changeObj += movement * cost[iSequence];
2607 outputArray->quickAdd(iSequence, -movement);
2608 #ifndef NO_SWAP7
2609 } else if (value > -tolerance) {
2610 // at correct bound but may swap
2611 FakeBound bound = getFakeBound(iSequence + numberColumns_);
2612 if (bound == ClpSimplexDual::upperFake) {
2613 movement = lower[iSequence] - upper[iSequence];
2614 #ifndef NDEBUG
2615 if (fabs(movement) >= 1.0e30)
2616 resetFakeBounds(-1000 - iSequence);
2617 #endif
2618 setStatus(iSequence + numberColumns_, atLowerBound);
2619 solution[iSequence] = lower[iSequence];
2620 changeObj += movement * cost[iSequence];
2621 //numberFake_--;
2622 //setFakeBound(iSequence+numberColumns_,noFake);
2623 }
2624 #endif
2625 }
2626 } else if (status == atLowerBound) {
2627 double movement = 0.0;
2628
2629 if (value < -tolerance) {
2630 // to upper bound
2631 // put back alpha
2632 which[numberInfeasibilities++] = iSequence;
2633 movement = upper[iSequence] - lower[iSequence];
2634 #ifdef TRY_SET_FAKE
2635 if (fabs(movement) > dualBound_) {
2636 FakeBound bound = getFakeBound(iSequence + numberColumns_);
2637 if (bound == ClpSimplexDual::noFake) {
2638 setFakeBound(iSequence + numberColumns_,
2639 ClpSimplexDual::upperFake);
2640 upper[iSequence] = lower[iSequence] + dualBound_;
2641 assert(fabs(upper[iSequence]) < 1.0e30);
2642 movement = upper[iSequence] - lower[iSequence];
2643 numberFake_++;
2644 #ifndef NDEBUG
2645 } else {
2646 if (fabs(movement) >= 1.0e30)
2647 resetFakeBounds(-1000 - iSequence);
2648 #endif
2649 }
2650 }
2651 #endif
2652 changeObj += movement * cost[iSequence];
2653 outputArray->quickAdd(iSequence, -movement);
2654 #ifndef NO_SWAP7
2655 } else if (value < tolerance) {
2656 // at correct bound but may swap
2657 FakeBound bound = getFakeBound(iSequence + numberColumns_);
2658 if (bound == ClpSimplexDual::lowerFake) {
2659 movement = upper[iSequence] - lower[iSequence];
2660 #ifndef NDEBUG
2661 if (fabs(movement) >= 1.0e30)
2662 resetFakeBounds(-1000 - iSequence);
2663 #endif
2664 setStatus(iSequence + numberColumns_, atUpperBound);
2665 solution[iSequence] = upper[iSequence];
2666 changeObj += movement * cost[iSequence];
2667 //numberFake_--;
2668 //setFakeBound(iSequence+numberColumns_,noFake);
2669 }
2670 #endif
2671 }
2672 }
2673 }
2674 // Do columns
2675 solution = solutionRegion(1);
2676 reducedCost = djRegion(1);
2677 lower = lowerRegion(1);
2678 upper = upperRegion(1);
2679 cost = costRegion(1);
2680 // set number of infeasibilities in row array
2681 numberRowInfeasibilities = numberInfeasibilities;
2682 rowArray->setNumElements(numberInfeasibilities);
2683 numberInfeasibilities = 0;
2684 which = columnArray->getIndices();
2685 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
2686 double value = reducedCost[iSequence];
2687
2688 Status status = getStatus(iSequence);
2689 if (status == atLowerBound) {
2690 double movement = 0.0;
2691
2692 if (value < -tolerance) {
2693 // to upper bound
2694 // put back alpha
2695 which[numberInfeasibilities++] = iSequence;
2696 movement = upper[iSequence] - lower[iSequence];
2697 #ifdef TRY_SET_FAKE
2698 if (fabs(movement) > dualBound_) {
2699 FakeBound bound = getFakeBound(iSequence);
2700 if (bound == ClpSimplexDual::noFake) {
2701 setFakeBound(iSequence,
2702 ClpSimplexDual::upperFake);
2703 upper[iSequence] = lower[iSequence] + dualBound_;
2704 assert(fabs(upper[iSequence]) < 1.0e30);
2705 movement = upper[iSequence] - lower[iSequence];
2706 numberFake_++;
2707 #ifndef NDEBUG
2708 } else {
2709 if (fabs(movement) >= 1.0e30)
2710 resetFakeBounds(-1000 - iSequence);
2711 #endif
2712 }
2713 }
2714 #endif
2715 changeObj += movement * cost[iSequence];
2716 matrix_->add(this, outputArray, iSequence, movement);
2717 #ifndef NO_SWAP7
2718 } else if (value < tolerance) {
2719 // at correct bound but may swap
2720 FakeBound bound = getFakeBound(iSequence);
2721 if (bound == ClpSimplexDual::lowerFake) {
2722 movement = upper[iSequence] - lower[iSequence];
2723 #ifndef NDEBUG
2724 if (fabs(movement) >= 1.0e30)
2725 resetFakeBounds(-1000 - iSequence);
2726 #endif
2727 setStatus(iSequence, atUpperBound);
2728 solution[iSequence] = upper[iSequence];
2729 changeObj += movement * cost[iSequence];
2730 //numberFake_--;
2731 //setFakeBound(iSequence,noFake);
2732 }
2733 #endif
2734 }
2735 } else if (status == atUpperBound) {
2736 double movement = 0.0;
2737
2738 if (value > tolerance) {
2739 // to lower bound (if swap)
2740 // put back alpha
2741 which[numberInfeasibilities++] = iSequence;
2742 movement = lower[iSequence] - upper[iSequence];
2743 #ifdef TRY_SET_FAKE
2744 if (fabs(movement) > dualBound_) {
2745 FakeBound bound = getFakeBound(iSequence);
2746 if (bound == ClpSimplexDual::noFake) {
2747 setFakeBound(iSequence,
2748 ClpSimplexDual::lowerFake);
2749 lower[iSequence] = upper[iSequence] - dualBound_;
2750 assert(fabs(lower[iSequence]) < 1.0e30);
2751 movement = lower[iSequence] - upper[iSequence];
2752 numberFake_++;
2753 #ifndef NDEBUG
2754 } else {
2755 if (fabs(movement) >= 1.0e30)
2756 resetFakeBounds(-1000 - iSequence);
2757 #endif
2758 }
2759 }
2760 #endif
2761 changeObj += movement * cost[iSequence];
2762 matrix_->add(this, outputArray, iSequence, movement);
2763 #ifndef NO_SWAP7
2764 } else if (value > -tolerance) {
2765 // at correct bound but may swap
2766 FakeBound bound = getFakeBound(iSequence);
2767 if (bound == ClpSimplexDual::upperFake) {
2768 movement = lower[iSequence] - upper[iSequence];
2769 #ifndef NDEBUG
2770 if (fabs(movement) >= 1.0e30)
2771 resetFakeBounds(-1000 - iSequence);
2772 #endif
2773 setStatus(iSequence, atLowerBound);
2774 solution[iSequence] = lower[iSequence];
2775 changeObj += movement * cost[iSequence];
2776 //numberFake_--;
2777 //setFakeBound(iSequence,noFake);
2778 }
2779 #endif
2780 }
2781 }
2782 }
2783 }
2784
2785 #ifdef CLP_DEBUG
2786 if (fullRecompute && numberFake_ && (handler_->logLevel() & 16) != 0)
2787 printf("%d fake after full update\n", numberFake_);
2788 #endif
2789 // set number of infeasibilities
2790 columnArray->setNumElements(numberInfeasibilities);
2791 numberInfeasibilities += numberRowInfeasibilities;
2792 if (fullRecompute) {
2793 // do actual flips
2794 flipBounds(rowArray, columnArray);
2795 }
2796 objectiveChange += changeObj;
2797 return numberInfeasibilities;
2798 }
updateDualsInValuesPass(CoinIndexedVector * rowArray,CoinIndexedVector * columnArray,double theta)2799 void ClpSimplexDual::updateDualsInValuesPass(CoinIndexedVector *rowArray,
2800 CoinIndexedVector *columnArray,
2801 double theta)
2802 {
2803
2804 // use a tighter tolerance except for all being okay
2805 double tolerance = dualTolerance_;
2806
2807 // Coding is very similar but we can save a bit by splitting
2808 // Do rows
2809 {
2810 int i;
2811 double *reducedCost = djRegion(0);
2812 double *work;
2813 int number;
2814 int *which;
2815 work = rowArray->denseVector();
2816 number = rowArray->getNumElements();
2817 which = rowArray->getIndices();
2818 for (i = 0; i < number; i++) {
2819 int iSequence = which[i];
2820 double alphaI = work[i];
2821 double value = reducedCost[iSequence] - theta * alphaI;
2822 work[i] = 0.0;
2823 reducedCost[iSequence] = value;
2824
2825 Status status = getStatus(iSequence + numberColumns_);
2826 // more likely to be at upper bound ?
2827 if (status == atUpperBound) {
2828
2829 if (value > tolerance)
2830 reducedCost[iSequence] = 0.0;
2831 } else if (status == atLowerBound) {
2832
2833 if (value < -tolerance) {
2834 reducedCost[iSequence] = 0.0;
2835 }
2836 }
2837 }
2838 }
2839 rowArray->setNumElements(0);
2840
2841 // Do columns
2842 {
2843 int i;
2844 double *reducedCost = djRegion(1);
2845 double *work;
2846 int number;
2847 int *which;
2848 work = columnArray->denseVector();
2849 number = columnArray->getNumElements();
2850 which = columnArray->getIndices();
2851
2852 for (i = 0; i < number; i++) {
2853 int iSequence = which[i];
2854 double alphaI = work[i];
2855 double value = reducedCost[iSequence] - theta * alphaI;
2856 work[i] = 0.0;
2857 reducedCost[iSequence] = value;
2858
2859 Status status = getStatus(iSequence);
2860 if (status == atLowerBound) {
2861 if (value < -tolerance)
2862 reducedCost[iSequence] = 0.0;
2863 } else if (status == atUpperBound) {
2864 if (value > tolerance)
2865 reducedCost[iSequence] = 0.0;
2866 }
2867 }
2868 }
2869 columnArray->setNumElements(0);
2870 }
2871 /*
2872 Chooses dual pivot row
2873 Would be faster with separate region to scan
2874 and will have this (with square of infeasibility) when steepest
2875 For easy problems we can just choose one of the first rows we look at
2876 */
dualRow(int alreadyChosen)2877 void ClpSimplexDual::dualRow(int alreadyChosen)
2878 {
2879 // get pivot row using whichever method it is
2880 int chosenRow = -1;
2881 #ifdef FORCE_FOLLOW
2882 bool forceThis = false;
2883 if (!fpFollow && strlen(forceFile)) {
2884 fpFollow = fopen(forceFile, "r");
2885 assert(fpFollow);
2886 }
2887 if (fpFollow) {
2888 if (numberIterations_ <= force_iteration) {
2889 // read to next Clp0102
2890 char temp[300];
2891 while (fgets(temp, 250, fpFollow)) {
2892 if (strncmp(temp, "Clp0102", 7))
2893 continue;
2894 char cin, cout;
2895 sscanf(temp + 9, "%d%*f%*s%*c%c%d%*s%*c%c%d",
2896 &force_iteration, &cin, &force_in, &cout, &force_out);
2897 if (cin == 'R')
2898 force_in += numberColumns_;
2899 if (cout == 'R')
2900 force_out += numberColumns_;
2901 forceThis = true;
2902 assert(numberIterations_ == force_iteration - 1);
2903 printf("Iteration %d will force %d out and %d in\n",
2904 force_iteration, force_out, force_in);
2905 alreadyChosen = force_out;
2906 break;
2907 }
2908 } else {
2909 // use old
2910 forceThis = true;
2911 }
2912 if (!forceThis) {
2913 fclose(fpFollow);
2914 fpFollow = NULL;
2915 forceFile = "";
2916 }
2917 }
2918 #endif
2919 //double freeAlpha = 0.0;
2920 if (alreadyChosen < 0) {
2921 // first see if any free variables and put them in basis
2922 int nextFree = nextSuperBasic();
2923 //nextFree=-1; //off
2924 if (nextFree >= 0) {
2925 // unpack vector and find a good pivot
2926 unpack(rowArray_[1], nextFree);
2927 factorization_->updateColumn(rowArray_[2], rowArray_[1]);
2928
2929 double *work = rowArray_[1]->denseVector();
2930 int number = rowArray_[1]->getNumElements();
2931 int *which = rowArray_[1]->getIndices();
2932 double bestFeasibleAlpha = 0.0;
2933 int bestFeasibleRow = -1;
2934 double bestInfeasibleAlpha = 0.0;
2935 int bestInfeasibleRow = -1;
2936 int i;
2937
2938 for (i = 0; i < number; i++) {
2939 int iRow = which[i];
2940 double alpha = fabs(work[iRow]);
2941 if (alpha > 1.0e-3) {
2942 int iSequence = pivotVariable_[iRow];
2943 double value = solution_[iSequence];
2944 double lower = lower_[iSequence];
2945 double upper = upper_[iSequence];
2946 double infeasibility = 0.0;
2947 if (value > upper)
2948 infeasibility = value - upper;
2949 else if (value < lower)
2950 infeasibility = lower - value;
2951 if (infeasibility * alpha > bestInfeasibleAlpha && alpha > 1.0e-1) {
2952 if (!flagged(iSequence)) {
2953 bestInfeasibleAlpha = infeasibility * alpha;
2954 bestInfeasibleRow = iRow;
2955 }
2956 }
2957 if (alpha > bestFeasibleAlpha && (lower > -1.0e20 || upper < 1.0e20)) {
2958 bestFeasibleAlpha = alpha;
2959 bestFeasibleRow = iRow;
2960 }
2961 }
2962 }
2963 if (bestInfeasibleRow >= 0)
2964 chosenRow = bestInfeasibleRow;
2965 else if (bestFeasibleAlpha > 1.0e-2)
2966 chosenRow = bestFeasibleRow;
2967 if (chosenRow >= 0) {
2968 pivotRow_ = chosenRow;
2969 //freeAlpha = work[chosenRow];
2970 }
2971 rowArray_[1]->clear();
2972 }
2973 } else {
2974 // in values pass
2975 chosenRow = alreadyChosen;
2976 #ifdef FORCE_FOLLOW
2977 if (forceThis) {
2978 alreadyChosen = -1;
2979 chosenRow = -1;
2980 for (int i = 0; i < numberRows_; i++) {
2981 if (pivotVariable_[i] == force_out) {
2982 chosenRow = i;
2983 break;
2984 }
2985 }
2986 assert(chosenRow >= 0);
2987 }
2988 #endif
2989 pivotRow_ = chosenRow;
2990 }
2991 if (chosenRow < 0)
2992 pivotRow_ = dualRowPivot_->pivotRow();
2993
2994 if (pivotRow_ >= 0) {
2995 sequenceOut_ = pivotVariable_[pivotRow_];
2996 valueOut_ = solution_[sequenceOut_];
2997 lowerOut_ = lower_[sequenceOut_];
2998 upperOut_ = upper_[sequenceOut_];
2999 if (alreadyChosen < 0) {
3000 // if we have problems we could try other way and hope we get a
3001 // zero pivot?
3002 if (valueOut_ > upperOut_) {
3003 directionOut_ = -1;
3004 dualOut_ = valueOut_ - upperOut_;
3005 } else if (valueOut_ < lowerOut_) {
3006 directionOut_ = 1;
3007 dualOut_ = lowerOut_ - valueOut_;
3008 } else {
3009 #if 1
3010 // odd (could be free) - it's feasible - go to nearest
3011 if (valueOut_ - lowerOut_ < upperOut_ - valueOut_) {
3012 directionOut_ = 1;
3013 dualOut_ = lowerOut_ - valueOut_;
3014 } else {
3015 directionOut_ = -1;
3016 dualOut_ = valueOut_ - upperOut_;
3017 }
3018 #else
3019 // odd (could be free) - it's feasible - improve obj
3020 printf("direction from alpha of %g is %d\n",
3021 freeAlpha, freeAlpha > 0.0 ? 1 : -1);
3022 if (valueOut_ - lowerOut_ > 1.0e20)
3023 freeAlpha = 1.0;
3024 else if (upperOut_ - valueOut_ > 1.0e20)
3025 freeAlpha = -1.0;
3026 //if (valueOut_-lowerOut_<upperOut_-valueOut_) {
3027 if (freeAlpha < 0.0) {
3028 directionOut_ = 1;
3029 dualOut_ = lowerOut_ - valueOut_;
3030 } else {
3031 directionOut_ = -1;
3032 dualOut_ = valueOut_ - upperOut_;
3033 }
3034 printf("direction taken %d - bounds %g %g %g\n",
3035 directionOut_, lowerOut_, valueOut_, upperOut_);
3036 #endif
3037 }
3038 #ifdef CLP_DEBUG
3039 assert(dualOut_ >= 0.0);
3040 #endif
3041 } else {
3042 // in values pass so just use sign of dj
3043 // We don't want to go through any barriers so set dualOut low
3044 // free variables will never be here
3045 dualOut_ = 1.0e-6;
3046 if (dj_[sequenceOut_] > 0.0) {
3047 // this will give a -1 in pivot row (as slacks are -1.0)
3048 directionOut_ = 1;
3049 } else {
3050 directionOut_ = -1;
3051 }
3052 }
3053 }
3054 return;
3055 }
3056 // Checks if any fake bounds active - if so returns number and modifies
3057 // dualBound_ and everything.
3058 // Free variables will be left as free
3059 // Returns number of bounds changed if >=0
3060 // Returns -1 if not initialize and no effect
3061 // Fills in changeVector which can be used to see if unbounded
3062 // and cost of change vector
changeBounds(int initialize,CoinIndexedVector * outputArray,double & changeCost)3063 int ClpSimplexDual::changeBounds(int initialize,
3064 CoinIndexedVector *outputArray,
3065 double &changeCost)
3066 {
3067 numberFake_ = 0;
3068 if (!initialize) {
3069 int numberInfeasibilities;
3070 double newBound;
3071 newBound = 5.0 * dualBound_;
3072 numberInfeasibilities = 0;
3073 changeCost = 0.0;
3074 // put back original bounds and then check
3075 createRim1(false);
3076 int iSequence;
3077 // bounds will get bigger - just look at ones at bounds
3078 for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
3079 double lowerValue = lower_[iSequence];
3080 double upperValue = upper_[iSequence];
3081 double value = solution_[iSequence];
3082 setFakeBound(iSequence, ClpSimplexDual::noFake);
3083 switch (getStatus(iSequence)) {
3084
3085 case basic:
3086 case ClpSimplex::isFixed:
3087 break;
3088 case isFree:
3089 case superBasic:
3090 break;
3091 case atUpperBound:
3092 if (fabs(value - upperValue) > primalTolerance_) {
3093 if (fabs(dj_[iSequence]) > 1.0e-9) {
3094 numberInfeasibilities++;
3095 } else {
3096 setStatus(iSequence, superBasic);
3097 moreSpecialOptions_ &= ~8;
3098 }
3099 }
3100 break;
3101 case atLowerBound:
3102 if (fabs(value - lowerValue) > primalTolerance_) {
3103 if (fabs(dj_[iSequence]) > 1.0e-9) {
3104 numberInfeasibilities++;
3105 } else {
3106 setStatus(iSequence, superBasic);
3107 moreSpecialOptions_ &= ~8;
3108 }
3109 }
3110 break;
3111 }
3112 }
3113 // If dual infeasible then carry on
3114 if (numberInfeasibilities) {
3115 handler_->message(CLP_DUAL_CHECKB, messages_)
3116 << newBound
3117 << CoinMessageEol;
3118 int iSequence;
3119 for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
3120 double lowerValue = lower_[iSequence];
3121 double upperValue = upper_[iSequence];
3122 double newLowerValue;
3123 double newUpperValue;
3124 Status status = getStatus(iSequence);
3125 if (status == atUpperBound || status == atLowerBound) {
3126 double value = solution_[iSequence];
3127 if (value - lowerValue <= upperValue - value) {
3128 newLowerValue = CoinMax(lowerValue, value - 0.666667 * newBound);
3129 newUpperValue = CoinMin(upperValue, newLowerValue + newBound);
3130 } else {
3131 newUpperValue = CoinMin(upperValue, value + 0.666667 * newBound);
3132 newLowerValue = CoinMax(lowerValue, newUpperValue - newBound);
3133 }
3134 if (newLowerValue > lowerValue) {
3135 if (newUpperValue < upperValue) {
3136 setFakeBound(iSequence, ClpSimplexDual::bothFake);
3137 // redo
3138 if (status == atLowerBound) {
3139 newLowerValue = value;
3140 newUpperValue = CoinMin(upperValue, newLowerValue + newBound);
3141 } else {
3142 newUpperValue = value;
3143 newLowerValue = CoinMax(lowerValue, newUpperValue - newBound);
3144 }
3145 numberFake_++;
3146 } else {
3147 setFakeBound(iSequence, ClpSimplexDual::lowerFake);
3148 numberFake_++;
3149 }
3150 } else {
3151 if (newUpperValue < upperValue) {
3152 setFakeBound(iSequence, ClpSimplexDual::upperFake);
3153 numberFake_++;
3154 }
3155 }
3156 lower_[iSequence] = newLowerValue;
3157 upper_[iSequence] = newUpperValue;
3158 if (status == atUpperBound)
3159 solution_[iSequence] = newUpperValue;
3160 else
3161 solution_[iSequence] = newLowerValue;
3162 double movement = solution_[iSequence] - value;
3163 if (movement && outputArray) {
3164 if (iSequence >= numberColumns_) {
3165 outputArray->quickAdd(iSequence, -movement);
3166 changeCost += movement * cost_[iSequence];
3167 } else {
3168 matrix_->add(this, outputArray, iSequence, movement);
3169 changeCost += movement * cost_[iSequence];
3170 }
3171 }
3172 }
3173 }
3174 dualBound_ = newBound;
3175 } else {
3176 numberInfeasibilities = -1;
3177 }
3178 return numberInfeasibilities;
3179 } else if (initialize == 1 || initialize == 3) {
3180 int iSequence;
3181 if (initialize == 3) {
3182 if (columnScale_) {
3183 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
3184 if (getFakeBound(iSequence) != ClpSimplexDual::noFake) {
3185 double multiplier = rhsScale_ * inverseColumnScale_[iSequence];
3186 // lower
3187 double value = columnLower_[iSequence];
3188 if (value > -1.0e30) {
3189 value *= multiplier;
3190 }
3191 lower_[iSequence] = value;
3192 // upper
3193 value = columnUpper_[iSequence];
3194 if (value < 1.0e30) {
3195 value *= multiplier;
3196 }
3197 upper_[iSequence] = value;
3198 setFakeBound(iSequence, ClpSimplexDual::noFake);
3199 }
3200 }
3201 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
3202 // lower
3203 double multiplier = rhsScale_ * rowScale_[iSequence];
3204 double value = rowLower_[iSequence];
3205 if (value > -1.0e30) {
3206 value *= multiplier;
3207 }
3208 lower_[iSequence + numberColumns_] = value;
3209 // upper
3210 value = rowUpper_[iSequence];
3211 if (value < 1.0e30) {
3212 value *= multiplier;
3213 }
3214 upper_[iSequence + numberColumns_] = value;
3215 setFakeBound(iSequence + numberColumns_, ClpSimplexDual::noFake);
3216 }
3217 } else {
3218 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
3219 if (getFakeBound(iSequence) != ClpSimplexDual::noFake) {
3220 lower_[iSequence] = columnLower_[iSequence];
3221 upper_[iSequence] = columnUpper_[iSequence];
3222 setFakeBound(iSequence, ClpSimplexDual::noFake);
3223 }
3224 }
3225 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
3226 if (getFakeBound(iSequence + numberColumns_) != ClpSimplexDual::noFake) {
3227 lower_[iSequence + numberColumns_] = rowLower_[iSequence];
3228 upper_[iSequence + numberColumns_] = rowUpper_[iSequence];
3229 setFakeBound(iSequence + numberColumns_, ClpSimplexDual::noFake);
3230 }
3231 }
3232 }
3233 }
3234 double testBound = 0.999999 * dualBound_;
3235 for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
3236 Status status = getStatus(iSequence);
3237 if (status == atUpperBound || status == atLowerBound) {
3238 double lowerValue = lower_[iSequence];
3239 double upperValue = upper_[iSequence];
3240 double value = solution_[iSequence];
3241 if (lowerValue > -largeValue_ || upperValue < largeValue_) {
3242 if (true || lowerValue - value > -0.5 * dualBound_ || upperValue - value < 0.5 * dualBound_) {
3243 if (fabs(lowerValue - value) <= fabs(upperValue - value)) {
3244 if (upperValue > lowerValue + testBound) {
3245 if (getFakeBound(iSequence) == ClpSimplexDual::noFake)
3246 numberFake_++;
3247 upper_[iSequence] = lowerValue + dualBound_;
3248 setFakeBound(iSequence, ClpSimplexDual::upperFake);
3249 }
3250 } else {
3251 if (lowerValue < upperValue - testBound) {
3252 if (getFakeBound(iSequence) == ClpSimplexDual::noFake)
3253 numberFake_++;
3254 lower_[iSequence] = upperValue - dualBound_;
3255 setFakeBound(iSequence, ClpSimplexDual::lowerFake);
3256 }
3257 }
3258 } else {
3259 if (getFakeBound(iSequence) == ClpSimplexDual::noFake)
3260 numberFake_++;
3261 lower_[iSequence] = -0.5 * dualBound_;
3262 upper_[iSequence] = 0.5 * dualBound_;
3263 setFakeBound(iSequence, ClpSimplexDual::bothFake);
3264 abort();
3265 }
3266 if (status == atUpperBound)
3267 solution_[iSequence] = upper_[iSequence];
3268 else
3269 solution_[iSequence] = lower_[iSequence];
3270 } else {
3271 // set non basic free variables to fake bounds
3272 // I don't think we should ever get here
3273 // yes we can if basis goes singular twice in succession!
3274 //CoinAssert(!("should not be here"));
3275 lower_[iSequence] = -0.5 * dualBound_;
3276 upper_[iSequence] = 0.5 * dualBound_;
3277 setFakeBound(iSequence, ClpSimplexDual::bothFake);
3278 numberFake_++;
3279 setStatus(iSequence, atUpperBound);
3280 solution_[iSequence] = 0.5 * dualBound_;
3281 }
3282 } else if (status == basic) {
3283 // make sure not at fake bound and bounds correct
3284 setFakeBound(iSequence, ClpSimplexDual::noFake);
3285 double gap = upper_[iSequence] - lower_[iSequence];
3286 if (gap > 0.5 * dualBound_ && gap < 2.0 * dualBound_) {
3287 if (iSequence < numberColumns_) {
3288 if (columnScale_) {
3289 double multiplier = rhsScale_ * inverseColumnScale_[iSequence];
3290 // lower
3291 double value = columnLower_[iSequence];
3292 if (value > -1.0e30) {
3293 value *= multiplier;
3294 }
3295 lower_[iSequence] = value;
3296 // upper
3297 value = columnUpper_[iSequence];
3298 if (value < 1.0e30) {
3299 value *= multiplier;
3300 }
3301 upper_[iSequence] = value;
3302 } else {
3303 lower_[iSequence] = columnLower_[iSequence];
3304 ;
3305 upper_[iSequence] = columnUpper_[iSequence];
3306 ;
3307 }
3308 } else {
3309 int iRow = iSequence - numberColumns_;
3310 if (rowScale_) {
3311 // lower
3312 double multiplier = rhsScale_ * rowScale_[iRow];
3313 double value = rowLower_[iRow];
3314 if (value > -1.0e30) {
3315 value *= multiplier;
3316 }
3317 lower_[iSequence] = value;
3318 // upper
3319 value = rowUpper_[iRow];
3320 if (value < 1.0e30) {
3321 value *= multiplier;
3322 }
3323 upper_[iSequence] = value;
3324 } else {
3325 lower_[iSequence] = rowLower_[iRow];
3326 ;
3327 upper_[iSequence] = rowUpper_[iRow];
3328 ;
3329 }
3330 }
3331 }
3332 }
3333 }
3334
3335 return 1;
3336 } else {
3337 // just reset changed ones
3338 if (columnScale_) {
3339 int iSequence;
3340 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
3341 FakeBound fakeStatus = getFakeBound(iSequence);
3342 if (fakeStatus != noFake) {
3343 if ((static_cast< int >(fakeStatus) & 1) != 0) {
3344 // lower
3345 double value = columnLower_[iSequence];
3346 if (value > -1.0e30) {
3347 double multiplier = rhsScale_ * inverseColumnScale_[iSequence];
3348 value *= multiplier;
3349 }
3350 columnLowerWork_[iSequence] = value;
3351 }
3352 if ((static_cast< int >(fakeStatus) & 2) != 0) {
3353 // upper
3354 double value = columnUpper_[iSequence];
3355 if (value < 1.0e30) {
3356 double multiplier = rhsScale_ * inverseColumnScale_[iSequence];
3357 value *= multiplier;
3358 }
3359 columnUpperWork_[iSequence] = value;
3360 }
3361 }
3362 }
3363 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
3364 FakeBound fakeStatus = getFakeBound(iSequence + numberColumns_);
3365 if (fakeStatus != noFake) {
3366 if ((static_cast< int >(fakeStatus) & 1) != 0) {
3367 // lower
3368 double value = rowLower_[iSequence];
3369 if (value > -1.0e30) {
3370 double multiplier = rhsScale_ * rowScale_[iSequence];
3371 value *= multiplier;
3372 }
3373 rowLowerWork_[iSequence] = value;
3374 }
3375 if ((static_cast< int >(fakeStatus) & 2) != 0) {
3376 // upper
3377 double value = rowUpper_[iSequence];
3378 if (value < 1.0e30) {
3379 double multiplier = rhsScale_ * rowScale_[iSequence];
3380 value *= multiplier;
3381 }
3382 rowUpperWork_[iSequence] = value;
3383 }
3384 }
3385 }
3386 } else {
3387 int iSequence;
3388 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
3389 FakeBound fakeStatus = getFakeBound(iSequence);
3390 if ((static_cast< int >(fakeStatus) & 1) != 0) {
3391 // lower
3392 columnLowerWork_[iSequence] = columnLower_[iSequence];
3393 }
3394 if ((static_cast< int >(fakeStatus) & 2) != 0) {
3395 // upper
3396 columnUpperWork_[iSequence] = columnUpper_[iSequence];
3397 }
3398 }
3399 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
3400 FakeBound fakeStatus = getFakeBound(iSequence + numberColumns_);
3401 if ((static_cast< int >(fakeStatus) & 1) != 0) {
3402 // lower
3403 rowLowerWork_[iSequence] = rowLower_[iSequence];
3404 }
3405 if ((static_cast< int >(fakeStatus) & 2) != 0) {
3406 // upper
3407 rowUpperWork_[iSequence] = rowUpper_[iSequence];
3408 }
3409 }
3410 }
3411 return 0;
3412 }
3413 }
3414 // Just checks if any fake bounds active - if so returns number
checkFakeBounds() const3415 int ClpSimplexDual::checkFakeBounds() const
3416 {
3417 int numberActive = 0;
3418 for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
3419 switch (getStatus(iSequence)) {
3420
3421 case basic:
3422 case ClpSimplex::isFixed:
3423 break;
3424 case isFree:
3425 case superBasic:
3426 break;
3427 case atUpperBound:
3428 if ((getFakeBound(iSequence) & 2) != 0)
3429 numberActive++;
3430 break;
3431 case atLowerBound:
3432 if ((getFakeBound(iSequence) & 1) != 0)
3433 numberActive++;
3434 break;
3435 }
3436 }
3437 return numberActive;
3438 }
3439 #if ABOCA_LITE
3440 /* Meat of transposeTimes by column when not scaled and skipping
3441 and doing part of dualColumn */
3442 static void
dualColumn00(clpTempInfo & info)3443 dualColumn00(clpTempInfo &info)
3444 {
3445 const int *COIN_RESTRICT which = info.which;
3446 const double *COIN_RESTRICT work = info.work;
3447 int *COIN_RESTRICT index = info.index;
3448 double *COIN_RESTRICT spare = info.spare;
3449 const unsigned char *COIN_RESTRICT status = info.status;
3450 const double *COIN_RESTRICT reducedCost = info.reducedCost;
3451 double upperTheta = info.upperTheta;
3452 double acceptablePivot = info.acceptablePivot;
3453 double dualTolerance = info.tolerance;
3454 int numberToDo = info.numberToDo;
3455 double tentativeTheta = 1.0e15;
3456 int numberRemaining = 0;
3457 double multiplier[] = { -1.0, 1.0 };
3458 double dualT = -dualTolerance;
3459 for (int i = 0; i < numberToDo; i++) {
3460 int iSequence = which[i];
3461 int wanted = (status[iSequence] & 3) - 1;
3462 if (wanted) {
3463 double mult = multiplier[wanted - 1];
3464 double alpha = work[i] * mult;
3465 if (alpha > 0.0) {
3466 double oldValue = reducedCost[iSequence] * mult;
3467 double value = oldValue - tentativeTheta * alpha;
3468 if (value < dualT) {
3469 value = oldValue - upperTheta * alpha;
3470 if (value < dualT && alpha >= acceptablePivot) {
3471 upperTheta = (oldValue - dualT) / alpha;
3472 }
3473 // add to list
3474 spare[numberRemaining] = alpha * mult;
3475 index[numberRemaining++] = iSequence;
3476 }
3477 }
3478 }
3479 }
3480 info.numberRemaining = numberRemaining;
3481 info.upperTheta = upperTheta;
3482 }
3483 static void
dualColumn000(int numberThreads,clpTempInfo * info)3484 dualColumn000(int numberThreads, clpTempInfo *info)
3485 {
3486 for (int i = 0; i < numberThreads; i++) {
3487 cilk_spawn dualColumn00(info[i]);
3488 }
3489 cilk_sync;
3490 }
moveAndZero(clpTempInfo * info,int type,void * extra)3491 void moveAndZero(clpTempInfo *info, int type, void *extra)
3492 {
3493 int numberThreads = abcState();
3494 switch (type) {
3495 case 1: {
3496 int numberRemaining = info[0].numberRemaining;
3497 int *COIN_RESTRICT index = info[0].index + numberRemaining;
3498 double *COIN_RESTRICT spare = info[0].spare + numberRemaining;
3499 for (int i = 1; i < numberThreads; i++) {
3500 int number = info[i].numberRemaining;
3501 memmove(index, info[i].index, number * sizeof(int));
3502 index += number;
3503 double *COIN_RESTRICT from = info[i].spare;
3504 assert(from >= spare);
3505 memmove(spare, from, number * sizeof(double));
3506 spare += number;
3507 }
3508 // now zero out
3509 int i;
3510 for (i = 1; i < numberThreads; i++) {
3511 double *spareBit = info[i].spare + info[i].numberRemaining;
3512 if (spareBit > spare) {
3513 memset(spare, 0, (spareBit - spare) * sizeof(double));
3514 break;
3515 }
3516 }
3517 i++; // just zero
3518 for (; i < numberThreads; i++) {
3519 int number = info[i].numberRemaining;
3520 memset(info[i].spare, 0, number * sizeof(double));
3521 }
3522 } break;
3523 case 2: {
3524 int numberAdded = info[0].numberAdded;
3525 int *COIN_RESTRICT index = info[0].which + numberAdded;
3526 double *COIN_RESTRICT spare = info[0].infeas + numberAdded;
3527 for (int i = 1; i < numberThreads; i++) {
3528 int number = info[i].numberAdded;
3529 memmove(index, info[i].which, number * sizeof(int));
3530 index += number;
3531 double *COIN_RESTRICT from = info[i].infeas;
3532 assert(from >= spare);
3533 memmove(spare, from, number * sizeof(double));
3534 spare += number;
3535 }
3536 // now zero out
3537 int i;
3538 for (i = 1; i < numberThreads; i++) {
3539 double *spareBit = info[i].infeas + info[i].numberAdded;
3540 if (spareBit > spare) {
3541 memset(spare, 0, (spareBit - spare) * sizeof(double));
3542 break;
3543 }
3544 }
3545 i++; // just zero
3546 for (; i < numberThreads; i++) {
3547 int number = info[i].numberAdded;
3548 memset(info[i].infeas, 0, number * sizeof(double));
3549 }
3550 } break;
3551 default:
3552 abort();
3553 break;
3554 }
3555 }
3556 #endif
3557 #ifdef _MSC_VER
3558 #include <intrin.h>
3559 #elif defined(__arm__)
3560 #include <arm_neon.h>
3561 #else
3562 //#include <immintrin.h>
3563 //#include <fmaintrin.h>
3564 #endif
dualColumn0(const CoinIndexedVector * rowArray,const CoinIndexedVector * columnArray,CoinIndexedVector * spareArray,double acceptablePivot,double & upperReturn,double & badFree)3565 int ClpSimplexDual::dualColumn0(const CoinIndexedVector *rowArray,
3566 const CoinIndexedVector *columnArray,
3567 CoinIndexedVector *spareArray,
3568 double acceptablePivot,
3569 double &upperReturn, double &badFree)
3570 {
3571 // do first pass to get possibles
3572 double *spare = spareArray->denseVector();
3573 int *index = spareArray->getIndices();
3574 const double *work;
3575 int number;
3576 const int *which;
3577 const double *reducedCost;
3578 // We can also see if infeasible or pivoting on free
3579 double tentativeTheta = 1.0e15;
3580 double upperTheta = 1.0e31;
3581 double freePivot = acceptablePivot;
3582 int numberRemaining = 0;
3583 int i;
3584 badFree = 0.0;
3585 if ((moreSpecialOptions_ & 8) != 0) {
3586 // No free or super basic
3587 // bestPossible will re recomputed if necessary
3588 #ifndef COIN_AVX2
3589 double multiplier[] = { -1.0, 1.0 };
3590 #else
3591 double multiplier[4] = { 0.0, 0.0, -1.0, 1.0 };
3592 #endif
3593 double dualT = -dualTolerance_;
3594 #if ABOCA_LITE == 0
3595 int nSections = 2;
3596 #else
3597 int numberThreads = abcState();
3598 int nSections = numberThreads ? 1 : 2;
3599 #endif
3600 for (int iSection = 0; iSection < nSections; iSection++) {
3601
3602 int addSequence;
3603 unsigned char *statusArray;
3604 if (!iSection) {
3605 work = rowArray->denseVector();
3606 number = rowArray->getNumElements();
3607 which = rowArray->getIndices();
3608 reducedCost = rowReducedCost_;
3609 addSequence = numberColumns_;
3610 statusArray = status_ + numberColumns_;
3611 } else {
3612 work = columnArray->denseVector();
3613 number = columnArray->getNumElements();
3614 which = columnArray->getIndices();
3615 reducedCost = reducedCostWork_;
3616 addSequence = 0;
3617 statusArray = status_;
3618 }
3619 #ifndef COIN_AVX2
3620 for (i = 0; i < number; i++) {
3621 int iSequence = which[i];
3622 double alpha;
3623 double oldValue;
3624 double value;
3625
3626 assert(getStatus(iSequence + addSequence) != isFree
3627 && getStatus(iSequence + addSequence) != superBasic);
3628 int iStatus = (statusArray[iSequence] & 3) - 1;
3629 if (iStatus) {
3630 double mult = multiplier[iStatus - 1];
3631 alpha = work[i] * mult;
3632 if (alpha > 0.0) {
3633 oldValue = reducedCost[iSequence] * mult;
3634 value = oldValue - tentativeTheta * alpha;
3635 if (value < dualT) {
3636 value = oldValue - upperTheta * alpha;
3637 if (value < dualT && alpha >= acceptablePivot) {
3638 upperTheta = (oldValue - dualT) / alpha;
3639 //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta);
3640 }
3641 // add to list
3642 spare[numberRemaining] = alpha * mult;
3643 index[numberRemaining++] = iSequence + addSequence;
3644 }
3645 }
3646 }
3647 }
3648 //
3649 #else
3650 //#define COIN_AVX2 4 // temp
3651 #if COIN_AVX2 == 1
3652 #define COIN_AVX2_SHIFT 0
3653 #elif COIN_AVX2 == 2
3654 #define COIN_AVX2_SHIFT 1
3655 #elif COIN_AVX2 == 4
3656 #define COIN_AVX2_SHIFT 2
3657 #elif COIN_AVX2 == 8
3658 #define COIN_AVX2_SHIFT 3
3659 #else
3660 error;
3661 #endif
3662 //#define COIN_ALIGN 8*COIN_AVX2 // later
3663 //#define COIN_ALIGN_DOUBLE COIN_AVX2
3664 #define CHECK_CHUNK 4
3665 // round up
3666 int *whichX = const_cast< int * >(which);
3667 double *workX = const_cast< double * >(work);
3668 int nBlocks = (number + CHECK_CHUNK - 1) / CHECK_CHUNK;
3669 int n = nBlocks * CHECK_CHUNK + 1;
3670 for (int i = number; i < n; i++) {
3671 workX[i] = 0.0;
3672 whichX[i] = 0; // alpha will be zero so not chosen
3673 }
3674 bool acceptableX[CHECK_CHUNK + 1];
3675 double oldValueX[CHECK_CHUNK + 1];
3676 double newValueX[CHECK_CHUNK + 1];
3677 double alphaX[CHECK_CHUNK + 1];
3678 newValueX[CHECK_CHUNK] = 0.0;
3679 #define USE_USE_AVX
3680 //#define CHECK_H 1
3681 #ifdef USE_USE_AVX
3682 #define NEED_AVX
3683 #elif CHECK_H
3684 #define NEED_AVX
3685 #endif
3686 #ifdef NEED_AVX
3687 double mult2[CHECK_CHUNK] __attribute__((aligned(64)));
3688 CoinInt64 acceptableY[CHECK_CHUNK] __attribute__((aligned(64)));
3689 CoinInt64 goodDj[CHECK_CHUNK + 1] __attribute__((aligned(64)));
3690 double oldValueY[CHECK_CHUNK] __attribute__((aligned(64)));
3691 double alphaY[CHECK_CHUNK + 1] __attribute__((aligned(64)));
3692 memset(acceptableY, 0, sizeof(acceptableY));
3693 memset(goodDj, 0, sizeof(goodDj));
3694 memset(oldValueY, 0, sizeof(oldValueY));
3695 memset(alphaY, 0, sizeof(alphaY));
3696 __m256d tentative2 = _mm256_set1_pd(-tentativeTheta);
3697 __m256d dualT2 = _mm256_set1_pd(dualT);
3698 __m256d acceptable2 = _mm256_set1_pd(acceptablePivot);
3699 #endif
3700 for (int iBlock = 0; iBlock < nBlocks; iBlock++) {
3701 bool store = false;
3702 double alpha = 0.0;
3703 double oldValue = 0.0;
3704 double newValue = 0.0;
3705 double trueAlpha = 0.0;
3706 int jSequence = 0;
3707 #ifndef USE_USE_AVX
3708 for (int i = 0; i < CHECK_CHUNK + 1; i++) {
3709 int iSequence = which[i];
3710 int iStatus = (statusArray[iSequence] & 3);
3711 double mult = multiplier[iStatus];
3712 double newAlpha = work[i] * mult;
3713 double oldDj = reducedCost[iSequence] * mult;
3714 newValue = (oldDj - tentativeTheta * newAlpha) - dualT;
3715 acceptableX[i] = newAlpha >= acceptablePivot;
3716 oldValueX[i] = oldDj;
3717 newValueX[i] = newValue;
3718 alphaX[i] = newAlpha;
3719 }
3720 #endif
3721 #ifdef NEED_AVX
3722 __m128i columns = _mm_load_si128((const __m128i *)which);
3723 // what do we get - this must be wrong
3724 // probably only 1 and 2 - can we be clever
3725 // fix
3726 //__m128i status; // = _mm256_i32gather_ps(statusArray,columns,1);
3727 //status.m128i_i32[0]=statusArray[columns.m128i_i32[0]];
3728 for (int i = 0; i < CHECK_CHUNK; i++) {
3729 int iSequence = which[i];
3730 int iStatus = (statusArray[iSequence] & 3);
3731 mult2[i] = multiplier[iStatus];
3732 }
3733 //__m256d newAlpha2 = _mm256_i32gather_pd(multiplier,status,1); // mult here
3734 __m256d newAlpha2 = _mm256_load_pd(mult2);
3735 __m256d oldDj = _mm256_i32gather_pd(reducedCost, columns, 8);
3736 oldDj = _mm256_mul_pd(oldDj, newAlpha2); // remember newAlpha==mult
3737 _mm256_store_pd(oldValueY, oldDj); // redo later
3738 __m256d work2 = _mm256_load_pd(work);
3739 newAlpha2 = _mm256_mul_pd(newAlpha2, work2); // now really newAlpha
3740 //__m256d newValue2 = _mm256_fmadd_pd(tentative2,newAlpha2,oldDj);
3741 oldDj = _mm256_fmadd_pd(newAlpha2, tentative2, oldDj);
3742 __v4df bitsDj = _mm256_cmp_pd(oldDj, dualT2, _CMP_LT_OS);
3743 __v4df bitsAcceptable = _mm256_cmp_pd(newAlpha2, acceptable2, _CMP_GE_OS);
3744 _mm256_store_pd(reinterpret_cast< double * >(goodDj), bitsDj);
3745 _mm256_store_pd(reinterpret_cast< double * >(acceptableY), bitsAcceptable);
3746 _mm256_store_pd(alphaY, newAlpha2);
3747 #ifndef USE_USE_AVX
3748 #undef NDEBUG
3749 for (int i = 0; i < CHECK_CHUNK; i++) {
3750 assert(newValueX[i] > 0.0 == (goodDj[i]));
3751 //assert(acceptableX[i]==(acceptableY[i]));
3752 assert(oldValueX[i] == oldValueY[i]);
3753 assert(alphaX[i] == alphaY[i]);
3754 }
3755 for (int i = 0; i < CHECK_CHUNK; i++) {
3756 bool g1 = newValueX[i] < 0.0;
3757 bool g2 = goodDj[i] != 0;
3758 if (g1 != g2)
3759 abort();
3760 //if(acceptableX[i]!=(acceptableY[i]))abort();
3761 if (fabs(oldValueX[i] - oldValueY[i]) > 1.0e-5 + +(1.0e-10 * fabs(oldValueX[i])))
3762 abort();
3763 if (alphaX[i] != alphaY[i])
3764 abort();
3765 }
3766 #endif
3767 #endif
3768 for (int i = 0; i < CHECK_CHUNK + 1; i++) {
3769 #ifndef USE_USE_AVX
3770 double newValue = newValueX[i];
3771 bool newStore = newValue < 0.0;
3772 if (store) {
3773 // add to list
3774 bool acceptable = acceptableX[i - 1];
3775 spare[numberRemaining] = work[i - 1];
3776 index[numberRemaining++] = which[i - 1] + addSequence;
3777 double value = oldValueX[i - 1] - upperTheta * alphaX[i - 1];
3778 if (value < dualT && acceptable) {
3779 upperTheta = (oldValueX[i - 1] - dualT) / alphaX[i - 1];
3780 }
3781 }
3782 #else
3783 bool newStore = goodDj[i] != 0;
3784 if (store) {
3785 // add to list
3786 bool acceptable = acceptableY[i - 1];
3787 spare[numberRemaining] = work[i - 1];
3788 index[numberRemaining++] = which[i - 1] + addSequence;
3789 double value = oldValueY[i - 1] - upperTheta * alphaY[i - 1];
3790 if (value < dualT && acceptable) {
3791 upperTheta = (oldValueY[i - 1] - dualT) / alphaY[i - 1];
3792 }
3793 }
3794 #endif
3795 store = newStore;
3796 }
3797 which += CHECK_CHUNK;
3798 work += CHECK_CHUNK;
3799 }
3800 #endif
3801 }
3802 #if ABOCA_LITE
3803 if (numberThreads) {
3804 work = columnArray->denseVector();
3805 number = columnArray->getNumElements();
3806 which = columnArray->getIndices();
3807 reducedCost = reducedCostWork_;
3808 unsigned char *statusArray = status_;
3809
3810 clpTempInfo info[ABOCA_LITE];
3811 int chunk = (number + numberThreads - 1) / numberThreads;
3812 int n = 0;
3813 int nR = numberRemaining;
3814 for (int i = 0; i < numberThreads; i++) {
3815 info[i].which = const_cast< int * >(which + n);
3816 info[i].work = const_cast< double * >(work + n);
3817 info[i].numberToDo = CoinMin(chunk, number - n);
3818 n += chunk;
3819 info[i].index = index + nR;
3820 info[i].spare = spare + nR;
3821 nR += chunk;
3822 info[i].reducedCost = const_cast< double * >(reducedCost);
3823 info[i].upperTheta = upperTheta;
3824 info[i].acceptablePivot = acceptablePivot;
3825 info[i].status = statusArray;
3826 info[i].tolerance = dualTolerance_;
3827 }
3828 // for gcc - get cilk out of function to stop avx2 error
3829 dualColumn000(numberThreads, info);
3830 moveAndZero(info, 1, NULL);
3831 for (int i = 0; i < numberThreads; i++) {
3832 numberRemaining += info[i].numberRemaining;
3833 upperTheta = CoinMin(upperTheta, static_cast< double >(info[i].upperTheta));
3834 }
3835 }
3836 #endif
3837 } else {
3838 // some free or super basic
3839 for (int iSection = 0; iSection < 2; iSection++) {
3840
3841 int addSequence;
3842
3843 if (!iSection) {
3844 work = rowArray->denseVector();
3845 number = rowArray->getNumElements();
3846 which = rowArray->getIndices();
3847 reducedCost = rowReducedCost_;
3848 addSequence = numberColumns_;
3849 } else {
3850 work = columnArray->denseVector();
3851 number = columnArray->getNumElements();
3852 which = columnArray->getIndices();
3853 reducedCost = reducedCostWork_;
3854 addSequence = 0;
3855 }
3856
3857 for (i = 0; i < number; i++) {
3858 int iSequence = which[i];
3859 double alpha;
3860 double oldValue;
3861 double value;
3862 bool keep;
3863
3864 switch (getStatus(iSequence + addSequence)) {
3865
3866 case basic:
3867 case ClpSimplex::isFixed:
3868 break;
3869 case isFree:
3870 case superBasic:
3871 alpha = work[i];
3872 oldValue = reducedCost[iSequence];
3873 // If free has to be very large - should come in via dualRow
3874 //if (getStatus(iSequence+addSequence)==isFree&&fabs(alpha)<1.0e-3)
3875 //break;
3876 if (oldValue > dualTolerance_) {
3877 keep = true;
3878 } else if (oldValue < -dualTolerance_) {
3879 keep = true;
3880 } else {
3881 if (fabs(alpha) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) {
3882 keep = true;
3883 } else {
3884 keep = false;
3885 badFree = CoinMax(badFree, fabs(alpha));
3886 }
3887 }
3888 if (keep) {
3889 // free - choose largest
3890 if (fabs(alpha) > freePivot) {
3891 freePivot = fabs(alpha);
3892 sequenceIn_ = iSequence + addSequence;
3893 theta_ = oldValue / alpha;
3894 alpha_ = alpha;
3895 }
3896 // give fake bounds if possible
3897 int jSequence = iSequence + addSequence;
3898 if (2.0 * fabs(solution_[jSequence]) < dualBound_) {
3899 FakeBound bound = getFakeBound(jSequence);
3900 assert(bound == ClpSimplexDual::noFake);
3901 setFakeBound(jSequence, ClpSimplexDual::bothFake);
3902 numberFake_++;
3903 value = oldValue - tentativeTheta * alpha;
3904 if (value > dualTolerance_) {
3905 // pretend coming in from upper bound
3906 upper_[jSequence] = solution_[jSequence];
3907 lower_[jSequence] = upper_[jSequence] - dualBound_;
3908 setColumnStatus(jSequence, ClpSimplex::atUpperBound);
3909 } else {
3910 // pretend coming in from lower bound
3911 lower_[jSequence] = solution_[jSequence];
3912 upper_[jSequence] = lower_[jSequence] + dualBound_;
3913 setColumnStatus(jSequence, ClpSimplex::atLowerBound);
3914 }
3915 }
3916 }
3917 break;
3918 case atUpperBound:
3919 alpha = work[i];
3920 oldValue = reducedCost[iSequence];
3921 value = oldValue - tentativeTheta * alpha;
3922 //assert (oldValue<=dualTolerance_*1.0001);
3923 if (value > dualTolerance_) {
3924 value = oldValue - upperTheta * alpha;
3925 if (value > dualTolerance_ && -alpha >= acceptablePivot) {
3926 upperTheta = (oldValue - dualTolerance_) / alpha;
3927 //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta);
3928 }
3929 // add to list
3930 spare[numberRemaining] = alpha;
3931 index[numberRemaining++] = iSequence + addSequence;
3932 }
3933 break;
3934 case atLowerBound:
3935 alpha = work[i];
3936 oldValue = reducedCost[iSequence];
3937 value = oldValue - tentativeTheta * alpha;
3938 //assert (oldValue>=-dualTolerance_*1.0001);
3939 if (value < -dualTolerance_) {
3940 value = oldValue - upperTheta * alpha;
3941 if (value < -dualTolerance_ && alpha >= acceptablePivot) {
3942 upperTheta = (oldValue + dualTolerance_) / alpha;
3943 //tentativeTheta = CoinMin(2.0*upperTheta,tentativeTheta);
3944 }
3945 // add to list
3946 spare[numberRemaining] = alpha;
3947 index[numberRemaining++] = iSequence + addSequence;
3948 }
3949 break;
3950 }
3951 }
3952 }
3953 }
3954 upperReturn = upperTheta;
3955 return numberRemaining;
3956 }
3957 /*
3958 Row array has row part of pivot row (as duals so sign may be switched)
3959 Column array has column part.
3960 This chooses pivot column.
3961 Spare array will be needed when we start getting clever.
3962 We will check for basic so spare array will never overflow.
3963 If necessary will modify costs
3964 */
3965 double
dualColumn(CoinIndexedVector * rowArray,CoinIndexedVector * columnArray,CoinIndexedVector * spareArray,CoinIndexedVector * spareArray2,double acceptablePivot,CoinBigIndex *)3966 ClpSimplexDual::dualColumn(CoinIndexedVector *rowArray,
3967 CoinIndexedVector *columnArray,
3968 CoinIndexedVector *spareArray,
3969 CoinIndexedVector *spareArray2,
3970 double acceptablePivot,
3971 CoinBigIndex * /*dubiousWeights*/)
3972 {
3973 int numberPossiblySwapped = 0;
3974 int numberRemaining = 0;
3975
3976 double totalThru = 0.0; // for when variables flip
3977 //double saveAcceptable=acceptablePivot;
3978 //acceptablePivot=1.0e-9;
3979
3980 double bestEverPivot = acceptablePivot;
3981 int lastSequence = -1;
3982 double lastPivot = 0.0;
3983 double upperTheta;
3984 double newTolerance = dualTolerance_;
3985 //newTolerance = dualTolerance_+1.0e-6*dblParam_[ClpDualTolerance];
3986 // will we need to increase tolerance
3987 //bool thisIncrease = false;
3988 // If we think we need to modify costs (not if something from broad sweep)
3989 bool modifyCosts = false;
3990 // Increase in objective due to swapping bounds (may be negative)
3991 double increaseInObjective = 0.0;
3992
3993 // use spareArrays to put ones looked at in
3994 // we are going to flip flop between
3995 int iFlip = 0;
3996 // Possible list of pivots
3997 int interesting[2];
3998 // where possible swapped ones are
3999 int swapped[2];
4000 // for zeroing out arrays after
4001 int marker[2][2];
4002 // pivot elements
4003 double *array[2], *spare, *spare2;
4004 // indices
4005 int *indices[2], *index, *index2;
4006 spareArray2->clear();
4007 array[0] = spareArray->denseVector();
4008 indices[0] = spareArray->getIndices();
4009 spare = array[0];
4010 index = indices[0];
4011 array[1] = spareArray2->denseVector();
4012 indices[1] = spareArray2->getIndices();
4013 int i;
4014
4015 // initialize lists
4016 for (i = 0; i < 2; i++) {
4017 interesting[i] = 0;
4018 swapped[i] = numberColumns_;
4019 marker[i][0] = 0;
4020 marker[i][1] = numberColumns_;
4021 }
4022 /*
4023 First we get a list of possible pivots. We can also see if the
4024 problem looks infeasible or whether we want to pivot in free variable.
4025 This may make objective go backwards but can only happen a finite
4026 number of times and I do want free variables basic.
4027
4028 Then we flip back and forth. At the start of each iteration
4029 interesting[iFlip] should have possible candidates and swapped[iFlip]
4030 will have pivots if we decide to take a previous pivot.
4031 At end of each iteration interesting[1-iFlip] should have
4032 candidates if we go through this theta and swapped[1-iFlip]
4033 pivots if we don't go through.
4034
4035 At first we increase theta and see what happens. We start
4036 theta at a reasonable guess. If in right area then we do bit by bit.
4037
4038 */
4039
4040 // do first pass to get possibles
4041 upperTheta = 1.0e31;
4042 double bestPossible = 1.0;
4043 double badFree = 0.0;
4044 alpha_ = 0.0;
4045 if (spareIntArray_[0] >= 0) {
4046 numberRemaining = dualColumn0(rowArray, columnArray, spareArray,
4047 acceptablePivot, upperTheta, badFree);
4048 } else {
4049 // already done
4050 numberRemaining = spareArray->getNumElements();
4051 spareArray->setNumElements(0);
4052 upperTheta = spareDoubleArray_[0];
4053 if (spareIntArray_[0] == -1) {
4054 theta_ = spareDoubleArray_[2];
4055 alpha_ = spareDoubleArray_[3];
4056 sequenceIn_ = spareIntArray_[1];
4057 } else {
4058 #if 0
4059 #undef NDEBUG
4060 int n = numberRemaining;
4061 double u = upperTheta;
4062 upperTheta = 1.0e31;
4063 CoinIndexedVector temp(4000);
4064 numberRemaining = dualColumn0(rowArray, columnArray, &temp,
4065 acceptablePivot, upperTheta, badFree);
4066 assert (n == numberRemaining);
4067 double * spare = spareArray->denseVector();
4068 int * index = spareArray->getIndices();
4069 double * spareX = temp.denseVector();
4070 int * indexX = temp.getIndices();
4071 CoinSort_2(spare,spare+n,index);
4072 CoinSort_2(spareX,spareX+n,indexX);
4073 for (int i=0;i<n;i++) {
4074 assert (index[i]==indexX[i]);
4075 assert (fabs(spare[i]-spareX[i])<1.0e-6);
4076 }
4077 assert (fabs(u - upperTheta) < 1.0e-7);
4078 #endif
4079 }
4080 }
4081 // switch off
4082 spareIntArray_[0] = 0;
4083 // We can also see if infeasible or pivoting on free
4084 double tentativeTheta = 1.0e25;
4085 interesting[0] = numberRemaining;
4086 marker[0][0] = numberRemaining;
4087
4088 if (!numberRemaining && sequenceIn_ < 0)
4089 return 0.0; // Looks infeasible
4090
4091 // If sum of bad small pivots too much
4092 #define MORE_CAREFUL
4093 #ifdef MORE_CAREFUL
4094 bool badSumPivots = false;
4095 #endif
4096 if (sequenceIn_ >= 0) {
4097 // free variable - always choose
4098 } else {
4099
4100 theta_ = 1.0e50;
4101 // now flip flop between spare arrays until reasonable theta
4102 tentativeTheta = CoinMax(10.0 * upperTheta, 1.0e-7);
4103
4104 // loops increasing tentative theta until can't go through
4105
4106 while (tentativeTheta < 1.0e22) {
4107 double thruThis = 0.0;
4108
4109 double bestPivot = acceptablePivot;
4110 int bestSequence = -1;
4111
4112 numberPossiblySwapped = numberColumns_;
4113 numberRemaining = 0;
4114
4115 upperTheta = 1.0e50;
4116
4117 spare = array[iFlip];
4118 index = indices[iFlip];
4119 spare2 = array[1 - iFlip];
4120 index2 = indices[1 - iFlip];
4121
4122 // try 3 different ways
4123 // 1 bias increase by ones with slightly wrong djs
4124 // 2 bias by all
4125 // 3 bias by all - tolerance
4126 #define TRYBIAS 3
4127
4128 double increaseInThis = 0.0; //objective increase in this loop
4129
4130 for (i = 0; i < interesting[iFlip]; i++) {
4131 int iSequence = index[i];
4132 double alpha = spare[i];
4133 double oldValue = dj_[iSequence];
4134 double value = oldValue - tentativeTheta * alpha;
4135
4136 if (alpha < 0.0) {
4137 //at upper bound
4138 if (value > newTolerance) {
4139 double range = upper_[iSequence] - lower_[iSequence];
4140 thruThis -= range * alpha;
4141 #if TRYBIAS == 1
4142 if (oldValue > 0.0)
4143 increaseInThis -= oldValue * range;
4144 #elif TRYBIAS == 2
4145 increaseInThis -= oldValue * range;
4146 #else
4147 increaseInThis -= (oldValue + dualTolerance_) * range;
4148 #endif
4149 // goes on swapped list (also means candidates if too many)
4150 spare2[--numberPossiblySwapped] = alpha;
4151 index2[numberPossiblySwapped] = iSequence;
4152 if (fabs(alpha) > bestPivot) {
4153 bestPivot = fabs(alpha);
4154 bestSequence = numberPossiblySwapped;
4155 }
4156 } else {
4157 value = oldValue - upperTheta * alpha;
4158 if (value > newTolerance && -alpha >= acceptablePivot)
4159 upperTheta = (oldValue - newTolerance) / alpha;
4160 spare2[numberRemaining] = alpha;
4161 index2[numberRemaining++] = iSequence;
4162 }
4163 } else {
4164 // at lower bound
4165 if (value < -newTolerance) {
4166 double range = upper_[iSequence] - lower_[iSequence];
4167 thruThis += range * alpha;
4168 //?? is this correct - and should we look at good ones
4169 #if TRYBIAS == 1
4170 if (oldValue < 0.0)
4171 increaseInThis += oldValue * range;
4172 #elif TRYBIAS == 2
4173 increaseInThis += oldValue * range;
4174 #else
4175 increaseInThis += (oldValue - dualTolerance_) * range;
4176 #endif
4177 // goes on swapped list (also means candidates if too many)
4178 spare2[--numberPossiblySwapped] = alpha;
4179 index2[numberPossiblySwapped] = iSequence;
4180 if (fabs(alpha) > bestPivot) {
4181 bestPivot = fabs(alpha);
4182 bestSequence = numberPossiblySwapped;
4183 }
4184 } else {
4185 value = oldValue - upperTheta * alpha;
4186 if (value < -newTolerance && alpha >= acceptablePivot)
4187 upperTheta = (oldValue + newTolerance) / alpha;
4188 spare2[numberRemaining] = alpha;
4189 index2[numberRemaining++] = iSequence;
4190 }
4191 }
4192 }
4193 swapped[1 - iFlip] = numberPossiblySwapped;
4194 interesting[1 - iFlip] = numberRemaining;
4195 marker[1 - iFlip][0] = CoinMax(marker[1 - iFlip][0], numberRemaining);
4196 marker[1 - iFlip][1] = CoinMin(marker[1 - iFlip][1], numberPossiblySwapped);
4197
4198 double check = fabs(totalThru + thruThis);
4199 // add a bit
4200 check += 1.0e-8 + 1.0e-10 * check;
4201 if (check >= fabs(dualOut_) || increaseInObjective + increaseInThis < 0.0) {
4202 // We should be pivoting in this batch
4203 // so compress down to this lot
4204 numberRemaining = 0;
4205 for (i = numberColumns_ - 1; i >= swapped[1 - iFlip]; i--) {
4206 spare[numberRemaining] = spare2[i];
4207 index[numberRemaining++] = index2[i];
4208 }
4209 interesting[iFlip] = numberRemaining;
4210 int iTry;
4211 #define MAXTRY 100
4212 // first get ratio with tolerance
4213 for (iTry = 0; iTry < MAXTRY; iTry++) {
4214
4215 upperTheta = 1.0e50;
4216 numberPossiblySwapped = numberColumns_;
4217 numberRemaining = 0;
4218
4219 increaseInThis = 0.0; //objective increase in this loop
4220
4221 thruThis = 0.0;
4222
4223 spare = array[iFlip];
4224 index = indices[iFlip];
4225 spare2 = array[1 - iFlip];
4226 index2 = indices[1 - iFlip];
4227 for (i = 0; i < interesting[iFlip]; i++) {
4228 int iSequence = index[i];
4229 double alpha = spare[i];
4230 double oldValue = dj_[iSequence];
4231 double value = oldValue - upperTheta * alpha;
4232
4233 if (alpha < 0.0) {
4234 //at upper bound
4235 if (value > newTolerance) {
4236 if (-alpha >= acceptablePivot) {
4237 upperTheta = (oldValue - newTolerance) / alpha;
4238 }
4239 }
4240 } else {
4241 // at lower bound
4242 if (value < -newTolerance) {
4243 if (alpha >= acceptablePivot) {
4244 upperTheta = (oldValue + newTolerance) / alpha;
4245 }
4246 }
4247 }
4248 }
4249 bestPivot = acceptablePivot;
4250 sequenceIn_ = -1;
4251 #ifdef DUBIOUS_WEIGHTS
4252 double bestWeight = COIN_DBL_MAX;
4253 #endif
4254 double largestPivot = acceptablePivot;
4255 // now choose largest and sum all ones which will go through
4256 //printf("XX it %d number %d\n",numberIterations_,interesting[iFlip]);
4257 // Sum of bad small pivots
4258 #ifdef MORE_CAREFUL
4259 double sumBadPivots = 0.0;
4260 badSumPivots = false;
4261 #endif
4262 // Make sure upperTheta will work (-O2 and above gives problems)
4263 upperTheta *= 1.0000000001;
4264 for (i = 0; i < interesting[iFlip]; i++) {
4265 int iSequence = index[i];
4266 double alpha = spare[i];
4267 double value = dj_[iSequence] - upperTheta * alpha;
4268 double badDj = 0.0;
4269
4270 bool addToSwapped = false;
4271
4272 if (alpha < 0.0) {
4273 //at upper bound
4274 if (value >= 0.0) {
4275 addToSwapped = true;
4276 #if TRYBIAS == 1
4277 badDj = -CoinMax(dj_[iSequence], 0.0);
4278 #elif TRYBIAS == 2
4279 badDj = -dj_[iSequence];
4280 #else
4281 badDj = -dj_[iSequence] - dualTolerance_;
4282 #endif
4283 }
4284 } else {
4285 // at lower bound
4286 if (value <= 0.0) {
4287 addToSwapped = true;
4288 #if TRYBIAS == 1
4289 badDj = CoinMin(dj_[iSequence], 0.0);
4290 #elif TRYBIAS == 2
4291 badDj = dj_[iSequence];
4292 #else
4293 badDj = dj_[iSequence] - dualTolerance_;
4294 #endif
4295 }
4296 }
4297 if (!addToSwapped) {
4298 // add to list of remaining
4299 spare2[numberRemaining] = alpha;
4300 index2[numberRemaining++] = iSequence;
4301 } else {
4302 // add to list of swapped
4303 spare2[--numberPossiblySwapped] = alpha;
4304 index2[numberPossiblySwapped] = iSequence;
4305 // select if largest pivot
4306 bool take = false;
4307 double absAlpha = fabs(alpha);
4308 #ifdef DUBIOUS_WEIGHTS
4309 // User could do anything to break ties here
4310 double weight;
4311 if (dubiousWeights)
4312 weight = dubiousWeights[iSequence];
4313 else
4314 weight = 1.0;
4315 weight += randomNumberGenerator_.randomDouble() * 1.0e-2;
4316 if (absAlpha > 2.0 * bestPivot) {
4317 take = true;
4318 } else if (absAlpha > largestPivot) {
4319 // could multiply absAlpha and weight
4320 if (weight * bestPivot < bestWeight * absAlpha)
4321 take = true;
4322 }
4323 #else
4324 if (absAlpha > bestPivot)
4325 take = true;
4326 #endif
4327 #ifdef MORE_CAREFUL
4328 if (absAlpha < acceptablePivot && upperTheta < 1.0e20) {
4329 if (alpha < 0.0) {
4330 //at upper bound
4331 if (value > dualTolerance_) {
4332 double gap = upper_[iSequence] - lower_[iSequence];
4333 if (gap < 1.0e20)
4334 sumBadPivots += value * gap;
4335 else
4336 sumBadPivots += 1.0e20;
4337 //printf("bad %d alpha %g dj at upper %g\n",
4338 // iSequence,alpha,value);
4339 }
4340 } else {
4341 //at lower bound
4342 if (value < -dualTolerance_) {
4343 double gap = upper_[iSequence] - lower_[iSequence];
4344 if (gap < 1.0e20)
4345 sumBadPivots -= value * gap;
4346 else
4347 sumBadPivots += 1.0e20;
4348 //printf("bad %d alpha %g dj at lower %g\n",
4349 // iSequence,alpha,value);
4350 }
4351 }
4352 }
4353 #endif
4354 #ifdef FORCE_FOLLOW
4355 if (iSequence == force_in) {
4356 printf("taking %d - alpha %g best %g\n", force_in, absAlpha, largestPivot);
4357 take = true;
4358 }
4359 #endif
4360 if (take) {
4361 sequenceIn_ = numberPossiblySwapped;
4362 bestPivot = absAlpha;
4363 theta_ = dj_[iSequence] / alpha;
4364 largestPivot = CoinMax(largestPivot, 0.5 * bestPivot);
4365 #ifdef DUBIOUS_WEIGHTS
4366 bestWeight = weight;
4367 #endif
4368 //printf(" taken seq %d alpha %g weight %d\n",
4369 // iSequence,absAlpha,dubiousWeights[iSequence]);
4370 } else {
4371 //printf(" not taken seq %d alpha %g weight %d\n",
4372 // iSequence,absAlpha,dubiousWeights[iSequence]);
4373 }
4374 double range = upper_[iSequence] - lower_[iSequence];
4375 thruThis += range * fabs(alpha);
4376 increaseInThis += badDj * range;
4377 }
4378 }
4379 marker[1 - iFlip][0] = CoinMax(marker[1 - iFlip][0], numberRemaining);
4380 marker[1 - iFlip][1] = CoinMin(marker[1 - iFlip][1], numberPossiblySwapped);
4381 #ifdef MORE_CAREFUL
4382 // If we have done pivots and things look bad set alpha_ 0.0 to force factorization
4383 if (sumBadPivots > 1.0e4) {
4384 if (handler_->logLevel() > 1)
4385 *handler_ << "maybe forcing re-factorization - sum " << sumBadPivots << " " << factorization_->pivots() << " pivots" << CoinMessageEol;
4386 if (factorization_->pivots() > 3) {
4387 badSumPivots = true;
4388 break;
4389 }
4390 }
4391 #endif
4392 swapped[1 - iFlip] = numberPossiblySwapped;
4393 interesting[1 - iFlip] = numberRemaining;
4394 // If we stop now this will be increase in objective (I think)
4395 double increase = (fabs(dualOut_) - totalThru) * theta_;
4396 increase += increaseInObjective;
4397 if (theta_ < 0.0)
4398 thruThis += fabs(dualOut_); // force using this one
4399 if (increaseInObjective < 0.0 && increase < 0.0 && lastSequence >= 0) {
4400 // back
4401 // We may need to be more careful - we could do by
4402 // switch so we always do fine grained?
4403 bestPivot = 0.0;
4404 } else {
4405 // add in
4406 totalThru += thruThis;
4407 increaseInObjective += increaseInThis;
4408 }
4409 if (bestPivot < 0.1 * bestEverPivot && bestEverPivot > 1.0e-6 && (bestPivot < 1.0e-3 || totalThru * 2.0 > fabs(dualOut_))) {
4410 // back to previous one
4411 sequenceIn_ = lastSequence;
4412 // swap regions
4413 iFlip = 1 - iFlip;
4414 break;
4415 } else if (sequenceIn_ == -1 && upperTheta > largeValue_) {
4416 if (lastPivot > acceptablePivot) {
4417 // back to previous one
4418 sequenceIn_ = lastSequence;
4419 // swap regions
4420 iFlip = 1 - iFlip;
4421 } else {
4422 // can only get here if all pivots too small
4423 }
4424 break;
4425 } else if (totalThru >= fabs(dualOut_)) {
4426 modifyCosts = true; // fine grain - we can modify costs
4427 break; // no point trying another loop
4428 } else {
4429 lastSequence = sequenceIn_;
4430 if (bestPivot > bestEverPivot)
4431 bestEverPivot = bestPivot;
4432 iFlip = 1 - iFlip;
4433 modifyCosts = true; // fine grain - we can modify costs
4434 }
4435 }
4436 if (iTry == MAXTRY)
4437 iFlip = 1 - iFlip; // flip back
4438 break;
4439 } else {
4440 // skip this lot
4441 if (bestPivot > 1.0e-3 || bestPivot > bestEverPivot) {
4442 bestEverPivot = bestPivot;
4443 lastSequence = bestSequence;
4444 } else {
4445 // keep old swapped
4446 CoinMemcpyN(array[iFlip] + swapped[iFlip],
4447 numberColumns_ - swapped[iFlip], array[1 - iFlip] + swapped[iFlip]);
4448 CoinMemcpyN(indices[iFlip] + swapped[iFlip],
4449 numberColumns_ - swapped[iFlip], indices[1 - iFlip] + swapped[iFlip]);
4450 marker[1 - iFlip][1] = CoinMin(marker[1 - iFlip][1], swapped[iFlip]);
4451 swapped[1 - iFlip] = swapped[iFlip];
4452 }
4453 increaseInObjective += increaseInThis;
4454 iFlip = 1 - iFlip; // swap regions
4455 tentativeTheta = 2.0 * upperTheta;
4456 totalThru += thruThis;
4457 }
4458 }
4459
4460 // can get here without sequenceIn_ set but with lastSequence
4461 if (sequenceIn_ < 0 && lastSequence >= 0) {
4462 // back to previous one
4463 sequenceIn_ = lastSequence;
4464 // swap regions
4465 iFlip = 1 - iFlip;
4466 }
4467
4468 #define MINIMUMTHETA 1.0e-18
4469 // Movement should be minimum for anti-degeneracy - unless
4470 // fixed variable out
4471 double minimumTheta;
4472 if (upperOut_ > lowerOut_)
4473 minimumTheta = MINIMUMTHETA;
4474 else
4475 minimumTheta = 0.0;
4476 if (sequenceIn_ >= 0) {
4477 // at this stage sequenceIn_ is just pointer into index array
4478 // flip just so we can use iFlip
4479 iFlip = 1 - iFlip;
4480 spare = array[iFlip];
4481 index = indices[iFlip];
4482 double oldValue;
4483 alpha_ = spare[sequenceIn_];
4484 sequenceIn_ = indices[iFlip][sequenceIn_];
4485 oldValue = dj_[sequenceIn_];
4486 theta_ = CoinMax(oldValue / alpha_, 0.0);
4487 if (theta_ < minimumTheta && fabs(alpha_) < 1.0e5 && 1) {
4488 // can't pivot to zero
4489 #if 0
4490 if (oldValue - minimumTheta*alpha_ >= -dualTolerance_) {
4491 theta_ = minimumTheta;
4492 } else if (oldValue - minimumTheta*alpha_ >= -newTolerance) {
4493 theta_ = minimumTheta;
4494 thisIncrease = true;
4495 } else {
4496 theta_ = CoinMax((oldValue + newTolerance) / alpha_, 0.0);
4497 thisIncrease = true;
4498 }
4499 #else
4500 theta_ = minimumTheta;
4501 #endif
4502 }
4503 // may need to adjust costs so all dual feasible AND pivoted is exactly 0
4504 //int costOffset = numberRows_+numberColumns_;
4505 if (modifyCosts && !badSumPivots) {
4506 int i;
4507 for (i = numberColumns_ - 1; i >= swapped[iFlip]; i--) {
4508 int iSequence = index[i];
4509 double alpha = spare[i];
4510 double value = dj_[iSequence] - theta_ * alpha;
4511
4512 // can't be free here
4513
4514 if (alpha < 0.0) {
4515 //at upper bound
4516 if (value > dualTolerance_) {
4517 //thisIncrease = true;
4518 #if CLP_CAN_HAVE_ZERO_OBJ < 2
4519 #define MODIFYCOST 2
4520 #endif
4521 #if MODIFYCOST
4522 // modify cost to hit new tolerance
4523 double modification = alpha * theta_ - dj_[iSequence]
4524 + newTolerance;
4525 if ((specialOptions_ & (2048 + 4096 + 16384)) != 0) {
4526 if ((specialOptions_ & 16384) != 0) {
4527 if (fabs(modification) < 1.0e-8)
4528 modification = 0.0;
4529 } else if ((specialOptions_ & 2048) != 0) {
4530 if (fabs(modification) < 1.0e-10)
4531 modification = 0.0;
4532 } else {
4533 if (fabs(modification) < 1.0e-12)
4534 modification = 0.0;
4535 }
4536 }
4537 dj_[iSequence] += modification;
4538 cost_[iSequence] += modification;
4539 if (modification)
4540 numberChanged_++; // Say changed costs
4541 //cost_[iSequence+costOffset] += modification; // save change
4542 #endif
4543 }
4544 } else {
4545 // at lower bound
4546 if (-value > dualTolerance_) {
4547 //thisIncrease = true;
4548 #if MODIFYCOST
4549 // modify cost to hit new tolerance
4550 double modification = alpha * theta_ - dj_[iSequence]
4551 - newTolerance;
4552 //modification = CoinMax(modification,-dualTolerance_);
4553 //assert (fabs(modification)<1.0e-7);
4554 if ((specialOptions_ & (2048 + 4096)) != 0) {
4555 if ((specialOptions_ & 2048) != 0) {
4556 if (fabs(modification) < 1.0e-10)
4557 modification = 0.0;
4558 } else {
4559 if (fabs(modification) < 1.0e-12)
4560 modification = 0.0;
4561 }
4562 }
4563 dj_[iSequence] += modification;
4564 cost_[iSequence] += modification;
4565 if (modification)
4566 numberChanged_++; // Say changed costs
4567 //cost_[iSequence+costOffset] += modification; // save change
4568 #endif
4569 }
4570 }
4571 }
4572 }
4573 }
4574 }
4575
4576 #ifdef MORE_CAREFUL
4577 // If we have done pivots and things look bad set alpha_ 0.0 to force factorization
4578 if ((badSumPivots || fabs(theta_ * badFree) > 10.0 * dualTolerance_) && factorization_->pivots()) {
4579 if (handler_->logLevel() > 1)
4580 *handler_ << "forcing re-factorization" << CoinMessageEol;
4581 //printf("badSumPivots %g theta_ %g badFree %g\n",badSumPivots,theta_,badFree);
4582 sequenceIn_ = -1;
4583 acceptablePivot_ = -acceptablePivot_;
4584 }
4585 #endif
4586 if (sequenceIn_ >= 0) {
4587 lowerIn_ = lower_[sequenceIn_];
4588 upperIn_ = upper_[sequenceIn_];
4589 valueIn_ = solution_[sequenceIn_];
4590 dualIn_ = dj_[sequenceIn_];
4591
4592 if (numberTimesOptimal_) {
4593 // can we adjust cost back closer to original
4594 //*** add coding
4595 }
4596 #if MODIFYCOST > 1
4597 // modify cost to hit zero exactly
4598 // so (dualIn_+modification)==theta_*alpha_
4599 double modification = theta_ * alpha_ - dualIn_;
4600 // But should not move objective too much ??
4601 #define DONT_MOVE_OBJECTIVE
4602 #ifdef DONT_MOVE_OBJECTIVE
4603 double moveObjective = fabs(modification * solution_[sequenceIn_]);
4604 double smallMove = CoinMax(fabs(objectiveValue_), 1.0e-3);
4605 if (moveObjective > smallMove) {
4606 if (handler_->logLevel() > 1)
4607 printf("would move objective by %g - original mod %g sol value %g\n", moveObjective,
4608 modification, solution_[sequenceIn_]);
4609 modification *= smallMove / moveObjective;
4610 }
4611 #endif
4612 if (badSumPivots)
4613 modification = 0.0;
4614 if ((specialOptions_ & (2048 + 4096)) != 0) {
4615 if ((specialOptions_ & 16384) != 0) {
4616 // in fast dual
4617 if (fabs(modification) < 1.0e-7)
4618 modification = 0.0;
4619 } else if ((specialOptions_ & 2048) != 0) {
4620 if (fabs(modification) < 1.0e-10)
4621 modification = 0.0;
4622 } else {
4623 if (fabs(modification) < 1.0e-12)
4624 modification = 0.0;
4625 }
4626 }
4627 dualIn_ += modification;
4628 dj_[sequenceIn_] = dualIn_;
4629 cost_[sequenceIn_] += modification;
4630 if (modification)
4631 numberChanged_++; // Say changed costs
4632 //int costOffset = numberRows_+numberColumns_;
4633 //cost_[sequenceIn_+costOffset] += modification; // save change
4634 //assert (fabs(modification)<1.0e-6);
4635 #ifdef CLP_DEBUG
4636 if ((handler_->logLevel() & 32) && fabs(modification) > 1.0e-15)
4637 printf("exact %d new cost %g, change %g\n", sequenceIn_,
4638 cost_[sequenceIn_], modification);
4639 #endif
4640 #endif
4641
4642 if (alpha_ < 0.0) {
4643 // as if from upper bound
4644 directionIn_ = -1;
4645 upperIn_ = valueIn_;
4646 } else {
4647 // as if from lower bound
4648 directionIn_ = 1;
4649 lowerIn_ = valueIn_;
4650 }
4651 if (fabs(alpha_) < 1.0e-6) {
4652 // need bestPossible
4653 const double *work;
4654 int number;
4655 const int *which;
4656 const double *reducedCost;
4657 double tentativeTheta = 1.0e15;
4658 //double upperTheta = 1.0e31;
4659 bestPossible = 0.0;
4660 //double multiplier[] = { -1.0, 1.0 };
4661 double dualT = -dualTolerance_;
4662 int nSections = 2;
4663 int addSequence;
4664 for (int iSection = 0; iSection < nSections; iSection++) {
4665 if (!iSection) {
4666 work = rowArray->denseVector();
4667 number = rowArray->getNumElements();
4668 which = rowArray->getIndices();
4669 reducedCost = rowReducedCost_;
4670 addSequence = numberColumns_;
4671 } else {
4672 work = columnArray->denseVector();
4673 number = columnArray->getNumElements();
4674 which = columnArray->getIndices();
4675 reducedCost = reducedCostWork_;
4676 addSequence = 0;
4677 }
4678 for (i = 0; i < number; i++) {
4679 int iSequence = which[i];
4680 double alpha;
4681 double oldValue;
4682 double value;
4683 double mult = 1.0;
4684 switch (getStatus(iSequence + addSequence)) {
4685
4686 case basic:
4687 case ClpSimplex::isFixed:
4688 break;
4689 case isFree:
4690 case superBasic:
4691 alpha = work[i];
4692 bestPossible = CoinMax(bestPossible, fabs(alpha));
4693 break;
4694 case atUpperBound:
4695 mult = -1.0;
4696 case atLowerBound:
4697 alpha = work[i] * mult;
4698 if (alpha > 0.0) {
4699 oldValue = reducedCost[iSequence] * mult;
4700 value = oldValue - tentativeTheta * alpha;
4701 if (value < dualT) {
4702 bestPossible = CoinMax(bestPossible, alpha);
4703 }
4704 }
4705 break;
4706 }
4707 }
4708 }
4709 } else {
4710 bestPossible = fabs(alpha_);
4711 }
4712 } else {
4713 // no pivot
4714 bestPossible = 0.0;
4715 alpha_ = 0.0;
4716 }
4717 //if (thisIncrease)
4718 //dualTolerance_+= 1.0e-6*dblParam_[ClpDualTolerance];
4719
4720 // clear arrays
4721
4722 for (i = 0; i < 2; i++) {
4723 CoinZeroN(array[i], marker[i][0]);
4724 CoinZeroN(array[i] + marker[i][1], numberColumns_ - marker[i][1]);
4725 }
4726 return bestPossible;
4727 }
4728 #ifdef CLP_ALL_ONE_FILE
4729 #undef MAXTRY
4730 #endif
4731 /* Checks if tentative optimal actually means unbounded
4732 Returns -3 if not, 2 if is unbounded */
checkUnbounded(CoinIndexedVector * ray,CoinIndexedVector * spare,double changeCost)4733 int ClpSimplexDual::checkUnbounded(CoinIndexedVector *ray,
4734 CoinIndexedVector *spare,
4735 double changeCost)
4736 {
4737 int status = 2; // say unbounded
4738 factorization_->updateColumn(spare, ray);
4739 // get reduced cost
4740 int i;
4741 int number = ray->getNumElements();
4742 int *index = ray->getIndices();
4743 double *array = ray->denseVector();
4744 for (i = 0; i < number; i++) {
4745 int iRow = index[i];
4746 int iPivot = pivotVariable_[iRow];
4747 changeCost -= cost(iPivot) * array[iRow];
4748 }
4749 double way;
4750 if (changeCost > 0.0) {
4751 //try going down
4752 way = 1.0;
4753 } else if (changeCost < 0.0) {
4754 //try going up
4755 way = -1.0;
4756 } else {
4757 #ifdef CLP_DEBUG
4758 printf("can't decide on up or down\n");
4759 #endif
4760 way = 0.0;
4761 status = -3;
4762 }
4763 double movement = 1.0e10 * way; // some largish number
4764 double zeroTolerance = 1.0e-14 * dualBound_;
4765 for (i = 0; i < number; i++) {
4766 int iRow = index[i];
4767 int iPivot = pivotVariable_[iRow];
4768 double arrayValue = array[iRow];
4769 if (fabs(arrayValue) < zeroTolerance)
4770 arrayValue = 0.0;
4771 double newValue = solution(iPivot) + movement * arrayValue;
4772 if (newValue > upper(iPivot) + primalTolerance_ || newValue < lower(iPivot) - primalTolerance_)
4773 status = -3; // not unbounded
4774 }
4775 if (status == 2) {
4776 // create ray
4777 delete[] ray_;
4778 ray_ = new double[numberColumns_];
4779 CoinZeroN(ray_, numberColumns_);
4780 for (i = 0; i < number; i++) {
4781 int iRow = index[i];
4782 int iPivot = pivotVariable_[iRow];
4783 double arrayValue = array[iRow];
4784 if (iPivot < numberColumns_ && fabs(arrayValue) >= zeroTolerance)
4785 ray_[iPivot] = way * array[iRow];
4786 }
4787 }
4788 ray->clear();
4789 return status;
4790 }
4791 //static int count_status=0;
4792 //static double obj_status=0.0;
4793 //static int check_status=123456789;//41754;
4794 //static int count_alpha=0;
4795 /* Checks if finished. Updates status */
statusOfProblemInDual(int & lastCleaned,int type,double * givenDuals,ClpDataSave & saveData,int ifValuesPass)4796 void ClpSimplexDual::statusOfProblemInDual(int &lastCleaned, int type,
4797 double *givenDuals, ClpDataSave &saveData,
4798 int ifValuesPass)
4799 {
4800 #ifdef CLP_INVESTIGATE_SERIAL
4801 if (z_thinks > 0 && z_thinks < 2)
4802 z_thinks += 2;
4803 #endif
4804 bool arraysNotCreated = (type == 0);
4805 // If lots of iterations then adjust costs if large ones
4806 if (numberIterations_ > 4 * (numberRows_ + numberColumns_) && objectiveScale_ == 1.0) {
4807 double largest = 0.0;
4808 for (int i = 0; i < numberRows_; i++) {
4809 int iColumn = pivotVariable_[i];
4810 largest = CoinMax(largest, fabs(cost_[iColumn]));
4811 }
4812 if (largest > 1.0e6) {
4813 objectiveScale_ = 1.0e6 / largest;
4814 for (int i = 0; i < numberRows_ + numberColumns_; i++)
4815 cost_[i] *= objectiveScale_;
4816 }
4817 }
4818 int numberPivots = factorization_->pivots();
4819 double realDualInfeasibilities = 0.0;
4820 if (type == 2) {
4821 if (alphaAccuracy_ != -1.0)
4822 alphaAccuracy_ = -2.0;
4823 // trouble - restore solution
4824 CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_);
4825 CoinMemcpyN(savedSolution_ + numberColumns_,
4826 numberRows_, rowActivityWork_);
4827 CoinMemcpyN(savedSolution_,
4828 numberColumns_, columnActivityWork_);
4829 // restore extra stuff
4830 int dummy;
4831 matrix_->generalExpanded(this, 6, dummy);
4832 forceFactorization_ = 1; // a bit drastic but ..
4833 changeMade_++; // say something changed
4834 // get correct bounds on all variables
4835 resetFakeBounds(0);
4836 }
4837 int tentativeStatus = problemStatus_;
4838 double changeCost;
4839 bool unflagVariables = true;
4840 bool weightsSaved = false;
4841 bool weightsSaved2 = numberIterations_ && !numberPrimalInfeasibilities_;
4842 int dontFactorizePivots = dontFactorizePivots_;
4843 if (type == 3) {
4844 type = 1;
4845 dontFactorizePivots = 1;
4846 }
4847 if (alphaAccuracy_ < 0.0 || !numberPivots || alphaAccuracy_ > 1.0e4 || numberPivots > 20) {
4848 if (problemStatus_ > -3 || numberPivots > dontFactorizePivots) {
4849 // factorize
4850 // later on we will need to recover from singularities
4851 // also we could skip if first time
4852 // save dual weights
4853 dualRowPivot_->saveWeights(this, 1);
4854 weightsSaved = true;
4855 if (type) {
4856 // is factorization okay?
4857 if (internalFactorize(1)) {
4858 // no - restore previous basis
4859 unflagVariables = false;
4860 assert(type == 1);
4861 changeMade_++; // say something changed
4862 // Keep any flagged variables
4863 int i;
4864 for (i = 0; i < numberRows_ + numberColumns_; i++) {
4865 if (flagged(i))
4866 saveStatus_[i] |= 64; //say flagged
4867 }
4868 CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_);
4869 CoinMemcpyN(savedSolution_ + numberColumns_,
4870 numberRows_, rowActivityWork_);
4871 CoinMemcpyN(savedSolution_,
4872 numberColumns_, columnActivityWork_);
4873 // restore extra stuff
4874 int dummy;
4875 matrix_->generalExpanded(this, 6, dummy);
4876 // get correct bounds on all variables
4877 resetFakeBounds(1);
4878 // need to reject something
4879 char x = isColumn(sequenceOut_) ? 'C' : 'R';
4880 handler_->message(CLP_SIMPLEX_FLAG, messages_)
4881 << x << sequenceWithin(sequenceOut_)
4882 << CoinMessageEol;
4883 #ifdef COIN_DEVELOP
4884 printf("flag d\n");
4885 #endif
4886 setFlagged(sequenceOut_);
4887 progress_.clearBadTimes();
4888
4889 // Go to safe
4890 // not here - as can make more singular
4891 //factorization_->pivotTolerance(0.99);
4892 forceFactorization_ = 1; // a bit drastic but ..
4893 type = 2;
4894 //assert (internalFactorize(1)==0);
4895 if (internalFactorize(1)) {
4896 CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_);
4897 CoinMemcpyN(savedSolution_ + numberColumns_,
4898 numberRows_, rowActivityWork_);
4899 CoinMemcpyN(savedSolution_,
4900 numberColumns_, columnActivityWork_);
4901 // restore extra stuff
4902 int dummy;
4903 matrix_->generalExpanded(this, 6, dummy);
4904 // debug
4905 int returnCode = internalFactorize(1);
4906 while (returnCode) {
4907 // ouch
4908 // switch off dense
4909 int saveDense = factorization_->denseThreshold();
4910 factorization_->setDenseThreshold(0);
4911 // Go to safe
4912 factorization_->pivotTolerance(0.99);
4913 // make sure will do safe factorization
4914 pivotVariable_[0] = -1;
4915 returnCode = internalFactorize(2);
4916 factorization_->setDenseThreshold(saveDense);
4917 }
4918 // get correct bounds on all variables
4919 resetFakeBounds(1);
4920 }
4921 }
4922 }
4923 if (problemStatus_ != -4 || numberPivots > 10)
4924 problemStatus_ = -3;
4925 }
4926 } else {
4927 //printf("testing with accuracy of %g and status of %d\n",alphaAccuracy_,problemStatus_);
4928 //count_alpha++;
4929 //if ((count_alpha%5000)==0)
4930 //printf("count alpha %d\n",count_alpha);
4931 }
4932 if (progress_.infeasibility_[0] < 1.0e-1 && primalTolerance_ == 1.0e-7 && progress_.iterationNumber_[0] > 0 && progress_.iterationNumber_[CLP_PROGRESS - 1] - progress_.iterationNumber_[0] > 25) {
4933 // default - so user did not set
4934 int iP;
4935 double minAverage = COIN_DBL_MAX;
4936 double maxAverage = 0.0;
4937 for (iP = 0; iP < CLP_PROGRESS; iP++) {
4938 int n = progress_.numberInfeasibilities_[iP];
4939 if (!n) {
4940 break;
4941 } else {
4942 double average = progress_.infeasibility_[iP];
4943 if (average > 0.1)
4944 break;
4945 average /= static_cast< double >(n);
4946 minAverage = CoinMin(minAverage, average);
4947 maxAverage = CoinMax(maxAverage, average);
4948 }
4949 }
4950 if (iP == CLP_PROGRESS && minAverage < 1.0e-5 && maxAverage < 1.0e-3) {
4951 // change tolerance
4952 #if CBC_USEFUL_PRINTING > 0
4953 printf("CCchanging tolerance\n");
4954 #endif
4955 primalTolerance_ = 1.0e-6;
4956 minimumPrimalTolerance_ = primalTolerance_;
4957 dblParam_[ClpPrimalTolerance] = 1.0e-6;
4958 moreSpecialOptions_ |= 4194304;
4959 }
4960 }
4961 // at this stage status is -3 or -4 if looks infeasible
4962 // get primal and dual solutions
4963 #if 0
4964 {
4965 int numberTotal = numberRows_ + numberColumns_;
4966 double * saveSol = CoinCopyOfArray(solution_, numberTotal);
4967 double * saveDj = CoinCopyOfArray(dj_, numberTotal);
4968 double tolerance = type ? 1.0e-4 : 1.0e-8;
4969 // always if values pass
4970 double saveObj = objectiveValue_;
4971 double sumPrimal = sumPrimalInfeasibilities_;
4972 int numberPrimal = numberPrimalInfeasibilities_;
4973 double sumDual = sumDualInfeasibilities_;
4974 int numberDual = numberDualInfeasibilities_;
4975 gutsOfSolution(givenDuals, NULL);
4976 int j;
4977 double largestPrimal = tolerance;
4978 int iPrimal = -1;
4979 for (j = 0; j < numberTotal; j++) {
4980 double difference = solution_[j] - saveSol[j];
4981 if (fabs(difference) > largestPrimal) {
4982 iPrimal = j;
4983 largestPrimal = fabs(difference);
4984 }
4985 }
4986 double largestDual = tolerance;
4987 int iDual = -1;
4988 for (j = 0; j < numberTotal; j++) {
4989 double difference = dj_[j] - saveDj[j];
4990 if (fabs(difference) > largestDual && upper_[j] > lower_[j]) {
4991 iDual = j;
4992 largestDual = fabs(difference);
4993 }
4994 }
4995 if (!type) {
4996 if (fabs(saveObj - objectiveValue_) > 1.0e-5 ||
4997 numberPrimal != numberPrimalInfeasibilities_ || numberPrimal != 1 ||
4998 fabs(sumPrimal - sumPrimalInfeasibilities_) > 1.0e-5 || iPrimal >= 0 ||
4999 numberDual != numberDualInfeasibilities_ || numberDual != 0 ||
5000 fabs(sumDual - sumDualInfeasibilities_) > 1.0e-5 || iDual >= 0)
5001 printf("type %d its %d pivots %d primal n(%d,%d) s(%g,%g) diff(%g,%d) dual n(%d,%d) s(%g,%g) diff(%g,%d) obj(%g,%g)\n",
5002 type, numberIterations_, numberPivots,
5003 numberPrimal, numberPrimalInfeasibilities_, sumPrimal, sumPrimalInfeasibilities_,
5004 largestPrimal, iPrimal,
5005 numberDual, numberDualInfeasibilities_, sumDual, sumDualInfeasibilities_,
5006 largestDual, iDual,
5007 saveObj, objectiveValue_);
5008 } else {
5009 if (fabs(saveObj - objectiveValue_) > 1.0e-5 ||
5010 numberPrimalInfeasibilities_ || iPrimal >= 0 ||
5011 numberDualInfeasibilities_ || iDual >= 0)
5012 printf("type %d its %d pivots %d primal n(%d,%d) s(%g,%g) diff(%g,%d) dual n(%d,%d) s(%g,%g) diff(%g,%d) obj(%g,%g)\n",
5013 type, numberIterations_, numberPivots,
5014 numberPrimal, numberPrimalInfeasibilities_, sumPrimal, sumPrimalInfeasibilities_,
5015 largestPrimal, iPrimal,
5016 numberDual, numberDualInfeasibilities_, sumDual, sumDualInfeasibilities_,
5017 largestDual, iDual,
5018 saveObj, objectiveValue_);
5019 }
5020 delete [] saveSol;
5021 delete [] saveDj;
5022 }
5023 #else
5024 if (type || ifValuesPass)
5025 gutsOfSolution(givenDuals, NULL);
5026 #endif
5027 // If bad accuracy treat as singular
5028 if ((largestPrimalError_ > 1.0e15 || largestDualError_ > 1.0e15) && numberIterations_) {
5029 // restore previous basis
5030 unflagVariables = false;
5031 changeMade_++; // say something changed
5032 // Keep any flagged variables
5033 int i;
5034 for (i = 0; i < numberRows_ + numberColumns_; i++) {
5035 if (flagged(i))
5036 saveStatus_[i] |= 64; //say flagged
5037 }
5038 CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_);
5039 CoinMemcpyN(savedSolution_ + numberColumns_,
5040 numberRows_, rowActivityWork_);
5041 CoinMemcpyN(savedSolution_,
5042 numberColumns_, columnActivityWork_);
5043 // restore extra stuff
5044 int dummy;
5045 matrix_->generalExpanded(this, 6, dummy);
5046 // get correct bounds on all variables
5047 resetFakeBounds(1);
5048 // need to reject something
5049 int rejectedVariable = sequenceOut_;
5050 if (flagged(rejectedVariable)) {
5051 rejectedVariable = -1;
5052 for (int i = 0; i < numberRows_; i++) {
5053 int iSequence = pivotVariable_[i];
5054 if (!flagged(iSequence)) {
5055 rejectedVariable = iSequence;
5056 break;
5057 }
5058 }
5059 if (rejectedVariable < 0) {
5060 if (handler_->logLevel() > 1)
5061 printf("real trouble at line %d of ClpSimplexDual\n",
5062 __LINE__);
5063 problemStatus_ = 10;
5064 return;
5065 }
5066 }
5067 char x = isColumn(rejectedVariable) ? 'C' : 'R';
5068 handler_->message(CLP_SIMPLEX_FLAG, messages_)
5069 << x << sequenceWithin(rejectedVariable)
5070 << CoinMessageEol;
5071 #ifdef COIN_DEVELOP
5072 printf("flag e\n");
5073 #endif
5074 setFlagged(rejectedVariable);
5075 progress_.clearBadTimes();
5076
5077 // Go to safer
5078 double newTolerance = CoinMin(1.1 * factorization_->pivotTolerance(), 0.99);
5079 factorization_->pivotTolerance(newTolerance);
5080 forceFactorization_ = 1; // a bit drastic but ..
5081 if (alphaAccuracy_ != -1.0)
5082 alphaAccuracy_ = -2.0;
5083 type = 2;
5084 //assert (internalFactorize(1)==0);
5085 if (internalFactorize(1)) {
5086 CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_);
5087 CoinMemcpyN(savedSolution_ + numberColumns_,
5088 numberRows_, rowActivityWork_);
5089 CoinMemcpyN(savedSolution_,
5090 numberColumns_, columnActivityWork_);
5091 // restore extra stuff
5092 int dummy;
5093 matrix_->generalExpanded(this, 6, dummy);
5094 // debug
5095 int returnCode = internalFactorize(1);
5096 while (returnCode) {
5097 // ouch
5098 // switch off dense
5099 int saveDense = factorization_->denseThreshold();
5100 factorization_->setDenseThreshold(0);
5101 // Go to safe
5102 factorization_->pivotTolerance(0.99);
5103 // make sure will do safe factorization
5104 pivotVariable_[0] = -1;
5105 returnCode = internalFactorize(2);
5106 factorization_->setDenseThreshold(saveDense);
5107 }
5108 // get correct bounds on all variables
5109 resetFakeBounds(1);
5110 }
5111 // get primal and dual solutions
5112 gutsOfSolution(givenDuals, NULL);
5113 } else if (goodAccuracy()) {
5114 // Can reduce tolerance
5115 double newTolerance = CoinMax(0.995 * factorization_->pivotTolerance(), saveData.pivotTolerance_);
5116 factorization_->pivotTolerance(newTolerance);
5117 }
5118 bestObjectiveValue_ = CoinMax(bestObjectiveValue_,
5119 objectiveValue_ - bestPossibleImprovement_);
5120 bool reallyBadProblems = false;
5121 // Double check infeasibility if no action
5122 if (progress_.lastIterationNumber(0) == numberIterations_) {
5123 if (dualRowPivot_->looksOptimal()) {
5124 numberPrimalInfeasibilities_ = 0;
5125 sumPrimalInfeasibilities_ = 0.0;
5126 }
5127 #if 1
5128 } else {
5129 double thisObj = objectiveValue_ - bestPossibleImprovement_;
5130 #ifdef CLP_INVESTIGATE
5131 assert(bestPossibleImprovement_ > -1000.0 && objectiveValue_ > -1.0e100);
5132 if (bestPossibleImprovement_)
5133 printf("obj %g add in %g -> %g\n", objectiveValue_, bestPossibleImprovement_,
5134 thisObj);
5135 #endif
5136 double lastObj = progress_.lastObjective(0);
5137 #ifndef NDEBUG
5138 #ifdef COIN_DEVELOP
5139 resetFakeBounds(-1);
5140 #endif
5141 #endif
5142 #ifdef CLP_REPORT_PROGRESS
5143 ixxxxxx++;
5144 if (ixxxxxx >= ixxyyyy - 4 && ixxxxxx <= ixxyyyy) {
5145 char temp[20];
5146 sprintf(temp, "sol%d.out", ixxxxxx);
5147 printf("sol%d.out\n", ixxxxxx);
5148 FILE *fp = fopen(temp, "w");
5149 int nTotal = numberRows_ + numberColumns_;
5150 for (int i = 0; i < nTotal; i++)
5151 fprintf(fp, "%d %d %g %g %g %g %g\n",
5152 i, status_[i], lower_[i], solution_[i], upper_[i], cost_[i], dj_[i]);
5153 fclose(fp);
5154 }
5155 #endif
5156 if (!ifValuesPass && firstFree_ < 0) {
5157 double testTol = 5.0e-3;
5158 if (progress_.timesFlagged() > 10) {
5159 testTol *= pow(2.0, progress_.timesFlagged() - 8);
5160 } else if (progress_.timesFlagged() > 5) {
5161 testTol *= 5.0;
5162 }
5163 if (lastObj > thisObj + testTol * (fabs(thisObj) + fabs(lastObj)) + testTol) {
5164 int maxFactor = factorization_->maximumPivots();
5165 if ((specialOptions_ & 1048576) == 0) {
5166 if (progress_.timesFlagged() > 10)
5167 progress_.incrementReallyBadTimes();
5168 if (maxFactor > 10 - 9) {
5169 #ifdef COIN_DEVELOP
5170 printf("lastobj %g thisobj %g\n", lastObj, thisObj);
5171 #endif
5172 //if (forceFactorization_<0)
5173 //forceFactorization_= maxFactor;
5174 //forceFactorization_ = CoinMax(1,(forceFactorization_>>1));
5175 if ((progressFlag_ & 4) == 0 && lastObj < thisObj + 1.0e4 && largestPrimalError_ < 1.0e2) {
5176 // Just save costs
5177 // save extra copy of cost_
5178 int nTotal = numberRows_ + numberColumns_;
5179 double *temp = new double[2 * nTotal];
5180 memcpy(temp, cost_, nTotal * sizeof(double));
5181 memcpy(temp + nTotal, cost_, nTotal * sizeof(double));
5182 delete[] cost_;
5183 cost_ = temp;
5184 objectiveWork_ = cost_;
5185 rowObjectiveWork_ = cost_ + numberColumns_;
5186 progressFlag_ |= 4;
5187 } else {
5188 forceFactorization_ = 1;
5189 #ifdef COIN_DEVELOP
5190 printf("Reducing factorization frequency - bad backwards\n");
5191 #endif
5192 #if 1
5193 unflagVariables = false;
5194 changeMade_++; // say something changed
5195 int nTotal = numberRows_ + numberColumns_;
5196 CoinMemcpyN(saveStatus_, nTotal, status_);
5197 CoinMemcpyN(savedSolution_ + numberColumns_,
5198 numberRows_, rowActivityWork_);
5199 CoinMemcpyN(savedSolution_,
5200 numberColumns_, columnActivityWork_);
5201 if ((progressFlag_ & 4) == 0) {
5202 // save extra copy of cost_
5203 double *temp = new double[2 * nTotal];
5204 memcpy(temp, cost_, nTotal * sizeof(double));
5205 memcpy(temp + nTotal, cost_, nTotal * sizeof(double));
5206 delete[] cost_;
5207 cost_ = temp;
5208 objectiveWork_ = cost_;
5209 rowObjectiveWork_ = cost_ + numberColumns_;
5210 progressFlag_ |= 4;
5211 } else {
5212 memcpy(cost_, cost_ + nTotal, nTotal * sizeof(double));
5213 }
5214 // restore extra stuff
5215 int dummy;
5216 matrix_->generalExpanded(this, 6, dummy);
5217 double pivotTolerance = factorization_->pivotTolerance();
5218 if (pivotTolerance < 0.2)
5219 factorization_->pivotTolerance(0.2);
5220 else if (progress_.timesFlagged() > 2)
5221 factorization_->pivotTolerance(CoinMin(pivotTolerance * 1.1, 0.99));
5222 if (alphaAccuracy_ != -1.0)
5223 alphaAccuracy_ = -2.0;
5224 if (internalFactorize(1)) {
5225 CoinMemcpyN(saveStatus_, numberColumns_ + numberRows_, status_);
5226 CoinMemcpyN(savedSolution_ + numberColumns_,
5227 numberRows_, rowActivityWork_);
5228 CoinMemcpyN(savedSolution_,
5229 numberColumns_, columnActivityWork_);
5230 // restore extra stuff
5231 int dummy;
5232 matrix_->generalExpanded(this, 6, dummy);
5233 // debug
5234 int returnCode = internalFactorize(1);
5235 while (returnCode) {
5236 // ouch
5237 // switch off dense
5238 int saveDense = factorization_->denseThreshold();
5239 factorization_->setDenseThreshold(0);
5240 // Go to safe
5241 factorization_->pivotTolerance(0.99);
5242 // make sure will do safe factorization
5243 pivotVariable_[0] = -1;
5244 returnCode = internalFactorize(2);
5245 factorization_->setDenseThreshold(saveDense);
5246 }
5247 }
5248 resetFakeBounds(0);
5249 type = 2; // so will restore weights
5250 // get primal and dual solutions
5251 gutsOfSolution(givenDuals, NULL);
5252 if (numberPivots < 2) {
5253 // need to reject something
5254 char x = isColumn(sequenceOut_) ? 'C' : 'R';
5255 handler_->message(CLP_SIMPLEX_FLAG, messages_)
5256 << x << sequenceWithin(sequenceOut_)
5257 << CoinMessageEol;
5258 #ifdef COIN_DEVELOP
5259 printf("flag d\n");
5260 #endif
5261 setFlagged(sequenceOut_);
5262 progress_.clearBadTimes();
5263 progress_.incrementTimesFlagged();
5264 }
5265 if (numberPivots < 10)
5266 reallyBadProblems = true;
5267 #ifdef COIN_DEVELOP
5268 printf("obj now %g\n", objectiveValue_);
5269 #endif
5270 progress_.modifyObjective(objectiveValue_
5271 - bestPossibleImprovement_);
5272 #endif
5273 }
5274 }
5275 } else {
5276 // in fast dual give up
5277 #ifdef COIN_DEVELOP
5278 printf("In fast dual?\n");
5279 #endif
5280 problemStatus_ = 3;
5281 }
5282 } else if (lastObj < thisObj - 1.0e-5 * CoinMax(fabs(thisObj), fabs(lastObj)) - 1.0e-3) {
5283 numberTimesOptimal_ = 0;
5284 }
5285 }
5286 #endif
5287 }
5288 // Up tolerance if looks a bit odd
5289 if (numberIterations_ > CoinMax(1000, numberRows_ >> 4) && (specialOptions_ & 64) != 0) {
5290 if (sumPrimalInfeasibilities_ && sumPrimalInfeasibilities_ < 1.0e5) {
5291 int backIteration = progress_.lastIterationNumber(CLP_PROGRESS - 1);
5292 if (backIteration > 0 && numberIterations_ - backIteration < 9 * CLP_PROGRESS) {
5293 if (factorization_->pivotTolerance() < 0.9) {
5294 // up tolerance
5295 factorization_->pivotTolerance(CoinMin(factorization_->pivotTolerance() * 1.05 + 0.02, 0.91));
5296 //printf("tol now %g\n",factorization_->pivotTolerance());
5297 progress_.clearIterationNumbers();
5298 }
5299 }
5300 }
5301 }
5302 // Check if looping
5303 int loop;
5304 if (!givenDuals && type != 2)
5305 loop = progress_.looping();
5306 else
5307 loop = -1;
5308 if (progress_.reallyBadTimes() > 10) {
5309 problemStatus_ = 10; // instead - try other algorithm
5310 #if COIN_DEVELOP > 2
5311 printf("returning at %d\n", __LINE__);
5312 #endif
5313 }
5314 int situationChanged = 0;
5315 if (loop >= 0) {
5316 problemStatus_ = loop; //exit if in loop
5317 if (!problemStatus_) {
5318 // declaring victory
5319 numberPrimalInfeasibilities_ = 0;
5320 sumPrimalInfeasibilities_ = 0.0;
5321 } else {
5322 problemStatus_ = 10; // instead - try other algorithm
5323 #if COIN_DEVELOP > 2
5324 printf("returning at %d\n", __LINE__);
5325 #endif
5326 }
5327 return;
5328 } else if (loop < -1) {
5329 // something may have changed
5330 gutsOfSolution(NULL, NULL);
5331 situationChanged = 1;
5332 }
5333 // really for free variables in
5334 if ((progressFlag_ & 2) != 0) {
5335 situationChanged = 2;
5336 }
5337 progressFlag_ &= (~3); //reset progress flag
5338 if ((progressFlag_ & 4) != 0) {
5339 // save copy of cost_
5340 int nTotal = numberRows_ + numberColumns_;
5341 memcpy(cost_ + nTotal, cost_, nTotal * sizeof(double));
5342 }
5343 /*if (!numberIterations_&&sumDualInfeasibilities_)
5344 printf("OBJ %g sumPinf %g sumDinf %g\n",
5345 objectiveValue(),sumPrimalInfeasibilities_,
5346 sumDualInfeasibilities_);*/
5347 // mark as having gone optimal if looks like it
5348 if (!numberPrimalInfeasibilities_ && !numberDualInfeasibilities_)
5349 progressFlag_ |= 8;
5350 if (handler_->detail(CLP_SIMPLEX_STATUS, messages_) < 100) {
5351 handler_->message(CLP_SIMPLEX_STATUS, messages_)
5352 << numberIterations_ << objectiveValue();
5353 handler_->printing(sumPrimalInfeasibilities_ > 0.0)
5354 << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_;
5355 handler_->printing(sumDualInfeasibilities_ > 0.0)
5356 << sumDualInfeasibilities_ << numberDualInfeasibilities_;
5357 handler_->printing(numberDualInfeasibilitiesWithoutFree_
5358 < numberDualInfeasibilities_)
5359 << numberDualInfeasibilitiesWithoutFree_;
5360 handler_->message() << CoinMessageEol;
5361 }
5362 #if 0
5363 count_status++;
5364 if (!numberIterations_)
5365 obj_status=-1.0e30;
5366 if (objectiveValue()<obj_status-0.01) {
5367 printf("Backward obj at %d from %g to %g\n",
5368 count_status,obj_status,objectiveValue());
5369 }
5370 obj_status=objectiveValue();
5371 if (count_status>=check_status-1) {
5372 printf("Trouble ahead - count_status %d\n",count_status);
5373 }
5374 #endif
5375 #if 0
5376 printf("IT %d %g %g(%d) %g(%d)\n",
5377 numberIterations_, objectiveValue(),
5378 sumPrimalInfeasibilities_, numberPrimalInfeasibilities_,
5379 sumDualInfeasibilities_, numberDualInfeasibilities_);
5380 #endif
5381 double approximateObjective = objectiveValue_;
5382 #ifdef CLP_REPORT_PROGRESS
5383 if (ixxxxxx >= ixxyyyy - 4 && ixxxxxx <= ixxyyyy) {
5384 char temp[20];
5385 sprintf(temp, "x_sol%d.out", ixxxxxx);
5386 FILE *fp = fopen(temp, "w");
5387 int nTotal = numberRows_ + numberColumns_;
5388 for (int i = 0; i < nTotal; i++)
5389 fprintf(fp, "%d %d %g %g %g %g %g\n",
5390 i, status_[i], lower_[i], solution_[i], upper_[i], cost_[i], dj_[i]);
5391 fclose(fp);
5392 if (ixxxxxx == ixxyyyy)
5393 exit(6);
5394 }
5395 #endif
5396 realDualInfeasibilities = sumDualInfeasibilities_;
5397 double saveTolerance = dualTolerance_;
5398 // If we need to carry on cleaning variables
5399 if (!numberPrimalInfeasibilities_ && (specialOptions_ & 1024) != 0 && CLEAN_FIXED) {
5400 for (int iRow = 0; iRow < numberRows_; iRow++) {
5401 int iPivot = pivotVariable_[iRow];
5402 if (!flagged(iPivot) && pivoted(iPivot)) {
5403 // carry on
5404 numberPrimalInfeasibilities_ = -1;
5405 sumOfRelaxedPrimalInfeasibilities_ = 1.0;
5406 sumPrimalInfeasibilities_ = 1.0;
5407 break;
5408 }
5409 }
5410 }
5411 /* If we are primal feasible and any dual infeasibilities are on
5412 free variables then it is better to go to primal */
5413 if (!numberPrimalInfeasibilities_ && ((!numberDualInfeasibilitiesWithoutFree_ && numberDualInfeasibilities_) || (moreSpecialOptions_ & 16777216) != 0))
5414 problemStatus_ = 10;
5415 // dual bound coming in
5416 double saveDualBound = dualBound_;
5417 bool needCleanFake = false;
5418 while (problemStatus_ <= -3 && saveDualBound == dualBound_) {
5419 int cleanDuals = 0;
5420 if (situationChanged != 0)
5421 cleanDuals = 1;
5422 int numberChangedBounds = 0;
5423 int doOriginalTolerance = 0;
5424 if (lastCleaned == numberIterations_)
5425 doOriginalTolerance = 1;
5426 // check optimal
5427 // give code benefit of doubt
5428 if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) {
5429 // say optimal (with these bounds etc)
5430 numberDualInfeasibilities_ = 0;
5431 sumDualInfeasibilities_ = 0.0;
5432 numberPrimalInfeasibilities_ = 0;
5433 sumPrimalInfeasibilities_ = 0.0;
5434 }
5435 //if (dualFeasible()||problemStatus_==-4||(primalFeasible()&&!numberDualInfeasibilitiesWithoutFree_)) {
5436 if (dualFeasible() || problemStatus_ == -4) {
5437 progress_.modifyObjective(objectiveValue_
5438 - bestPossibleImprovement_);
5439 #ifdef COIN_DEVELOP
5440 if (sumDualInfeasibilities_ || bestPossibleImprovement_)
5441 printf("improve %g dualinf %g -> %g\n",
5442 bestPossibleImprovement_, sumDualInfeasibilities_,
5443 sumDualInfeasibilities_ * dualBound_);
5444 #endif
5445 // see if cutoff reached
5446 double limit = 0.0;
5447 getDblParam(ClpDualObjectiveLimit, limit);
5448 #if 0
5449 if(fabs(limit) < 1.0e30 && objectiveValue()*optimizationDirection_ >
5450 limit + 1.0e-7 + 1.0e-8 * fabs(limit) && !numberAtFakeBound()) {
5451 //looks infeasible on objective
5452 if (perturbation_ == 101) {
5453 cleanDuals = 1;
5454 // Save costs
5455 int numberTotal = numberRows_ + numberColumns_;
5456 double * saveCost = CoinCopyOfArray(cost_, numberTotal);
5457 // make sure fake bounds are back
5458 changeBounds(1, NULL, changeCost);
5459 createRim4(false);
5460 // make sure duals are current
5461 computeDuals(givenDuals);
5462 checkDualSolution();
5463 if(objectiveValue()*optimizationDirection_ >
5464 limit + 1.0e-7 + 1.0e-8 * fabs(limit) && !numberDualInfeasibilities_) {
5465 perturbation_ = 102; // stop any perturbations
5466 printf("cutoff test succeeded\n");
5467 } else {
5468 printf("cutoff test failed\n");
5469 // put back
5470 memcpy(cost_, saveCost, numberTotal * sizeof(double));
5471 // make sure duals are current
5472 computeDuals(givenDuals);
5473 checkDualSolution();
5474 progress_.modifyObjective(-COIN_DBL_MAX);
5475 problemStatus_ = -1;
5476 }
5477 delete [] saveCost;
5478 }
5479 }
5480 #endif
5481 if (primalFeasible() && !givenDuals) {
5482 // may be optimal - or may be bounds are wrong
5483 handler_->message(CLP_DUAL_BOUNDS, messages_)
5484 << dualBound_
5485 << CoinMessageEol;
5486 // save solution in case unbounded
5487 double *saveColumnSolution = NULL;
5488 double *saveRowSolution = NULL;
5489 bool inCbc = (specialOptions_ & (0x01000000 | 16384)) != 0;
5490 if (!inCbc) {
5491 saveColumnSolution = CoinCopyOfArray(columnActivityWork_, numberColumns_);
5492 saveRowSolution = CoinCopyOfArray(rowActivityWork_, numberRows_);
5493 }
5494 #ifndef COIN_MAX_DUAL_BOUND
5495 #define COIN_MAX_DUAL_BOUND 1.0e20
5496 #endif
5497 numberChangedBounds = (dualBound_ < COIN_MAX_DUAL_BOUND) ? changeBounds(0, rowArray_[3], changeCost) : 0;
5498 if (numberChangedBounds <= 0 && !numberDualInfeasibilities_) {
5499 //looks optimal - do we need to reset tolerance
5500 if (perturbation_ == 101) {
5501 perturbation_ = 102; // stop any perturbations
5502 cleanDuals = 1;
5503 // make sure fake bounds are back
5504 //computeObjectiveValue();
5505 changeBounds(1, NULL, changeCost);
5506 //computeObjectiveValue();
5507 createRim4(false);
5508 // make sure duals are current
5509 computeDuals(givenDuals);
5510 checkDualSolution();
5511 progress_.modifyObjective(-COIN_DBL_MAX);
5512 #define DUAL_TRY_FASTER
5513 #ifdef DUAL_TRY_FASTER
5514 if (numberDualInfeasibilities_) {
5515 #endif
5516 numberChanged_ = 1; // force something to happen
5517 lastCleaned = numberIterations_ - 1;
5518 #ifdef DUAL_TRY_FASTER
5519 } else {
5520 //double value = objectiveValue_;
5521 computeObjectiveValue(true);
5522 //printf("old %g new %g\n",value,objectiveValue_);
5523 //numberChanged_=1;
5524 }
5525 #endif
5526 }
5527 if (lastCleaned < numberIterations_ && numberTimesOptimal_ < 4 && (numberChanged_ || (specialOptions_ & 4096) == 0)) {
5528 #if CLP_CAN_HAVE_ZERO_OBJ
5529 if ((specialOptions_ & 16777216) == 0) {
5530 #endif
5531 doOriginalTolerance = 2;
5532 numberTimesOptimal_++;
5533 changeMade_++; // say something changed
5534 if (numberTimesOptimal_ == 1) {
5535 dualTolerance_ = dblParam_[ClpDualTolerance];
5536 } else {
5537 if (numberTimesOptimal_ == 2) {
5538 // better to have small tolerance even if slower
5539 factorization_->zeroTolerance(CoinMin(factorization_->zeroTolerance(), 1.0e-15));
5540 }
5541 dualTolerance_ = dblParam_[ClpDualTolerance];
5542 dualTolerance_ *= pow(2.0, numberTimesOptimal_ - 1);
5543 }
5544 cleanDuals = 2; // If nothing changed optimal else primal
5545 #if CLP_CAN_HAVE_ZERO_OBJ
5546 } else {
5547 // no cost - skip checks
5548 problemStatus_ = 0;
5549 }
5550 #endif
5551 } else {
5552 problemStatus_ = 0; // optimal
5553 if (lastCleaned < numberIterations_ && numberChanged_) {
5554 handler_->message(CLP_SIMPLEX_GIVINGUP, messages_)
5555 << CoinMessageEol;
5556 }
5557 }
5558 } else {
5559 cleanDuals = 1;
5560 if (doOriginalTolerance == 1) {
5561 // check unbounded
5562 // find a variable with bad dj
5563 int iSequence;
5564 int iChosen = -1;
5565 if (!inCbc) {
5566 double largest = 100.0 * primalTolerance_;
5567 for (iSequence = 0; iSequence < numberRows_ + numberColumns_;
5568 iSequence++) {
5569 double djValue = dj_[iSequence];
5570 double originalLo = originalLower(iSequence);
5571 double originalUp = originalUpper(iSequence);
5572 if (fabs(djValue) > fabs(largest)) {
5573 if (getStatus(iSequence) != basic) {
5574 if (djValue > 0 && originalLo < -1.0e20) {
5575 if (djValue > fabs(largest)) {
5576 largest = djValue;
5577 iChosen = iSequence;
5578 }
5579 } else if (djValue < 0 && originalUp > 1.0e20) {
5580 if (-djValue > fabs(largest)) {
5581 largest = djValue;
5582 iChosen = iSequence;
5583 }
5584 }
5585 }
5586 }
5587 }
5588 }
5589 if (iChosen >= 0) {
5590 int iSave = sequenceIn_;
5591 sequenceIn_ = iChosen;
5592 unpack(rowArray_[1]);
5593 sequenceIn_ = iSave;
5594 // if dual infeasibilities then must be free vector so add in dual
5595 if (numberDualInfeasibilities_) {
5596 if (fabs(changeCost) > 1.0e-5)
5597 COIN_DETAIL_PRINT(printf("Odd free/unbounded combo\n"));
5598 changeCost += cost_[iChosen];
5599 }
5600 problemStatus_ = checkUnbounded(rowArray_[1], rowArray_[0],
5601 changeCost);
5602 rowArray_[1]->clear();
5603 } else {
5604 problemStatus_ = -3;
5605 }
5606 if (problemStatus_ == 2 && perturbation_ == 101) {
5607 perturbation_ = 102; // stop any perturbations
5608 cleanDuals = 1;
5609 createRim4(false);
5610 progress_.modifyObjective(-COIN_DBL_MAX);
5611 problemStatus_ = -1;
5612 }
5613 if (problemStatus_ == 2) {
5614 // it is unbounded - restore solution
5615 // but first add in changes to non-basic
5616 int iColumn;
5617 double *original = columnArray_[0]->denseVector();
5618 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
5619 if (getColumnStatus(iColumn) != basic)
5620 ray_[iColumn] += saveColumnSolution[iColumn] - original[iColumn];
5621 columnActivityWork_[iColumn] = original[iColumn];
5622 }
5623 CoinMemcpyN(saveRowSolution, numberRows_,
5624 rowActivityWork_);
5625 }
5626 } else {
5627 doOriginalTolerance = 2;
5628 rowArray_[0]->clear();
5629 }
5630 }
5631 delete[] saveColumnSolution;
5632 delete[] saveRowSolution;
5633 }
5634 if (problemStatus_ == -4 || problemStatus_ == -5) {
5635 // may be infeasible - or may be bounds are wrong
5636 numberChangedBounds = changeBounds(0, NULL, changeCost);
5637 needCleanFake = true;
5638 /* Should this be here as makes no difference to being feasible.
5639 But seems to make a difference to run times. */
5640 if (perturbation_ == 101 && 0) {
5641 perturbation_ = 102; // stop any perturbations
5642 cleanDuals = 1;
5643 numberChangedBounds = 1;
5644 // make sure fake bounds are back
5645 changeBounds(1, NULL, changeCost);
5646 needCleanFake = true;
5647 createRim4(false);
5648 progress_.modifyObjective(-COIN_DBL_MAX);
5649 }
5650 if ((numberChangedBounds <= 0 || dualBound_ > 1.0e20 || (largestPrimalError_ > 1.0 && dualBound_ > 1.0e17)) && (numberPivots < 4 || sumPrimalInfeasibilities_ > 1.0e-6)) {
5651 problemStatus_ = 1; // infeasible
5652 if (perturbation_ == 101) {
5653 perturbation_ = 102; // stop any perturbations
5654 //cleanDuals=1;
5655 //numberChangedBounds=1;
5656 //createRim4(false);
5657 }
5658 // but double check
5659 if (!numberPrimalInfeasibilities_) {
5660 problemStatus_ = -1;
5661 doOriginalTolerance = 2;
5662 }
5663 } else {
5664 problemStatus_ = -1; //iterate
5665 cleanDuals = 1;
5666 if (numberChangedBounds <= 0)
5667 doOriginalTolerance = 2;
5668 // and delete ray which has been created
5669 delete[] ray_;
5670 ray_ = NULL;
5671 }
5672 }
5673 } else {
5674 cleanDuals = 1;
5675 }
5676 if (problemStatus_ < 0) {
5677 if (doOriginalTolerance == 2) {
5678 // put back original tolerance
5679 lastCleaned = numberIterations_;
5680 numberChanged_ = 0; // Number of variables with changed costs
5681 handler_->message(CLP_DUAL_ORIGINAL, messages_)
5682 << CoinMessageEol;
5683 perturbation_ = 102; // stop any perturbations
5684 #if 0
5685 double * xcost = new double[numberRows_+numberColumns_];
5686 double * xlower = new double[numberRows_+numberColumns_];
5687 double * xupper = new double[numberRows_+numberColumns_];
5688 double * xdj = new double[numberRows_+numberColumns_];
5689 double * xsolution = new double[numberRows_+numberColumns_];
5690 CoinMemcpyN(cost_, (numberRows_ + numberColumns_), xcost);
5691 CoinMemcpyN(lower_, (numberRows_ + numberColumns_), xlower);
5692 CoinMemcpyN(upper_, (numberRows_ + numberColumns_), xupper);
5693 CoinMemcpyN(dj_, (numberRows_ + numberColumns_), xdj);
5694 CoinMemcpyN(solution_, (numberRows_ + numberColumns_), xsolution);
5695 #endif
5696 createRim4(false);
5697 progress_.modifyObjective(-COIN_DBL_MAX);
5698 // make sure duals are current
5699 computeDuals(givenDuals);
5700 checkDualSolution();
5701 #if 0
5702 int i;
5703 for (i = 0; i < numberRows_ + numberColumns_; i++) {
5704 if (cost_[i] != xcost[i])
5705 printf("** %d old cost %g new %g sol %g\n",
5706 i, xcost[i], cost_[i], solution_[i]);
5707 if (lower_[i] != xlower[i])
5708 printf("** %d old lower %g new %g sol %g\n",
5709 i, xlower[i], lower_[i], solution_[i]);
5710 if (upper_[i] != xupper[i])
5711 printf("** %d old upper %g new %g sol %g\n",
5712 i, xupper[i], upper_[i], solution_[i]);
5713 if (dj_[i] != xdj[i])
5714 printf("** %d old dj %g new %g sol %g\n",
5715 i, xdj[i], dj_[i], solution_[i]);
5716 if (solution_[i] != xsolution[i])
5717 printf("** %d old solution %g new %g sol %g\n",
5718 i, xsolution[i], solution_[i], solution_[i]);
5719 }
5720 //delete [] xcost;
5721 //delete [] xupper;
5722 //delete [] xlower;
5723 //delete [] xdj;
5724 //delete [] xsolution;
5725 #endif
5726 // put back bounds as they were if was optimal
5727 if (doOriginalTolerance == 2 && cleanDuals != 2) {
5728 changeMade_++; // say something changed
5729 /* We may have already changed some bounds in this function
5730 so save numberFake_ and add in.
5731
5732 Worst that can happen is that we waste a bit of time - but it must be finite.
5733 */
5734 //int saveNumberFake = numberFake_;
5735 //resetFakeBounds(-1);
5736 changeBounds(3, NULL, changeCost);
5737 needCleanFake = true;
5738 //numberFake_ += saveNumberFake;
5739 //resetFakeBounds(-1);
5740 cleanDuals = 2;
5741 //cleanDuals=1;
5742 }
5743 #if 0
5744 //int i;
5745 for (i = 0; i < numberRows_ + numberColumns_; i++) {
5746 if (cost_[i] != xcost[i])
5747 printf("** %d old cost %g new %g sol %g\n",
5748 i, xcost[i], cost_[i], solution_[i]);
5749 if (lower_[i] != xlower[i])
5750 printf("** %d old lower %g new %g sol %g\n",
5751 i, xlower[i], lower_[i], solution_[i]);
5752 if (upper_[i] != xupper[i])
5753 printf("** %d old upper %g new %g sol %g\n",
5754 i, xupper[i], upper_[i], solution_[i]);
5755 if (dj_[i] != xdj[i])
5756 printf("** %d old dj %g new %g sol %g\n",
5757 i, xdj[i], dj_[i], solution_[i]);
5758 if (solution_[i] != xsolution[i])
5759 printf("** %d old solution %g new %g sol %g\n",
5760 i, xsolution[i], solution_[i], solution_[i]);
5761 }
5762 delete [] xcost;
5763 delete [] xupper;
5764 delete [] xlower;
5765 delete [] xdj;
5766 delete [] xsolution;
5767 #endif
5768 }
5769 if (cleanDuals == 1 || (cleanDuals == 2 && !numberDualInfeasibilities_)) {
5770 // make sure dual feasible
5771 // look at all rows and columns
5772 rowArray_[0]->clear();
5773 columnArray_[0]->clear();
5774 double objectiveChange = 0.0;
5775 double savePrimalInfeasibilities = sumPrimalInfeasibilities_;
5776 if (!numberIterations_) {
5777 int nTotal = numberRows_ + numberColumns_;
5778 if (arraysNotCreated) {
5779 // create save arrays
5780 delete[] saveStatus_;
5781 delete[] savedSolution_;
5782 saveStatus_ = new unsigned char[nTotal];
5783 savedSolution_ = new double[nTotal];
5784 arraysNotCreated = false;
5785 }
5786 // save arrays
5787 CoinMemcpyN(status_, nTotal, saveStatus_);
5788 CoinMemcpyN(rowActivityWork_,
5789 numberRows_, savedSolution_ + numberColumns_);
5790 CoinMemcpyN(columnActivityWork_, numberColumns_, savedSolution_);
5791 }
5792 #if 0
5793 double * xcost = new double[numberRows_+numberColumns_];
5794 double * xlower = new double[numberRows_+numberColumns_];
5795 double * xupper = new double[numberRows_+numberColumns_];
5796 double * xdj = new double[numberRows_+numberColumns_];
5797 double * xsolution = new double[numberRows_+numberColumns_];
5798 CoinMemcpyN(cost_, (numberRows_ + numberColumns_), xcost);
5799 CoinMemcpyN(lower_, (numberRows_ + numberColumns_), xlower);
5800 CoinMemcpyN(upper_, (numberRows_ + numberColumns_), xupper);
5801 CoinMemcpyN(dj_, (numberRows_ + numberColumns_), xdj);
5802 CoinMemcpyN(solution_, (numberRows_ + numberColumns_), xsolution);
5803 #endif
5804 if (givenDuals)
5805 dualTolerance_ = 1.0e50;
5806 #if CLP_CAN_HAVE_ZERO_OBJ > 1
5807 if ((specialOptions_ & 16777216) == 0) {
5808 #endif
5809 updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1],
5810 0.0, objectiveChange, true);
5811 #if CLP_CAN_HAVE_ZERO_OBJ > 1
5812 } else {
5813 rowArray_[0]->clear();
5814 rowArray_[1]->clear();
5815 columnArray_[0]->clear();
5816 }
5817 #endif
5818 dualTolerance_ = saveTolerance;
5819 #if 0
5820 int i;
5821 for (i = 0; i < numberRows_ + numberColumns_; i++) {
5822 if (cost_[i] != xcost[i])
5823 printf("** %d old cost %g new %g sol %g\n",
5824 i, xcost[i], cost_[i], solution_[i]);
5825 if (lower_[i] != xlower[i])
5826 printf("** %d old lower %g new %g sol %g\n",
5827 i, xlower[i], lower_[i], solution_[i]);
5828 if (upper_[i] != xupper[i])
5829 printf("** %d old upper %g new %g sol %g\n",
5830 i, xupper[i], upper_[i], solution_[i]);
5831 if (dj_[i] != xdj[i])
5832 printf("** %d old dj %g new %g sol %g\n",
5833 i, xdj[i], dj_[i], solution_[i]);
5834 if (solution_[i] != xsolution[i])
5835 printf("** %d old solution %g new %g sol %g\n",
5836 i, xsolution[i], solution_[i], solution_[i]);
5837 }
5838 delete [] xcost;
5839 delete [] xupper;
5840 delete [] xlower;
5841 delete [] xdj;
5842 delete [] xsolution;
5843 #endif
5844 // for now - recompute all
5845 gutsOfSolution(NULL, NULL);
5846 if (givenDuals)
5847 dualTolerance_ = 1.0e50;
5848 #if CLP_CAN_HAVE_ZERO_OBJ > 1
5849 if ((specialOptions_ & 16777216) == 0) {
5850 #endif
5851 updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1],
5852 0.0, objectiveChange, true);
5853 #if CLP_CAN_HAVE_ZERO_OBJ > 1
5854 } else {
5855 rowArray_[0]->clear();
5856 rowArray_[1]->clear();
5857 columnArray_[0]->clear();
5858 }
5859 #endif
5860 dualTolerance_ = saveTolerance;
5861 if (!numberIterations_ && sumPrimalInfeasibilities_ > 1.0e5 * (savePrimalInfeasibilities + 1.0e3) && (moreSpecialOptions_ & (256 | 8192)) == 0) {
5862 // Use primal
5863 int nTotal = numberRows_ + numberColumns_;
5864 CoinMemcpyN(saveStatus_, nTotal, status_);
5865 CoinMemcpyN(savedSolution_ + numberColumns_,
5866 numberRows_, rowActivityWork_);
5867 CoinMemcpyN(savedSolution_,
5868 numberColumns_, columnActivityWork_);
5869 problemStatus_ = 10;
5870 situationChanged = 0;
5871 }
5872 //assert(numberDualInfeasibilitiesWithoutFree_==0);
5873 if (numberDualInfeasibilities_) {
5874 if ((numberPrimalInfeasibilities_ || numberPivots)
5875 && problemStatus_ != 10) {
5876 problemStatus_ = -1; // carry on as normal
5877 } else {
5878 problemStatus_ = 10; // try primal
5879 #if COIN_DEVELOP > 1
5880 printf("returning at %d\n", __LINE__);
5881 #endif
5882 }
5883 } else if (situationChanged == 2) {
5884 problemStatus_ = -1; // carry on as normal
5885 // need to reset bounds
5886 changeBounds(3, NULL, changeCost);
5887 }
5888 situationChanged = 0;
5889 } else {
5890 // iterate
5891 if (cleanDuals != 2) {
5892 problemStatus_ = -1;
5893 } else {
5894 problemStatus_ = 10; // try primal
5895 #if COIN_DEVELOP > 2
5896 printf("returning at %d\n", __LINE__);
5897 #endif
5898 }
5899 }
5900 }
5901 }
5902 // unflag all variables (we may want to wait a bit?)
5903 if ((tentativeStatus != -2 && tentativeStatus != -1) && unflagVariables) {
5904 int iRow;
5905 int numberFlagged = 0;
5906 for (iRow = 0; iRow < numberRows_; iRow++) {
5907 int iPivot = pivotVariable_[iRow];
5908 if (flagged(iPivot)) {
5909 numberFlagged++;
5910 clearFlagged(iPivot);
5911 }
5912 }
5913 #ifdef COIN_DEVELOP
5914 if (numberFlagged) {
5915 printf("unflagging %d variables - tentativeStatus %d probStat %d ninf %d nopt %d\n", numberFlagged, tentativeStatus,
5916 problemStatus_, numberPrimalInfeasibilities_,
5917 numberTimesOptimal_);
5918 }
5919 #endif
5920 unflagVariables = numberFlagged > 0;
5921 if (numberFlagged && !numberPivots) {
5922 /* looks like trouble as we have not done any iterations.
5923 Try changing pivot tolerance then give it a few goes and give up */
5924 if (factorization_->pivotTolerance() < 0.9) {
5925 factorization_->pivotTolerance(0.99);
5926 problemStatus_ = -1;
5927 } else if (numberTimesOptimal_ < 3) {
5928 numberTimesOptimal_++;
5929 problemStatus_ = -1;
5930 } else {
5931 unflagVariables = false;
5932 //secondaryStatus_ = 1; // and say probably infeasible
5933 if ((moreSpecialOptions_ & 256) == 0) {
5934 // try primal
5935 problemStatus_ = 10;
5936 } else {
5937 // almost certainly infeasible
5938 problemStatus_ = 1;
5939 }
5940 #if COIN_DEVELOP > 1
5941 printf("returning at %d\n", __LINE__);
5942 #endif
5943 }
5944 }
5945 }
5946 if (problemStatus_ < 0) {
5947 if (needCleanFake) {
5948 double dummyChangeCost = 0.0;
5949 changeBounds(3, NULL, dummyChangeCost);
5950 }
5951 #if 0
5952 if (objectiveValue_ < lastObjectiveValue_ - 1.0e-8 *
5953 CoinMax(fabs(objectivevalue_), fabs(lastObjectiveValue_))) {
5954 } else {
5955 lastObjectiveValue_ = objectiveValue_;
5956 }
5957 #endif
5958 if (type == 0 || type == 1) {
5959 if (!type && arraysNotCreated) {
5960 // create save arrays
5961 delete[] saveStatus_;
5962 delete[] savedSolution_;
5963 saveStatus_ = new unsigned char[numberRows_ + numberColumns_];
5964 savedSolution_ = new double[numberRows_ + numberColumns_];
5965 }
5966 // save arrays
5967 CoinMemcpyN(status_, numberColumns_ + numberRows_, saveStatus_);
5968 CoinMemcpyN(rowActivityWork_,
5969 numberRows_, savedSolution_ + numberColumns_);
5970 CoinMemcpyN(columnActivityWork_, numberColumns_, savedSolution_);
5971 // save extra stuff
5972 int dummy;
5973 matrix_->generalExpanded(this, 5, dummy);
5974 }
5975 if (weightsSaved) {
5976 // restore weights (if saved) - also recompute infeasibility list
5977 if (!reallyBadProblems && (largestPrimalError_ < 100.0 || numberPivots > 10)) {
5978 if (tentativeStatus > -3)
5979 dualRowPivot_->saveWeights(this, (type < 2) ? 2 : 4);
5980 else
5981 dualRowPivot_->saveWeights(this, 3);
5982 } else {
5983 // reset weights or scale back
5984 dualRowPivot_->saveWeights(this, 6);
5985 }
5986 } else if (weightsSaved2 && numberPrimalInfeasibilities_) {
5987 dualRowPivot_->saveWeights(this, 3);
5988 }
5989 }
5990 // see if cutoff reached
5991 double limit = 0.0;
5992 getDblParam(ClpDualObjectiveLimit, limit);
5993 #if 0
5994 if(fabs(limit) < 1.0e30 && objectiveValue()*optimizationDirection_ >
5995 limit + 100.0) {
5996 printf("lim %g obj %g %g - wo perturb %g sum dual %g\n",
5997 limit, objectiveValue_, objectiveValue(), computeInternalObjectiveValue(), sumDualInfeasibilities_);
5998 }
5999 #endif
6000 if (fabs(limit) < 1.0e30 && objectiveValue() * optimizationDirection_ > limit && !numberAtFakeBound()) {
6001 bool looksInfeasible = !numberDualInfeasibilities_;
6002 if (objectiveValue() * optimizationDirection_ > limit + fabs(0.1 * limit) + 1.0e2 * sumDualInfeasibilities_ + 1.0e4 && sumDualInfeasibilities_ < largestDualError_ && numberIterations_ > 0.5 * numberRows_ + 1000)
6003 looksInfeasible = true;
6004 if (looksInfeasible) {
6005 // Even if not perturbed internal costs may have changed
6006 // be careful
6007 if (true || numberIterations_) {
6008 if (computeInternalObjectiveValue() > limit) {
6009 problemStatus_ = 1;
6010 secondaryStatus_ = 1; // and say was on cutoff
6011 }
6012 } else {
6013 problemStatus_ = 1;
6014 secondaryStatus_ = 1; // and say was on cutoff
6015 }
6016 }
6017 }
6018 // If we are in trouble and in branch and bound give up
6019 if ((specialOptions_ & 1024) != 0) {
6020 int looksBad = 0;
6021 if (largestPrimalError_ * largestDualError_ > 1.0e2) {
6022 looksBad = 1;
6023 } else if (largestPrimalError_ > 1.0e-2
6024 && objectiveValue_ > CoinMin(1.0e15, 1.0e3 * limit)) {
6025 looksBad = 2;
6026 }
6027 if (looksBad) {
6028 if (factorization_->pivotTolerance() < 0.9) {
6029 // up tolerance
6030 factorization_->pivotTolerance(CoinMin(factorization_->pivotTolerance() * 1.05 + 0.02, 0.91));
6031 } else if (numberIterations_ > 10000) {
6032 if (handler_->logLevel() > 2)
6033 printf("bad dual - saying infeasible %d\n", looksBad);
6034 problemStatus_ = 1;
6035 secondaryStatus_ = 1; // and say was on cutoff
6036 } else if (largestPrimalError_ > 1.0e5) {
6037 {
6038 //int iBigB = -1;
6039 double bigB = 0.0;
6040 //int iBigN = -1;
6041 double bigN = 0.0;
6042 for (int i = 0; i < numberRows_ + numberColumns_; i++) {
6043 double value = fabs(solution_[i]);
6044 if (getStatus(i) == basic) {
6045 if (value > bigB) {
6046 bigB = value;
6047 //iBigB = i;
6048 }
6049 } else {
6050 if (value > bigN) {
6051 bigN = value;
6052 //iBigN = i;
6053 }
6054 }
6055 }
6056 #ifdef CLP_INVESTIGATE
6057 if (bigB > 1.0e8 || bigN > 1.0e8) {
6058 if (handler_->logLevel() > 0)
6059 printf("it %d - basic %d %g, nonbasic %d %g\n",
6060 numberIterations_, iBigB, bigB, iBigN, bigN);
6061 }
6062 #endif
6063 }
6064 #if COIN_DEVELOP != 2
6065 if (handler_->logLevel() > 2)
6066 #endif
6067 printf("bad dual - going to primal %d %g\n", looksBad, largestPrimalError_);
6068 allSlackBasis(true);
6069 problemStatus_ = 10;
6070 }
6071 }
6072 }
6073 if (problemStatus_ < 0 && !changeMade_) {
6074 problemStatus_ = 4; // unknown
6075 }
6076 lastGoodIteration_ = numberIterations_;
6077 if (numberIterations_ > lastBadIteration_ + 100)
6078 moreSpecialOptions_ &= ~16; // clear check accuracy flag
6079 if (problemStatus_ < 0) {
6080 sumDualInfeasibilities_ = realDualInfeasibilities; // back to say be careful
6081 if (sumDualInfeasibilities_)
6082 numberDualInfeasibilities_ = 1;
6083 }
6084 #ifdef CLP_REPORT_PROGRESS
6085 if (ixxxxxx > ixxyyyy - 3) {
6086 printf("objectiveValue_ %g\n", objectiveValue_);
6087 handler_->setLogLevel(63);
6088 int nTotal = numberColumns_ + numberRows_;
6089 double newObj = 0.0;
6090 for (int i = 0; i < nTotal; i++) {
6091 if (solution_[i])
6092 newObj += solution_[i] * cost_[i];
6093 }
6094 printf("xxx obj %g\n", newObj);
6095 // for now - recompute all
6096 gutsOfSolution(NULL, NULL);
6097 newObj = 0.0;
6098 for (int i = 0; i < nTotal; i++) {
6099 if (solution_[i])
6100 newObj += solution_[i] * cost_[i];
6101 }
6102 printf("yyy obj %g %g\n", newObj, objectiveValue_);
6103 progress_.modifyObjective(objectiveValue_
6104 - bestPossibleImprovement_);
6105 }
6106 #endif
6107 #if 1
6108 double thisObj = progress_.lastObjective(0);
6109 double lastObj = progress_.lastObjective(1);
6110 if (lastObj > thisObj + 1.0e-4 * CoinMax(fabs(thisObj), fabs(lastObj)) + 1.0e-4
6111 && givenDuals == NULL && firstFree_ < 0) {
6112 int maxFactor = factorization_->maximumPivots();
6113 if (maxFactor > 10) {
6114 if (forceFactorization_ < 0)
6115 forceFactorization_ = maxFactor;
6116 forceFactorization_ = CoinMax(1, (forceFactorization_ >> 1));
6117 //printf("Reducing factorization frequency\n");
6118 }
6119 }
6120 #endif
6121 // Allow matrices to be sorted etc
6122 int fake = -999; // signal sort
6123 matrix_->correctSequence(this, fake, fake);
6124 if (alphaAccuracy_ > 0.0)
6125 alphaAccuracy_ = 1.0;
6126 // If we are stopping - use plausible objective
6127 // Maybe only in fast dual
6128 if (problemStatus_ > 2)
6129 objectiveValue_ = approximateObjective;
6130 if (problemStatus_ == 1 && (progressFlag_ & 8) != 0 && fabs(objectiveValue_) > 1.0e10)
6131 problemStatus_ = 10; // infeasible - but has looked feasible
6132 }
6133 /* While updateDualsInDual sees what effect is of flip
6134 this does actual flipping.
6135 If change >0.0 then value in array >0.0 => from lower to upper
6136 */
flipBounds(CoinIndexedVector * rowArray,CoinIndexedVector * columnArray)6137 void ClpSimplexDual::flipBounds(CoinIndexedVector *rowArray,
6138 CoinIndexedVector *columnArray)
6139 {
6140 int number;
6141 int *which;
6142
6143 int iSection;
6144
6145 for (iSection = 0; iSection < 2; iSection++) {
6146 int i;
6147 double *solution = solutionRegion(iSection);
6148 double *lower = lowerRegion(iSection);
6149 double *upper = upperRegion(iSection);
6150 int addSequence;
6151 if (!iSection) {
6152 number = rowArray->getNumElements();
6153 which = rowArray->getIndices();
6154 addSequence = numberColumns_;
6155 } else {
6156 number = columnArray->getNumElements();
6157 which = columnArray->getIndices();
6158 addSequence = 0;
6159 }
6160
6161 for (i = 0; i < number; i++) {
6162 int iSequence = which[i];
6163 Status status = getStatus(iSequence + addSequence);
6164
6165 switch (status) {
6166
6167 case basic:
6168 case isFree:
6169 case superBasic:
6170 case ClpSimplex::isFixed:
6171 break;
6172 case atUpperBound:
6173 // to lower bound
6174 setStatus(iSequence + addSequence, atLowerBound);
6175 solution[iSequence] = lower[iSequence];
6176 // correct in vector copy
6177 iSequence += addSequence;
6178 matrix_->correctSequence(this, iSequence, iSequence);
6179 break;
6180 case atLowerBound:
6181 // to upper bound
6182 setStatus(iSequence + addSequence, atUpperBound);
6183 solution[iSequence] = upper[iSequence];
6184 // correct in vector copy
6185 iSequence += addSequence;
6186 matrix_->correctSequence(this, iSequence, iSequence);
6187 break;
6188 }
6189 }
6190 }
6191 rowArray->setNumElements(0);
6192 columnArray->setNumElements(0);
6193 }
6194 // Restores bound to original bound
originalBound(int iSequence)6195 void ClpSimplexDual::originalBound(int iSequence)
6196 {
6197 if (getFakeBound(iSequence) != noFake) {
6198 numberFake_--;
6199 setFakeBound(iSequence, noFake);
6200 if (iSequence >= numberColumns_) {
6201 // rows
6202 int iRow = iSequence - numberColumns_;
6203 rowLowerWork_[iRow] = rowLower_[iRow];
6204 rowUpperWork_[iRow] = rowUpper_[iRow];
6205 if (rowScale_) {
6206 if (rowLowerWork_[iRow] > -1.0e50)
6207 rowLowerWork_[iRow] *= rowScale_[iRow] * rhsScale_;
6208 if (rowUpperWork_[iRow] < 1.0e50)
6209 rowUpperWork_[iRow] *= rowScale_[iRow] * rhsScale_;
6210 } else if (rhsScale_ != 1.0) {
6211 if (rowLowerWork_[iRow] > -1.0e50)
6212 rowLowerWork_[iRow] *= rhsScale_;
6213 if (rowUpperWork_[iRow] < 1.0e50)
6214 rowUpperWork_[iRow] *= rhsScale_;
6215 }
6216 } else {
6217 // columns
6218 columnLowerWork_[iSequence] = columnLower_[iSequence];
6219 columnUpperWork_[iSequence] = columnUpper_[iSequence];
6220 if (rowScale_) {
6221 double multiplier = 1.0 * inverseColumnScale_[iSequence];
6222 if (columnLowerWork_[iSequence] > -1.0e50)
6223 columnLowerWork_[iSequence] *= multiplier * rhsScale_;
6224 if (columnUpperWork_[iSequence] < 1.0e50)
6225 columnUpperWork_[iSequence] *= multiplier * rhsScale_;
6226 } else if (rhsScale_ != 1.0) {
6227 if (columnLowerWork_[iSequence] > -1.0e50)
6228 columnLowerWork_[iSequence] *= rhsScale_;
6229 if (columnUpperWork_[iSequence] < 1.0e50)
6230 columnUpperWork_[iSequence] *= rhsScale_;
6231 }
6232 }
6233 }
6234 }
6235 /* As changeBounds but just changes new bounds for a single variable.
6236 Returns true if change */
changeBound(int iSequence)6237 bool ClpSimplexDual::changeBound(int iSequence)
6238 {
6239 // old values
6240 double oldLower = lower_[iSequence];
6241 double oldUpper = upper_[iSequence];
6242 double value = solution_[iSequence];
6243 bool modified = false;
6244 originalBound(iSequence);
6245 // original values
6246 double lowerValue = lower_[iSequence];
6247 double upperValue = upper_[iSequence];
6248 // back to altered values
6249 lower_[iSequence] = oldLower;
6250 upper_[iSequence] = oldUpper;
6251 assert(getFakeBound(iSequence) == noFake);
6252 //if (getFakeBound(iSequence)!=noFake)
6253 //numberFake_--;;
6254 if (value == oldLower) {
6255 if (upperValue > oldLower + dualBound_) {
6256 upper_[iSequence] = oldLower + dualBound_;
6257 setFakeBound(iSequence, upperFake);
6258 modified = true;
6259 numberFake_++;
6260 }
6261 } else if (value == oldUpper) {
6262 if (lowerValue < oldUpper - dualBound_) {
6263 lower_[iSequence] = oldUpper - dualBound_;
6264 setFakeBound(iSequence, lowerFake);
6265 modified = true;
6266 numberFake_++;
6267 }
6268 } else {
6269 assert(value == oldLower || value == oldUpper);
6270 }
6271 return modified;
6272 }
6273 #if ABC_NORMAL_DEBUG > 0
6274 //#define PERT_STATISTICS
6275 #endif
6276 #ifdef PERT_STATISTICS
breakdown(const char * name,int numberLook,const double * region)6277 static void breakdown(const char *name, int numberLook, const double *region)
6278 {
6279 double range[] = {
6280 -COIN_DBL_MAX,
6281 -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, -1.0e2, -1.0e1,
6282 -1.0,
6283 -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15,
6284 0.0,
6285 1.0e-15, 1.0e-11, 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1,
6286 1.0,
6287 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, 1.0e15,
6288 COIN_DBL_MAX
6289 };
6290 int nRanges = static_cast< int >(sizeof(range) / sizeof(double));
6291 int *number = new int[nRanges];
6292 memset(number, 0, nRanges * sizeof(int));
6293 int *numberExact = new int[nRanges];
6294 memset(numberExact, 0, nRanges * sizeof(int));
6295 int i;
6296 for (i = 0; i < numberLook; i++) {
6297 double value = region[i];
6298 for (int j = 0; j < nRanges; j++) {
6299 if (value == range[j]) {
6300 numberExact[j]++;
6301 break;
6302 } else if (value < range[j]) {
6303 number[j]++;
6304 break;
6305 }
6306 }
6307 }
6308 printf("\n%s has %d entries\n", name, numberLook);
6309 for (i = 0; i < nRanges; i++) {
6310 if (number[i])
6311 printf("%d between %g and %g", number[i], range[i - 1], range[i]);
6312 if (numberExact[i]) {
6313 if (number[i])
6314 printf(", ");
6315 printf("%d exactly at %g", numberExact[i], range[i]);
6316 }
6317 if (number[i] + numberExact[i])
6318 printf("\n");
6319 }
6320 delete[] number;
6321 delete[] numberExact;
6322 }
6323 #endif
6324 // Perturbs problem
perturb()6325 int ClpSimplexDual::perturb()
6326 {
6327 if (perturbation_ > 100)
6328 return 0; //perturbed already
6329 if (perturbation_ == 100)
6330 perturbation_ = 50; // treat as normal
6331 int savePerturbation = perturbation_;
6332 bool modifyRowCosts = false;
6333 // dual perturbation
6334 double perturbation = 1.0e-20;
6335 // maximum fraction of cost to perturb
6336 double maximumFraction = 1.0e-5;
6337 double constantPerturbation = 100.0 * dualTolerance_;
6338 int maxLength = 0;
6339 int minLength = numberRows_;
6340 double averageCost = 0.0;
6341 #if 0
6342 // look at element range
6343 double smallestNegative;
6344 double largestNegative;
6345 double smallestPositive;
6346 double largestPositive;
6347 matrix_->rangeOfElements(smallestNegative, largestNegative,
6348 smallestPositive, largestPositive);
6349 smallestPositive = CoinMin(fabs(smallestNegative), smallestPositive);
6350 largestPositive = CoinMax(fabs(largestNegative), largestPositive);
6351 double elementRatio = largestPositive / smallestPositive;
6352 #endif
6353 int numberNonZero = 0;
6354 if (!numberIterations_ && perturbation_ >= 50) {
6355 // See if we need to perturb
6356 double *sort = new double[numberColumns_];
6357 // Use objective BEFORE scaling
6358 const double *obj = ((moreSpecialOptions_ & 128) == 0) ? objective() : cost_;
6359 int i;
6360 for (i = 0; i < numberColumns_; i++) {
6361 double value = fabs(obj[i]);
6362 sort[i] = value;
6363 averageCost += value;
6364 if (value)
6365 numberNonZero++;
6366 }
6367 if (numberNonZero)
6368 averageCost /= static_cast< double >(numberNonZero);
6369 else
6370 averageCost = 1.0;
6371 std::sort(sort, sort + numberColumns_);
6372 int number = 1;
6373 double last = sort[0];
6374 for (i = 1; i < numberColumns_; i++) {
6375 if (last != sort[i])
6376 number++;
6377 last = sort[i];
6378 }
6379 delete[] sort;
6380 if (!numberNonZero && perturbation_ < 55)
6381 return 1; // safer to use primal
6382 #if 0
6383 printf("nnz %d percent %d", number, (number * 100) / numberColumns_);
6384 if (number * 4 > numberColumns_)
6385 printf(" - Would not perturb\n");
6386 else
6387 printf(" - Would perturb\n");
6388 //exit(0);
6389 #endif
6390 //printf("ratio number diff costs %g, element ratio %g\n",((double)number)/((double) numberColumns_),
6391 // elementRatio);
6392 //number=0;
6393 //if (number*4>numberColumns_||elementRatio>1.0e12) {
6394 if (number * 4 > numberColumns_) {
6395 perturbation_ = 100;
6396 return 0; // good enough
6397 }
6398 }
6399 int iColumn;
6400 const int *columnLength = matrix_->getVectorLengths();
6401 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
6402 if (columnLowerWork_[iColumn] < columnUpperWork_[iColumn]) {
6403 int length = columnLength[iColumn];
6404 if (length > 2) {
6405 maxLength = CoinMax(maxLength, length);
6406 minLength = CoinMin(minLength, length);
6407 }
6408 }
6409 }
6410 // If > 70 then do rows
6411 if (perturbation_ >= 70) {
6412 modifyRowCosts = true;
6413 perturbation_ -= 20;
6414 printf("Row costs modified, ");
6415 }
6416 bool uniformChange = false;
6417 bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0;
6418 if (perturbation_ > 50) {
6419 // Experiment
6420 // maximumFraction could be 1.0e-10 to 1.0
6421 double m[] = { 1.0e-10, 1.0e-9, 1.0e-8, 1.0e-7, 1.0e-6, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1, 1.0 };
6422 int whichOne = perturbation_ - 51;
6423 //if (inCbcOrOther&&whichOne>0)
6424 //whichOne--;
6425 maximumFraction = m[CoinMin(whichOne, 10)];
6426 } else if (inCbcOrOther) {
6427 //maximumFraction = 1.0e-6;
6428 }
6429 int iRow;
6430 double smallestNonZero = 1.0e100;
6431 numberNonZero = 0;
6432 if (perturbation_ >= 50) {
6433 perturbation = 1.0e-8;
6434 if (perturbation_ > 50 && perturbation_ < 60)
6435 perturbation = CoinMax(1.0e-8, maximumFraction);
6436 bool allSame = true;
6437 double lastValue = 0.0;
6438 for (iRow = 0; iRow < numberRows_; iRow++) {
6439 double lo = rowLowerWork_[iRow];
6440 double up = rowUpperWork_[iRow];
6441 if (lo < up) {
6442 double value = fabs(rowObjectiveWork_[iRow]);
6443 perturbation = CoinMax(perturbation, value);
6444 if (value) {
6445 modifyRowCosts = true;
6446 smallestNonZero = CoinMin(smallestNonZero, value);
6447 }
6448 }
6449 if (lo && lo > -1.0e10) {
6450 numberNonZero++;
6451 lo = fabs(lo);
6452 if (!lastValue)
6453 lastValue = lo;
6454 else if (fabs(lo - lastValue) > 1.0e-7)
6455 allSame = false;
6456 }
6457 if (up && up < 1.0e10) {
6458 numberNonZero++;
6459 up = fabs(up);
6460 if (!lastValue)
6461 lastValue = up;
6462 else if (fabs(up - lastValue) > 1.0e-7)
6463 allSame = false;
6464 }
6465 }
6466 double lastValue2 = 0.0;
6467 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
6468 double lo = columnLowerWork_[iColumn];
6469 double up = columnUpperWork_[iColumn];
6470 if (lo < up) {
6471 double value = fabs(objectiveWork_[iColumn]);
6472 perturbation = CoinMax(perturbation, value);
6473 if (value) {
6474 smallestNonZero = CoinMin(smallestNonZero, value);
6475 }
6476 }
6477 if (lo && lo > -1.0e10) {
6478 //numberNonZero++;
6479 lo = fabs(lo);
6480 if (!lastValue2)
6481 lastValue2 = lo;
6482 else if (fabs(lo - lastValue2) > 1.0e-7)
6483 allSame = false;
6484 }
6485 if (up && up < 1.0e10) {
6486 //numberNonZero++;
6487 up = fabs(up);
6488 if (!lastValue2)
6489 lastValue2 = up;
6490 else if (fabs(up - lastValue2) > 1.0e-7)
6491 allSame = false;
6492 }
6493 }
6494 if (allSame) {
6495 // Check elements
6496 double smallestNegative;
6497 double largestNegative;
6498 double smallestPositive;
6499 double largestPositive;
6500 matrix_->rangeOfElements(smallestNegative, largestNegative,
6501 smallestPositive, largestPositive);
6502 if (smallestNegative == largestNegative && smallestPositive == largestPositive) {
6503 // Really hit perturbation
6504 double adjust = CoinMin(100.0 * maximumFraction, 1.0e-3 * CoinMax(lastValue, lastValue2));
6505 maximumFraction = CoinMax(adjust, maximumFraction);
6506 }
6507 }
6508 perturbation = CoinMin(perturbation, smallestNonZero / maximumFraction);
6509 } else {
6510 // user is in charge
6511 maximumFraction = 1.0e-1;
6512 // but some experiments
6513 if (perturbation_ <= -900) {
6514 modifyRowCosts = true;
6515 perturbation_ += 1000;
6516 printf("Row costs modified, ");
6517 }
6518 if (perturbation_ <= -10) {
6519 perturbation_ += 10;
6520 maximumFraction = 1.0;
6521 if ((-perturbation_) % 100 >= 10) {
6522 uniformChange = true;
6523 perturbation_ += 20;
6524 }
6525 while (perturbation_ < -10) {
6526 perturbation_ += 100;
6527 maximumFraction *= 1.0e-1;
6528 }
6529 }
6530 perturbation = pow(10.0, perturbation_);
6531 }
6532 double largestZero = 0.0;
6533 double largest = 0.0;
6534 double largestPerCent = 0.0;
6535 // modify costs
6536 bool printOut = (handler_->logLevel() == 63);
6537 printOut = false;
6538 //assert (!modifyRowCosts);
6539 modifyRowCosts = false;
6540 if (modifyRowCosts) {
6541 for (iRow = 0; iRow < numberRows_; iRow++) {
6542 if (rowLowerWork_[iRow] < rowUpperWork_[iRow]) {
6543 double value = perturbation;
6544 double currentValue = rowObjectiveWork_[iRow];
6545 value = CoinMin(value, maximumFraction * (fabs(currentValue) + 1.0e-1 * perturbation + 1.0e-3));
6546 if (rowLowerWork_[iRow] > -largeValue_) {
6547 if (fabs(rowLowerWork_[iRow]) < fabs(rowUpperWork_[iRow]))
6548 value *= randomNumberGenerator_.randomDouble();
6549 else
6550 value *= -randomNumberGenerator_.randomDouble();
6551 } else if (rowUpperWork_[iRow] < largeValue_) {
6552 value *= -randomNumberGenerator_.randomDouble();
6553 } else {
6554 value = 0.0;
6555 }
6556 if (currentValue) {
6557 largest = CoinMax(largest, fabs(value));
6558 if (fabs(value) > fabs(currentValue) * largestPerCent)
6559 largestPerCent = fabs(value / currentValue);
6560 } else {
6561 largestZero = CoinMax(largestZero, fabs(value));
6562 }
6563 if (printOut)
6564 printf("row %d cost %g change %g\n", iRow, rowObjectiveWork_[iRow], value);
6565 rowObjectiveWork_[iRow] += value;
6566 }
6567 }
6568 }
6569 // more its but faster double weight[]={1.0e-4,1.0e-2,1.0e-1,1.0,2.0,10.0,100.0,200.0,400.0,600.0,1000.0};
6570 // good its double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,2.0,5.0,10.0,20.0,30.0,40.0,100.0};
6571 double weight[] = { 1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 40.0, 100.0 };
6572 //double weight[]={1.0e-4,1.0e-2,5.0e-1,1.0,20.0,50.0,100.0,120.0,130.0,140.0,200.0};
6573 //double extraWeight = 10.0;
6574 // Scale back if wanted
6575 double weight2[] = { 1.0e-4, 1.0e-2, 5.0e-1, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
6576 if (constantPerturbation < 99.0 * dualTolerance_) {
6577 perturbation *= 0.1;
6578 //extraWeight = 0.5;
6579 memcpy(weight, weight2, sizeof(weight2));
6580 }
6581 // adjust weights if all columns long
6582 double factor = 1.0;
6583 if (maxLength) {
6584 factor = 3.0 / static_cast< double >(minLength);
6585 }
6586 // Make variables with more elements more expensive
6587 const double m1 = 0.5;
6588 double smallestAllowed = CoinMin(1.0e-2 * dualTolerance_, maximumFraction);
6589 double largestAllowed = CoinMax(1.0e3 * dualTolerance_, maximumFraction * averageCost);
6590 // smaller if in BAB
6591 //if (inCbcOrOther)
6592 //largestAllowed=CoinMin(largestAllowed,1.0e-5);
6593 //smallestAllowed = CoinMin(smallestAllowed,0.1*largestAllowed);
6594 #define SAVE_PERT
6595 #ifdef SAVE_PERT
6596 if (2 * numberColumns_ > maximumPerturbationSize_) {
6597 delete[] perturbationArray_;
6598 maximumPerturbationSize_ = 2 * numberColumns_;
6599 perturbationArray_ = new double[maximumPerturbationSize_];
6600 for (iColumn = 0; iColumn < maximumPerturbationSize_; iColumn++) {
6601 perturbationArray_[iColumn] = randomNumberGenerator_.randomDouble();
6602 }
6603 }
6604 #endif
6605 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
6606 if (columnLowerWork_[iColumn] < columnUpperWork_[iColumn] && getStatus(iColumn) != basic) {
6607 double value = perturbation;
6608 double currentValue = objectiveWork_[iColumn];
6609 value = CoinMin(value, constantPerturbation + maximumFraction * (fabs(currentValue) + 1.0e-1 * perturbation + 1.0e-8));
6610 //value = CoinMin(value,constantPerturbation;+maximumFraction*fabs(currentValue));
6611 double value2 = constantPerturbation + 1.0e-1 * smallestNonZero;
6612 if (uniformChange) {
6613 value = maximumFraction;
6614 value2 = maximumFraction;
6615 }
6616 if (columnLowerWork_[iColumn] > -largeValue_) {
6617 if (fabs(columnLowerWork_[iColumn]) < fabs(columnUpperWork_[iColumn])) {
6618 #ifndef SAVE_PERT
6619 value *= (1.0 - m1 + m1 * randomNumberGenerator_.randomDouble());
6620 value2 *= (1.0 - m1 + m1 * randomNumberGenerator_.randomDouble());
6621 #else
6622 value *= (1.0 - m1 + m1 * perturbationArray_[2 * iColumn]);
6623 value2 *= (1.0 - m1 + m1 * perturbationArray_[2 * iColumn + 1]);
6624 #endif
6625 } else {
6626 //value *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble());
6627 //value2 *= -(1.0-m1+m1*randomNumberGenerator_.randomDouble());
6628 value = 0.0;
6629 }
6630 } else if (columnUpperWork_[iColumn] < largeValue_) {
6631 #ifndef SAVE_PERT
6632 value *= -(1.0 - m1 + m1 * randomNumberGenerator_.randomDouble());
6633 value2 *= -(1.0 - m1 + m1 * randomNumberGenerator_.randomDouble());
6634 #else
6635 value *= -(1.0 - m1 + m1 * perturbationArray_[2 * iColumn]);
6636 value2 *= -(1.0 - m1 + m1 * perturbationArray_[2 * iColumn + 1]);
6637 #endif
6638 } else {
6639 value = 0.0;
6640 }
6641 if (value) {
6642 int length = columnLength[iColumn];
6643 if (length > 3) {
6644 length = static_cast< int >(static_cast< double >(length) * factor);
6645 length = CoinMax(3, length);
6646 }
6647 double multiplier;
6648 #if 1
6649 if (length < 10)
6650 multiplier = weight[length];
6651 else
6652 multiplier = weight[10];
6653 #else
6654 if (length < 10)
6655 multiplier = weight[length];
6656 else
6657 multiplier = weight[10] + extraWeight * (length - 10);
6658 multiplier *= 0.5;
6659 #endif
6660 value *= multiplier;
6661 value = CoinMin(value, value2);
6662 if (savePerturbation < 50 || savePerturbation > 60) {
6663 if (fabs(value) <= dualTolerance_)
6664 value = 0.0;
6665 } else if (value) {
6666 // get in range
6667 if (fabs(value) <= smallestAllowed) {
6668 value *= 10.0;
6669 while (fabs(value) <= smallestAllowed)
6670 value *= 10.0;
6671 } else if (fabs(value) > largestAllowed) {
6672 value *= 0.1;
6673 while (fabs(value) > largestAllowed)
6674 value *= 0.1;
6675 }
6676 }
6677 if (currentValue) {
6678 largest = CoinMax(largest, fabs(value));
6679 if (fabs(value) > fabs(currentValue) * largestPerCent)
6680 largestPerCent = fabs(value / currentValue);
6681 } else {
6682 largestZero = CoinMax(largestZero, fabs(value));
6683 }
6684 // but negative if at ub
6685 if (getStatus(iColumn) == atUpperBound)
6686 value = -value;
6687 if (printOut)
6688 printf("col %d cost %g change %g\n", iColumn, objectiveWork_[iColumn], value);
6689 objectiveWork_[iColumn] += value;
6690 }
6691 }
6692 }
6693 if (largestZero > 1.0 * largest && largest) {
6694 //printf("largest zero perturbation of %g too big (nonzero %g)\n",
6695 // largestZero,largest);
6696 largestZero = 0.0;
6697 const double *obj = objective();
6698 double test = CoinMax(1.0e-8, largest);
6699 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
6700 if (!obj[iColumn]) {
6701 double cost = cost_[iColumn];
6702 while (fabs(cost) > test)
6703 cost *= 0.5;
6704 cost_[iColumn] = cost;
6705 largestZero = CoinMax(largestZero, fabs(cost));
6706 }
6707 }
6708 }
6709 handler_->message(CLP_SIMPLEX_PERTURB, messages_)
6710 << 100.0 * maximumFraction << perturbation << largest << 100.0 * largestPerCent << largestZero
6711 << CoinMessageEol;
6712 // and zero changes
6713 //int nTotal = numberRows_+numberColumns_;
6714 //CoinZeroN(cost_+nTotal,nTotal);
6715 // say perturbed
6716 #ifdef PERT_STATISTICS
6717 {
6718 double averageCost = 0.0;
6719 int numberNonZero = 0;
6720 double *COIN_RESTRICT sort = new double[numberColumns_];
6721 for (int i = 0; i < numberColumns_; i++) {
6722 double value = fabs(cost_[i]);
6723 sort[i] = value;
6724 averageCost += value;
6725 if (value)
6726 numberNonZero++;
6727 }
6728 if (numberNonZero)
6729 averageCost /= static_cast< double >(numberNonZero);
6730 else
6731 averageCost = 1.0;
6732 std::sort(sort, sort + numberColumns_);
6733 int number = 1;
6734 double last = sort[0];
6735 for (int i = 1; i < numberColumns_; i++) {
6736 if (last != sort[i])
6737 number++;
6738 last = sort[i];
6739 }
6740 printf("nnz %d percent %d", number, (number * 100) / numberColumns_);
6741 delete[] sort;
6742 breakdown("Objective", numberColumns_ + numberRows_, cost_);
6743 }
6744 #endif
6745 perturbation_ = 101;
6746 return 0;
6747 }
6748 /* For strong branching. On input lower and upper are new bounds
6749 while on output they are change in objective function values
6750 (>1.0e50 infeasible).
6751 Return code is 0 if nothing interesting, -1 if infeasible both
6752 ways and +1 if infeasible one way (check values to see which one(s))
6753 Returns -2 if bad factorization
6754 */
strongBranching(int numberVariables,const int * variables,double * newLower,double * newUpper,double ** outputSolution,int * outputStatus,int * outputIterations,bool stopOnFirstInfeasible,bool alwaysFinish,int startFinishOptions)6755 int ClpSimplexDual::strongBranching(int numberVariables, const int *variables,
6756 double *newLower, double *newUpper,
6757 double **outputSolution,
6758 int *outputStatus, int *outputIterations,
6759 bool stopOnFirstInfeasible,
6760 bool alwaysFinish,
6761 int startFinishOptions)
6762 {
6763 int i;
6764 int returnCode = 0;
6765 double saveObjectiveValue = objectiveValue_;
6766 algorithm_ = -1;
6767
6768 //scaling(false);
6769
6770 // put in standard form (and make row copy)
6771 // create modifiable copies of model rim and do optional scaling
6772 createRim(7 + 8 + 16 + 32, true, startFinishOptions);
6773
6774 // change newLower and newUpper if scaled
6775
6776 // Do initial factorization
6777 // and set certain stuff
6778 // We can either set increasing rows so ...IsBasic gives pivot row
6779 // or we can just increment iBasic one by one
6780 // for now let ...iBasic give pivot row
6781 int useFactorization = false;
6782 if ((startFinishOptions & 2) != 0 && (whatsChanged_ & (2 + 512)) == 2 + 512)
6783 useFactorization = true; // Keep factorization if possible
6784 // switch off factorization if bad
6785 if (pivotVariable_[0] < 0)
6786 useFactorization = false;
6787 if (!useFactorization || factorization_->numberRows() != numberRows_) {
6788 useFactorization = false;
6789 factorization_->setDefaultValues();
6790
6791 int factorizationStatus = internalFactorize(0);
6792 if (factorizationStatus < 0) {
6793 // some error
6794 // we should either debug or ignore
6795 #ifndef NDEBUG
6796 printf("***** ClpDual strong branching factorization error - debug\n");
6797 #endif
6798 return -2;
6799 } else if (factorizationStatus && factorizationStatus <= numberRows_) {
6800 handler_->message(CLP_SINGULARITIES, messages_)
6801 << factorizationStatus
6802 << CoinMessageEol;
6803 }
6804 }
6805 // save stuff
6806 ClpFactorization saveFactorization(*factorization_);
6807 // Get fake bounds correctly
6808 double changeCost;
6809 changeBounds(3, NULL, changeCost);
6810 int saveNumberFake = numberFake_;
6811 // save basis and solution
6812 double *saveSolution = new double[numberRows_ + numberColumns_];
6813 CoinMemcpyN(solution_,
6814 numberRows_ + numberColumns_, saveSolution);
6815 unsigned char *saveStatus = new unsigned char[numberRows_ + numberColumns_];
6816 CoinMemcpyN(status_, numberColumns_ + numberRows_, saveStatus);
6817 // save bounds as createRim makes clean copies
6818 double *saveLower = new double[numberRows_ + numberColumns_];
6819 CoinMemcpyN(lower_,
6820 numberRows_ + numberColumns_, saveLower);
6821 double *saveUpper = new double[numberRows_ + numberColumns_];
6822 CoinMemcpyN(upper_,
6823 numberRows_ + numberColumns_, saveUpper);
6824 double *saveObjective = new double[numberRows_ + numberColumns_];
6825 CoinMemcpyN(cost_,
6826 numberRows_ + numberColumns_, saveObjective);
6827 int *savePivot = new int[numberRows_];
6828 CoinMemcpyN(pivotVariable_, numberRows_, savePivot);
6829 // need to save/restore weights.
6830
6831 int iSolution = 0;
6832 for (i = 0; i < numberVariables; i++) {
6833 int iColumn = variables[i];
6834 double objectiveChange;
6835 double saveBound;
6836
6837 // try down
6838
6839 saveBound = columnUpper_[iColumn];
6840 // external view - in case really getting optimal
6841 columnUpper_[iColumn] = newUpper[i];
6842 assert(inverseColumnScale_ || scalingFlag_ <= 0);
6843 if (scalingFlag_ <= 0)
6844 upper_[iColumn] = newUpper[i] * rhsScale_;
6845 else
6846 upper_[iColumn] = (newUpper[i] * inverseColumnScale_[iColumn]) * rhsScale_; // scale
6847 // Start of fast iterations
6848 int status = fastDual(alwaysFinish);
6849 CoinAssert(problemStatus_ || objectiveValue_ < 1.0e50);
6850 #ifdef CLP_DEBUG
6851 printf("first status %d obj %g\n", problemStatus_, objectiveValue_);
6852 #endif
6853 if (problemStatus_ == 10)
6854 problemStatus_ = 3;
6855 // make sure plausible
6856 double obj = CoinMax(objectiveValue_, saveObjectiveValue);
6857 if (status && problemStatus_ != 3) {
6858 // not finished - might be optimal
6859 checkPrimalSolution(rowActivityWork_, columnActivityWork_);
6860 double limit = 0.0;
6861 getDblParam(ClpDualObjectiveLimit, limit);
6862 if (!numberPrimalInfeasibilities_ && obj < limit) {
6863 problemStatus_ = 0;
6864 }
6865 status = problemStatus_;
6866 }
6867 if (problemStatus_ == 3)
6868 status = 2;
6869 if (status || (problemStatus_ == 0 && !isDualObjectiveLimitReached())) {
6870 objectiveChange = obj - saveObjectiveValue;
6871 } else {
6872 objectiveChange = 1.0e100;
6873 status = 1;
6874 }
6875 if (outputSolution) {
6876 if (scalingFlag_ <= 0) {
6877 CoinMemcpyN(solution_, numberColumns_, outputSolution[iSolution]);
6878 } else {
6879 int j;
6880 double *sol = outputSolution[iSolution];
6881 for (j = 0; j < numberColumns_; j++)
6882 sol[j] = solution_[j] * columnScale_[j];
6883 }
6884 }
6885 outputStatus[iSolution] = status;
6886 outputIterations[iSolution] = numberIterations_;
6887 iSolution++;
6888 // restore
6889 numberFake_ = saveNumberFake;
6890 CoinMemcpyN(saveSolution,
6891 numberRows_ + numberColumns_, solution_);
6892 CoinMemcpyN(saveStatus, numberColumns_ + numberRows_, status_);
6893 CoinMemcpyN(saveLower,
6894 numberRows_ + numberColumns_, lower_);
6895 CoinMemcpyN(saveUpper,
6896 numberRows_ + numberColumns_, upper_);
6897 CoinMemcpyN(saveObjective,
6898 numberRows_ + numberColumns_, cost_);
6899 columnUpper_[iColumn] = saveBound;
6900 CoinMemcpyN(savePivot, numberRows_, pivotVariable_);
6901 //delete factorization_;
6902 //factorization_ = new ClpFactorization(saveFactorization,numberRows_);
6903 setFactorization(saveFactorization);
6904 newUpper[i] = objectiveChange;
6905 #ifdef CLP_DEBUG
6906 printf("down on %d costs %g\n", iColumn, objectiveChange);
6907 #endif
6908
6909 // try up
6910
6911 saveBound = columnLower_[iColumn];
6912 // external view - in case really getting optimal
6913 columnLower_[iColumn] = newLower[i];
6914 assert(inverseColumnScale_ || scalingFlag_ <= 0);
6915 if (scalingFlag_ <= 0)
6916 lower_[iColumn] = newLower[i] * rhsScale_;
6917 else
6918 lower_[iColumn] = (newLower[i] * inverseColumnScale_[iColumn]) * rhsScale_; // scale
6919 // Start of fast iterations
6920 status = fastDual(alwaysFinish);
6921 CoinAssert(problemStatus_ || objectiveValue_ < 1.0e50);
6922 #ifdef CLP_DEBUG
6923 printf("second status %d obj %g\n", problemStatus_, objectiveValue_);
6924 #endif
6925 if (problemStatus_ == 10)
6926 problemStatus_ = 3;
6927 // make sure plausible
6928 obj = CoinMax(objectiveValue_, saveObjectiveValue);
6929 if (status && problemStatus_ != 3) {
6930 // not finished - might be optimal
6931 checkPrimalSolution(rowActivityWork_, columnActivityWork_);
6932 double limit = 0.0;
6933 getDblParam(ClpDualObjectiveLimit, limit);
6934 if (!numberPrimalInfeasibilities_ && obj < limit) {
6935 problemStatus_ = 0;
6936 }
6937 status = problemStatus_;
6938 }
6939 if (problemStatus_ == 3)
6940 status = 2;
6941 if (status || (problemStatus_ == 0 && !isDualObjectiveLimitReached())) {
6942 objectiveChange = obj - saveObjectiveValue;
6943 } else {
6944 objectiveChange = 1.0e100;
6945 status = 1;
6946 }
6947 if (outputSolution) {
6948 if (scalingFlag_ <= 0) {
6949 CoinMemcpyN(solution_, numberColumns_, outputSolution[iSolution]);
6950 } else {
6951 int j;
6952 double *sol = outputSolution[iSolution];
6953 for (j = 0; j < numberColumns_; j++)
6954 sol[j] = solution_[j] * columnScale_[j];
6955 }
6956 }
6957 outputStatus[iSolution] = status;
6958 outputIterations[iSolution] = numberIterations_;
6959 iSolution++;
6960
6961 // restore
6962 numberFake_ = saveNumberFake;
6963 CoinMemcpyN(saveSolution,
6964 numberRows_ + numberColumns_, solution_);
6965 CoinMemcpyN(saveStatus, numberColumns_ + numberRows_, status_);
6966 CoinMemcpyN(saveLower,
6967 numberRows_ + numberColumns_, lower_);
6968 CoinMemcpyN(saveUpper,
6969 numberRows_ + numberColumns_, upper_);
6970 CoinMemcpyN(saveObjective,
6971 numberRows_ + numberColumns_, cost_);
6972 columnLower_[iColumn] = saveBound;
6973 CoinMemcpyN(savePivot, numberRows_, pivotVariable_);
6974 //delete factorization_;
6975 //factorization_ = new ClpFactorization(saveFactorization,numberRows_);
6976 setFactorization(saveFactorization);
6977
6978 newLower[i] = objectiveChange;
6979 #ifdef CLP_DEBUG
6980 printf("up on %d costs %g\n", iColumn, objectiveChange);
6981 #endif
6982
6983 /* Possibilities are:
6984 Both sides feasible - store
6985 Neither side feasible - set objective high and exit if desired
6986 One side feasible - change bounds and resolve
6987 */
6988 if (newUpper[i] < 1.0e100) {
6989 if (newLower[i] < 1.0e100) {
6990 // feasible - no action
6991 } else {
6992 // up feasible, down infeasible
6993 returnCode = 1;
6994 if (stopOnFirstInfeasible)
6995 break;
6996 }
6997 } else {
6998 if (newLower[i] < 1.0e100) {
6999 // down feasible, up infeasible
7000 returnCode = 1;
7001 if (stopOnFirstInfeasible)
7002 break;
7003 } else {
7004 // neither side feasible
7005 returnCode = -1;
7006 break;
7007 }
7008 }
7009 }
7010 delete[] saveSolution;
7011 delete[] saveLower;
7012 delete[] saveUpper;
7013 delete[] saveObjective;
7014 delete[] saveStatus;
7015 delete[] savePivot;
7016 if ((startFinishOptions & 1) == 0) {
7017 deleteRim(1);
7018 whatsChanged_ &= ~0xffff;
7019 } else {
7020 // Original factorization will have been put back by last loop
7021 //delete factorization_;
7022 //factorization_ = new ClpFactorization(saveFactorization);
7023 deleteRim(0);
7024 // mark all as current
7025 whatsChanged_ = 0x3ffffff;
7026 }
7027 objectiveValue_ = saveObjectiveValue;
7028 return returnCode;
7029 }
7030 // treat no pivot as finished (unless interesting)
fastDual(bool alwaysFinish)7031 int ClpSimplexDual::fastDual(bool alwaysFinish)
7032 {
7033 progressFlag_ = 0;
7034 bestObjectiveValue_ = objectiveValue_;
7035 algorithm_ = -1;
7036 secondaryStatus_ = 0;
7037 // Say in fast dual
7038 if (!alwaysFinish)
7039 specialOptions_ |= 1048576;
7040 specialOptions_ |= 16384;
7041 int saveDont = dontFactorizePivots_;
7042 if ((specialOptions_ & 2048) == 0)
7043 dontFactorizePivots_ = 0;
7044 else if (!dontFactorizePivots_)
7045 dontFactorizePivots_ = 20;
7046 //handler_->setLogLevel(63);
7047 // save data
7048 ClpDataSave data = saveData();
7049 dualTolerance_ = dblParam_[ClpDualTolerance];
7050 primalTolerance_ = dblParam_[ClpPrimalTolerance];
7051
7052 // save dual bound
7053 double saveDualBound = dualBound_;
7054
7055 // Start can skip some things in transposeTimes
7056 specialOptions_ |= 131072;
7057 if (alphaAccuracy_ != -1.0)
7058 alphaAccuracy_ = 1.0;
7059 // for dual we will change bounds using dualBound_
7060 // for this we need clean basis so it is after factorize
7061 #if 0
7062 {
7063 int numberTotal = numberRows_ + numberColumns_;
7064 double * saveSol = CoinCopyOfArray(solution_, numberTotal);
7065 double * saveDj = CoinCopyOfArray(dj_, numberTotal);
7066 double tolerance = 1.0e-8;
7067 gutsOfSolution(NULL, NULL);
7068 int j;
7069 double largestPrimal = tolerance;
7070 int iPrimal = -1;
7071 for (j = 0; j < numberTotal; j++) {
7072 double difference = solution_[j] - saveSol[j];
7073 if (fabs(difference) > largestPrimal) {
7074 iPrimal = j;
7075 largestPrimal = fabs(difference);
7076 }
7077 }
7078 double largestDual = tolerance;
7079 int iDual = -1;
7080 for (j = 0; j < numberTotal; j++) {
7081 double difference = dj_[j] - saveDj[j];
7082 if (fabs(difference) > largestDual && upper_[j] > lower_[j]) {
7083 iDual = j;
7084 largestDual = fabs(difference);
7085 }
7086 }
7087 if (iPrimal >= 0 || iDual >= 0)
7088 printf("pivots %d primal diff(%g,%d) dual diff(%g,%d)\n",
7089 factorization_->pivots(),
7090 largestPrimal, iPrimal,
7091 largestDual, iDual);
7092 delete [] saveSol;
7093 delete [] saveDj;
7094 }
7095 #else
7096 if ((specialOptions_ & 524288) == 0)
7097 gutsOfSolution(NULL, NULL);
7098 #endif
7099 #if 0
7100 if (numberPrimalInfeasibilities_ != 1 ||
7101 numberDualInfeasibilities_)
7102 printf("dual %g (%d) primal %g (%d)\n",
7103 sumDualInfeasibilities_, numberDualInfeasibilities_,
7104 sumPrimalInfeasibilities_, numberPrimalInfeasibilities_);
7105 #endif
7106 #ifndef NDEBUG
7107 #ifdef COIN_DEVELOP
7108 resetFakeBounds(-1);
7109 #endif
7110 #endif
7111 //numberFake_ =0; // Number of variables at fake bounds
7112 numberChanged_ = 0; // Number of variables with changed costs
7113 //changeBounds(1,NULL,objectiveChange);
7114
7115 problemStatus_ = -1;
7116 numberIterations_ = 0;
7117 if ((specialOptions_ & 524288) == 0) {
7118 factorization_->sparseThreshold(0);
7119 factorization_->goSparse();
7120 }
7121
7122 int lastCleaned = 0; // last time objective or bounds cleaned up
7123
7124 // number of times we have declared optimality
7125 numberTimesOptimal_ = 0;
7126
7127 // This says whether to restore things etc
7128 int factorType = 0;
7129 /*
7130 Status of problem:
7131 0 - optimal
7132 1 - infeasible
7133 2 - unbounded
7134 -1 - iterating
7135 -2 - factorization wanted
7136 -3 - redo checking without factorization
7137 -4 - looks infeasible
7138
7139 BUT also from whileIterating return code is:
7140
7141 -1 iterations etc
7142 -2 inaccuracy
7143 -3 slight inaccuracy (and done iterations)
7144 +0 looks optimal (might be unbounded - but we will investigate)
7145 +1 looks infeasible
7146 +3 max iterations
7147
7148 */
7149
7150 int returnCode = 0;
7151
7152 int iRow, iColumn;
7153 int maxPass = maximumIterations() / 10;
7154 while (problemStatus_ < 0) {
7155 // clear
7156 for (iRow = 0; iRow < 4; iRow++) {
7157 rowArray_[iRow]->clear();
7158 }
7159
7160 for (iColumn = 0; iColumn < SHORT_REGION; iColumn++) {
7161 columnArray_[iColumn]->clear();
7162 }
7163
7164 // give matrix (and model costs and bounds a chance to be
7165 // refreshed (normally null)
7166 matrix_->refresh(this);
7167 // If getting nowhere - why not give it a kick
7168 // does not seem to work too well - do some more work
7169 if ((specialOptions_ & 524288) != 0 && (moreSpecialOptions_ & 2048) == 0 && perturbation_ < 101 && numberIterations_ > 2 * (numberRows_ + numberColumns_) && (moreSpecialOptions_ & 1048576) == 0) {
7170 perturb();
7171 // Can't get here if values pass
7172 gutsOfSolution(NULL, NULL);
7173 if (handler_->logLevel() > 2) {
7174 handler_->message(CLP_SIMPLEX_STATUS, messages_)
7175 << numberIterations_ << objectiveValue();
7176 handler_->printing(sumPrimalInfeasibilities_ > 0.0)
7177 << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_;
7178 handler_->printing(sumDualInfeasibilities_ > 0.0)
7179 << sumDualInfeasibilities_ << numberDualInfeasibilities_;
7180 handler_->printing(numberDualInfeasibilitiesWithoutFree_
7181 < numberDualInfeasibilities_)
7182 << numberDualInfeasibilitiesWithoutFree_;
7183 handler_->message() << CoinMessageEol;
7184 }
7185 }
7186 // may factorize, checks if problem finished
7187 // should be able to speed this up on first time
7188 statusOfProblemInDual(lastCleaned, factorType, NULL, data, 0);
7189
7190 // Say good factorization
7191 factorType = 1;
7192 // but if large errors - probably not very useful
7193 if (maxPass > 0 && (largestDualError_ > 0.001 || largestPrimalError_ > 0.001))
7194 maxPass = -5;
7195 maxPass--;
7196 if (maxPass < -10) {
7197 // odd
7198 returnCode = 1;
7199 problemStatus_ = 3;
7200 // can't say anything interesting - might as well return
7201 #ifdef CLP_DEBUG
7202 printf("returning from fastDual after %d iterations with code %d because of loop\n",
7203 numberIterations_, returnCode);
7204 #endif
7205 break;
7206 }
7207
7208 // Do iterations
7209 if (problemStatus_ < 0) {
7210 double *givenPi = NULL;
7211 returnCode = whileIterating(givenPi, 0);
7212 if ((!alwaysFinish && returnCode < 0) || returnCode == 3) {
7213 if (returnCode != 3)
7214 assert(problemStatus_ < 0);
7215 returnCode = 1;
7216 problemStatus_ = 3;
7217 // can't say anything interesting - might as well return
7218 #ifdef CLP_DEBUG
7219 printf("returning from fastDual after %d iterations with code %d\n",
7220 numberIterations_, returnCode);
7221 #endif
7222 break;
7223 }
7224 if (returnCode == -2)
7225 factorType = 3;
7226 returnCode = 0;
7227 }
7228 }
7229 // slows down slightly - but more accurate
7230 if (problemStatus_ < 3 && factorization_->pivots()) {
7231 columnArray_[0]->clear();
7232 computeDuals(NULL);
7233 }
7234
7235 // clear
7236 for (iRow = 0; iRow < 4; iRow++) {
7237 rowArray_[iRow]->clear();
7238 }
7239
7240 for (iColumn = 0; iColumn < SHORT_REGION; iColumn++) {
7241 columnArray_[iColumn]->clear();
7242 }
7243 // Say not in fast dual
7244 specialOptions_ &= ~(16384 | 1048576);
7245 assert(!numberFake_ || ((specialOptions_ & (2048 | 4096)) != 0 && dualBound_ >= 1.0e8)
7246 || returnCode || problemStatus_); // all bounds should be okay
7247 if (numberFake_ > 0 && false) {
7248 // Set back
7249 double dummy;
7250 changeBounds(2, NULL, dummy);
7251 }
7252 // Restore any saved stuff
7253 restoreData(data);
7254 dontFactorizePivots_ = saveDont;
7255 dualBound_ = saveDualBound;
7256 // Stop can skip some things in transposeTimes
7257 specialOptions_ &= ~131072;
7258 if (!problemStatus_) {
7259 // see if cutoff reached
7260 double limit = 0.0;
7261 getDblParam(ClpDualObjectiveLimit, limit);
7262 if (fabs(limit) < 1.0e30 && objectiveValue() * optimizationDirection_ > limit + 1.0e-7 + 1.0e-8 * fabs(limit)) {
7263 // actually infeasible on objective
7264 problemStatus_ = 1;
7265 secondaryStatus_ = 1;
7266 }
7267 }
7268 if (problemStatus_ == 3)
7269 objectiveValue_ = CoinMax(bestObjectiveValue_, objectiveValue_ - bestPossibleImprovement_);
7270 return returnCode;
7271 }
7272 // This does first part of StrongBranching
7273 ClpFactorization *
setupForStrongBranching(char * arrays,int numberRows,int numberColumns,bool solveLp)7274 ClpSimplexDual::setupForStrongBranching(char *arrays, int numberRows,
7275 int numberColumns, bool solveLp)
7276 {
7277 if (solveLp) {
7278 // make sure won't create fake objective
7279 int saveOptions = specialOptions_;
7280 specialOptions_ |= 16384;
7281 // solve
7282 int saveMaximumIterations = intParam_[ClpMaxNumIteration];
7283 intParam_[ClpMaxNumIteration] = 100 + numberRows_ + numberColumns_;
7284 dual(0, 7);
7285 if (problemStatus_ == 10) {
7286 ClpSimplex::dual(0, 7);
7287 //if (problemStatus_)
7288 //printf("second go in hot start %d iterations - status %d\n",
7289 // numberIterations_,problemStatus_);
7290 assert(problemStatus_ != 10);
7291 if (problemStatus_ == 0 && false) {
7292 dual(0, 7);
7293 #if 0
7294 if (problemStatus_) {
7295 printf("third go in hot start %d iterations - status %d\n",
7296 numberIterations_,problemStatus_);
7297 //ClpSimplex::dual(0, 7);
7298 //printf("fourth go (part 1) in hot start %d iterations - status %d\n",
7299 // numberIterations_,problemStatus_);
7300 }
7301 #endif
7302 #if 0
7303 if (problemStatus_==10 && rowScale_) {
7304 ClpSimplex::dual(0, 0);
7305 printf("fourth go (part 1) in hot start %d iterations - status %d\n",
7306 numberIterations_,problemStatus_);
7307 scaling(0);
7308 dual(0, 7);
7309 printf("fourth go (part 2) in hot start %d iterations - status %d\n",
7310 numberIterations_,problemStatus_);
7311 //assert (problemStatus_!=10);
7312 }
7313 #endif
7314 }
7315 }
7316 intParam_[ClpMaxNumIteration] = saveMaximumIterations;
7317 specialOptions_ = saveOptions;
7318 if (problemStatus_ != 0 /*&& problemStatus_ != 10*/)
7319 return NULL; // say infeasible or odd
7320 // May be empty
7321 solveLp = (solution_ != NULL && problemStatus_ == 0);
7322 }
7323 problemStatus_ = 0;
7324 if (!solveLp) {
7325 algorithm_ = -1;
7326 // put in standard form (and make row copy)
7327 // create modifiable copies of model rim and do optional scaling
7328 int startFinishOptions;
7329 if ((specialOptions_ & 4096) == 0) {
7330 startFinishOptions = 0;
7331 } else {
7332 startFinishOptions = 1 + 2 + 4;
7333 }
7334 createRim(7 + 8 + 16 + 32, true, startFinishOptions);
7335 // Do initial factorization
7336 // and set certain stuff
7337 // We can either set increasing rows so ...IsBasic gives pivot row
7338 // or we can just increment iBasic one by one
7339 // for now let ...iBasic give pivot row
7340 bool useFactorization = false;
7341 if ((startFinishOptions & 2) != 0 && (whatsChanged_ & (2 + 512)) == 2 + 512) {
7342 useFactorization = true; // Keep factorization if possible
7343 // switch off factorization if bad
7344 if (pivotVariable_[0] < 0 || factorization_->numberRows() != numberRows_)
7345 useFactorization = false;
7346 }
7347 if (!useFactorization) {
7348 factorization_->setDefaultValues();
7349
7350 int factorizationStatus = internalFactorize(0);
7351 if (factorizationStatus < 0) {
7352 // some error
7353 // we should either debug or ignore
7354 #ifndef NDEBUG
7355 printf("***** ClpDual strong branching factorization error - debug\n");
7356 #endif
7357 } else if (factorizationStatus && factorizationStatus <= numberRows_) {
7358 handler_->message(CLP_SINGULARITIES, messages_)
7359 << factorizationStatus
7360 << CoinMessageEol;
7361 }
7362 }
7363 }
7364 // Get fake bounds correctly
7365 double dummyChangeCost;
7366 changeBounds(3, NULL, dummyChangeCost);
7367 double *arrayD = reinterpret_cast< double * >(arrays);
7368 arrayD[0] = objectiveValue() * optimizationDirection_;
7369 double *saveSolution = arrayD + 1;
7370 double *saveLower = saveSolution + (numberRows + numberColumns);
7371 double *saveUpper = saveLower + (numberRows + numberColumns);
7372 double *saveObjective = saveUpper + (numberRows + numberColumns);
7373 double *saveLowerOriginal = saveObjective + (numberRows + numberColumns);
7374 double *saveUpperOriginal = saveLowerOriginal + numberColumns;
7375 arrayD = saveUpperOriginal + numberColumns;
7376 int *savePivot = reinterpret_cast< int * >(arrayD);
7377 int *whichRow = savePivot + numberRows;
7378 int *whichColumn = whichRow + 3 * numberRows;
7379 int *arrayI = whichColumn + 2 * numberColumns;
7380 unsigned char *saveStatus = reinterpret_cast< unsigned char * >(arrayI + 1);
7381 // save stuff
7382 // save basis and solution
7383 CoinMemcpyN(solution_,
7384 numberRows_ + numberColumns_, saveSolution);
7385 CoinMemcpyN(status_, numberColumns_ + numberRows_, saveStatus);
7386 CoinMemcpyN(lower_,
7387 numberRows_ + numberColumns_, saveLower);
7388 CoinMemcpyN(upper_,
7389 numberRows_ + numberColumns_, saveUpper);
7390 CoinMemcpyN(cost_,
7391 numberRows_ + numberColumns_, saveObjective);
7392 CoinMemcpyN(pivotVariable_, numberRows_, savePivot);
7393 ClpFactorization *factorization = factorization_;
7394 factorization_ = NULL;
7395 return factorization;
7396 }
7397 // This cleans up after strong branching
cleanupAfterStrongBranching(ClpFactorization * factorization)7398 void ClpSimplexDual::cleanupAfterStrongBranching(ClpFactorization *factorization)
7399 {
7400 int startFinishOptions;
7401 /* COIN_CLP_VETTED
7402 Looks safe for Cbc
7403 */
7404 if ((specialOptions_ & 4096) == 0) {
7405 startFinishOptions = 0;
7406 } else {
7407 startFinishOptions = 1 + 2 + 4;
7408 }
7409 if ((startFinishOptions & 1) == 0 && cost_) {
7410 deleteRim(1);
7411 } else {
7412 // Original factorization will have been put back by last loop
7413 delete factorization_;
7414 factorization_ = factorization;
7415 //deleteRim(0);
7416 // mark all as current
7417 }
7418 whatsChanged_ &= ~0xffff;
7419 }
7420 /* Checks number of variables at fake bounds. This is used by fastDual
7421 so can exit gracefully before end */
numberAtFakeBound()7422 int ClpSimplexDual::numberAtFakeBound()
7423 {
7424 int iSequence;
7425 int numberFake = 0;
7426
7427 for (iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
7428 FakeBound bound = getFakeBound(iSequence);
7429 switch (getStatus(iSequence)) {
7430
7431 case basic:
7432 break;
7433 case isFree:
7434 case superBasic:
7435 case ClpSimplex::isFixed:
7436 //setFakeBound (iSequence, noFake);
7437 break;
7438 case atUpperBound:
7439 if (bound == upperFake || bound == bothFake)
7440 numberFake++;
7441 break;
7442 case atLowerBound:
7443 if (bound == lowerFake || bound == bothFake)
7444 numberFake++;
7445 break;
7446 }
7447 }
7448 //numberFake_ = numberFake;
7449 return numberFake;
7450 }
7451 /* Pivot out a variable and choose an incoing one. Assumes dual
7452 feasible - will not go through a reduced cost.
7453 Returns step length in theta
7454 Return codes as before but -1 means no acceptable pivot
7455 */
pivotResultPart1()7456 int ClpSimplexDual::pivotResultPart1()
7457 {
7458 // Get good size for pivot
7459 // Allow first few iterations to take tiny
7460 double acceptablePivot = 1.0e-1 * acceptablePivot_;
7461 if (numberIterations_ > 100)
7462 acceptablePivot = acceptablePivot_;
7463 if (factorization_->pivots() > 10)
7464 acceptablePivot = 1.0e+3 * acceptablePivot_; // if we have iterated be more strict
7465 else if (factorization_->pivots() > 5)
7466 acceptablePivot = 1.0e+2 * acceptablePivot_; // if we have iterated be slightly more strict
7467 else if (factorization_->pivots())
7468 acceptablePivot = acceptablePivot_; // relax
7469 // But factorizations complain if <1.0e-8
7470 //acceptablePivot=CoinMax(acceptablePivot,1.0e-8);
7471 double bestPossiblePivot = 1.0;
7472 // get sign for finding row of tableau
7473 // create as packed
7474 double direction = directionOut_;
7475 assert(!rowArray_[0]->getNumElements());
7476 rowArray_[1]->clear(); //assert (!rowArray_[1]->getNumElements());
7477 assert(!columnArray_[0]->getNumElements());
7478 assert(!columnArray_[1]->getNumElements());
7479 rowArray_[0]->createPacked(1, &pivotRow_, &direction);
7480 factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]);
7481 // Allow to do dualColumn0
7482 if (numberThreads_ < -1)
7483 spareIntArray_[0] = 1;
7484 spareDoubleArray_[0] = acceptablePivot;
7485 rowArray_[3]->clear();
7486 sequenceIn_ = -1;
7487 // put row of tableau in rowArray[0] and columnArray[0]
7488 assert(!rowArray_[1]->getNumElements());
7489 if (!scaledMatrix_) {
7490 if ((moreSpecialOptions_ & 8) != 0 && !rowScale_)
7491 spareIntArray_[0] = 1;
7492 matrix_->transposeTimes(this, -1.0,
7493 rowArray_[0], rowArray_[1], columnArray_[0]);
7494 } else {
7495 double *saveR = rowScale_;
7496 double *saveC = columnScale_;
7497 rowScale_ = NULL;
7498 columnScale_ = NULL;
7499 if ((moreSpecialOptions_ & 8) != 0)
7500 spareIntArray_[0] = 1;
7501 scaledMatrix_->transposeTimes(this, -1.0,
7502 rowArray_[0], rowArray_[1], columnArray_[0]);
7503 rowScale_ = saveR;
7504 columnScale_ = saveC;
7505 }
7506 // do ratio test for normal iteration
7507 dualOut_ *= 1.0e-8;
7508 bestPossiblePivot = dualColumn(rowArray_[0], columnArray_[0], rowArray_[3],
7509 #ifdef LONG_REGION_2
7510 rowArray_[2],
7511 #else
7512 columnArray_[1],
7513 #endif
7514 acceptablePivot,
7515 NULL /*dubiousWeights*/);
7516 dualOut_ *= 1.0e8;
7517 if (fabs(bestPossiblePivot) < 1.0e-6)
7518 return -1;
7519 else
7520 return 0;
7521 }
7522 /*
7523 Row array has row part of pivot row
7524 Column array has column part.
7525 This is used in dual values pass
7526 */
checkPossibleValuesMove(CoinIndexedVector * rowArray,CoinIndexedVector * columnArray,double acceptablePivot)7527 void ClpSimplexDual::checkPossibleValuesMove(CoinIndexedVector *rowArray,
7528 CoinIndexedVector *columnArray,
7529 double acceptablePivot)
7530 {
7531 double *work;
7532 int number;
7533 int *which;
7534 int iSection;
7535
7536 double tolerance = dualTolerance_ * 1.001;
7537
7538 double thetaDown = 1.0e31;
7539 double changeDown;
7540 double thetaUp = 1.0e31;
7541 double bestAlphaDown = acceptablePivot * 0.99999;
7542 double bestAlphaUp = acceptablePivot * 0.99999;
7543 int sequenceDown = -1;
7544 int sequenceUp = sequenceOut_;
7545
7546 double djBasic = dj_[sequenceOut_];
7547 if (djBasic > 0.0) {
7548 // basic at lower bound so directionOut_ 1 and -1 in pivot row
7549 // dj will go to zero on other way
7550 thetaUp = djBasic;
7551 changeDown = -lower_[sequenceOut_];
7552 } else {
7553 // basic at upper bound so directionOut_ -1 and 1 in pivot row
7554 // dj will go to zero on other way
7555 thetaUp = -djBasic;
7556 changeDown = upper_[sequenceOut_];
7557 }
7558 bestAlphaUp = 1.0;
7559 int addSequence;
7560
7561 double alphaUp = 0.0;
7562 double alphaDown = 0.0;
7563
7564 for (iSection = 0; iSection < 2; iSection++) {
7565
7566 int i;
7567 if (!iSection) {
7568 work = rowArray->denseVector();
7569 number = rowArray->getNumElements();
7570 which = rowArray->getIndices();
7571 addSequence = numberColumns_;
7572 } else {
7573 work = columnArray->denseVector();
7574 number = columnArray->getNumElements();
7575 which = columnArray->getIndices();
7576 addSequence = 0;
7577 }
7578
7579 for (i = 0; i < number; i++) {
7580 int iSequence = which[i];
7581 int iSequence2 = iSequence + addSequence;
7582 double alpha;
7583 double oldValue;
7584 double value;
7585
7586 switch (getStatus(iSequence2)) {
7587
7588 case basic:
7589 break;
7590 case ClpSimplex::isFixed:
7591 alpha = work[i];
7592 changeDown += alpha * upper_[iSequence2];
7593 break;
7594 case isFree:
7595 case superBasic:
7596 alpha = work[i];
7597 // dj must be effectively zero as dual feasible
7598 if (fabs(alpha) > bestAlphaUp) {
7599 thetaDown = 0.0;
7600 thetaUp = 0.0;
7601 bestAlphaDown = fabs(alpha);
7602 bestAlphaUp = bestAlphaDown;
7603 sequenceDown = iSequence2;
7604 sequenceUp = sequenceDown;
7605 alphaUp = alpha;
7606 alphaDown = alpha;
7607 }
7608 break;
7609 case atUpperBound:
7610 alpha = work[i];
7611 oldValue = dj_[iSequence2];
7612 changeDown += alpha * upper_[iSequence2];
7613 if (alpha >= acceptablePivot) {
7614 // might do other way
7615 value = oldValue + thetaUp * alpha;
7616 if (value > -tolerance) {
7617 if (value > tolerance || fabs(alpha) > bestAlphaUp) {
7618 thetaUp = -oldValue / alpha;
7619 bestAlphaUp = fabs(alpha);
7620 sequenceUp = iSequence2;
7621 alphaUp = alpha;
7622 }
7623 }
7624 } else if (alpha <= -acceptablePivot) {
7625 // might do this way
7626 value = oldValue - thetaDown * alpha;
7627 if (value > -tolerance) {
7628 if (value > tolerance || fabs(alpha) > bestAlphaDown) {
7629 thetaDown = oldValue / alpha;
7630 bestAlphaDown = fabs(alpha);
7631 sequenceDown = iSequence2;
7632 alphaDown = alpha;
7633 }
7634 }
7635 }
7636 break;
7637 case atLowerBound:
7638 alpha = work[i];
7639 oldValue = dj_[iSequence2];
7640 changeDown += alpha * lower_[iSequence2];
7641 if (alpha <= -acceptablePivot) {
7642 // might do other way
7643 value = oldValue + thetaUp * alpha;
7644 if (value < tolerance) {
7645 if (value < -tolerance || fabs(alpha) > bestAlphaUp) {
7646 thetaUp = -oldValue / alpha;
7647 bestAlphaUp = fabs(alpha);
7648 sequenceUp = iSequence2;
7649 alphaUp = alpha;
7650 }
7651 }
7652 } else if (alpha >= acceptablePivot) {
7653 // might do this way
7654 value = oldValue - thetaDown * alpha;
7655 if (value < tolerance) {
7656 if (value < -tolerance || fabs(alpha) > bestAlphaDown) {
7657 thetaDown = oldValue / alpha;
7658 bestAlphaDown = fabs(alpha);
7659 sequenceDown = iSequence2;
7660 alphaDown = alpha;
7661 }
7662 }
7663 }
7664 break;
7665 }
7666 }
7667 }
7668 thetaUp *= -1.0;
7669 double changeUp = -thetaUp * changeDown;
7670 changeDown = -thetaDown * changeDown;
7671 if (CoinMax(fabs(thetaDown), fabs(thetaUp)) < 1.0e-8) {
7672 // largest
7673 if (fabs(alphaDown) < fabs(alphaUp)) {
7674 sequenceDown = -1;
7675 }
7676 }
7677 // choose
7678 sequenceIn_ = -1;
7679 if (changeDown > changeUp && sequenceDown >= 0) {
7680 theta_ = thetaDown;
7681 if (fabs(changeDown) < 1.0e30)
7682 sequenceIn_ = sequenceDown;
7683 alpha_ = alphaDown;
7684 #ifdef CLP_DEBUG
7685 if ((handler_->logLevel() & 32))
7686 printf("predicted way - dirout %d, change %g,%g theta %g\n",
7687 directionOut_, changeDown, changeUp, theta_);
7688 #endif
7689 } else {
7690 theta_ = thetaUp;
7691 if (fabs(changeUp) < 1.0e30)
7692 sequenceIn_ = sequenceUp;
7693 alpha_ = alphaUp;
7694 if (sequenceIn_ != sequenceOut_) {
7695 #ifdef CLP_DEBUG
7696 if ((handler_->logLevel() & 32))
7697 printf("opposite way - dirout %d, change %g,%g theta %g\n",
7698 directionOut_, changeDown, changeUp, theta_);
7699 #endif
7700 } else {
7701 #ifdef CLP_DEBUG
7702 if ((handler_->logLevel() & 32))
7703 printf("opposite way to zero dj - dirout %d, change %g,%g theta %g\n",
7704 directionOut_, changeDown, changeUp, theta_);
7705 #endif
7706 }
7707 }
7708 if (sequenceIn_ >= 0) {
7709 lowerIn_ = lower_[sequenceIn_];
7710 upperIn_ = upper_[sequenceIn_];
7711 valueIn_ = solution_[sequenceIn_];
7712 dualIn_ = dj_[sequenceIn_];
7713
7714 if (alpha_ < 0.0) {
7715 // as if from upper bound
7716 directionIn_ = -1;
7717 upperIn_ = valueIn_;
7718 } else {
7719 // as if from lower bound
7720 directionIn_ = 1;
7721 lowerIn_ = valueIn_;
7722 }
7723 }
7724 }
7725 /*
7726 Row array has row part of pivot row
7727 Column array has column part.
7728 This is used in cleanup
7729 */
checkPossibleCleanup(CoinIndexedVector * rowArray,CoinIndexedVector * columnArray,double acceptablePivot)7730 void ClpSimplexDual::checkPossibleCleanup(CoinIndexedVector *rowArray,
7731 CoinIndexedVector *columnArray,
7732 double acceptablePivot)
7733 {
7734 double *work;
7735 int number;
7736 int *which;
7737 int iSection;
7738
7739 double tolerance = dualTolerance_ * 1.001;
7740
7741 double thetaDown = 1.0e31;
7742 double thetaUp = 1.0e31;
7743 double bestAlphaDown = acceptablePivot * 10.0;
7744 double bestAlphaUp = acceptablePivot * 10.0;
7745 int sequenceDown = -1;
7746 int sequenceUp = -1;
7747
7748 double djSlack = dj_[pivotRow_];
7749 if (getRowStatus(pivotRow_) == basic)
7750 djSlack = COIN_DBL_MAX;
7751 if (fabs(djSlack) < tolerance)
7752 djSlack = 0.0;
7753 int addSequence;
7754
7755 double alphaUp = 0.0;
7756 double alphaDown = 0.0;
7757 for (iSection = 0; iSection < 2; iSection++) {
7758
7759 int i;
7760 if (!iSection) {
7761 work = rowArray->denseVector();
7762 number = rowArray->getNumElements();
7763 which = rowArray->getIndices();
7764 addSequence = numberColumns_;
7765 } else {
7766 work = columnArray->denseVector();
7767 number = columnArray->getNumElements();
7768 which = columnArray->getIndices();
7769 addSequence = 0;
7770 }
7771
7772 for (i = 0; i < number; i++) {
7773 int iSequence = which[i];
7774 int iSequence2 = iSequence + addSequence;
7775 double alpha;
7776 double oldValue;
7777 double value;
7778
7779 switch (getStatus(iSequence2)) {
7780
7781 case basic:
7782 break;
7783 case ClpSimplex::isFixed:
7784 alpha = work[i];
7785 if (addSequence) {
7786 COIN_DETAIL_PRINT(printf("possible - pivot row %d this %d\n", pivotRow_, iSequence));
7787 oldValue = dj_[iSequence2];
7788 if (alpha <= -acceptablePivot) {
7789 // might do other way
7790 value = oldValue + thetaUp * alpha;
7791 if (value < tolerance) {
7792 if (value < -tolerance || fabs(alpha) > bestAlphaUp) {
7793 thetaUp = -oldValue / alpha;
7794 bestAlphaUp = fabs(alpha);
7795 sequenceUp = iSequence2;
7796 alphaUp = alpha;
7797 }
7798 }
7799 } else if (alpha >= acceptablePivot) {
7800 // might do this way
7801 value = oldValue - thetaDown * alpha;
7802 if (value < tolerance) {
7803 if (value < -tolerance || fabs(alpha) > bestAlphaDown) {
7804 thetaDown = oldValue / alpha;
7805 bestAlphaDown = fabs(alpha);
7806 sequenceDown = iSequence2;
7807 alphaDown = alpha;
7808 }
7809 }
7810 }
7811 }
7812 break;
7813 case isFree:
7814 case superBasic:
7815 alpha = work[i];
7816 // dj must be effectively zero as dual feasible
7817 if (fabs(alpha) > bestAlphaUp) {
7818 thetaDown = 0.0;
7819 thetaUp = 0.0;
7820 bestAlphaDown = fabs(alpha);
7821 bestAlphaUp = bestAlphaDown;
7822 sequenceDown = iSequence2;
7823 sequenceUp = sequenceDown;
7824 alphaUp = alpha;
7825 alphaDown = alpha;
7826 }
7827 break;
7828 case atUpperBound:
7829 alpha = work[i];
7830 oldValue = dj_[iSequence2];
7831 if (alpha >= acceptablePivot) {
7832 // might do other way
7833 value = oldValue + thetaUp * alpha;
7834 if (value > -tolerance) {
7835 if (value > tolerance || fabs(alpha) > bestAlphaUp) {
7836 thetaUp = -oldValue / alpha;
7837 bestAlphaUp = fabs(alpha);
7838 sequenceUp = iSequence2;
7839 alphaUp = alpha;
7840 }
7841 }
7842 } else if (alpha <= -acceptablePivot) {
7843 // might do this way
7844 value = oldValue - thetaDown * alpha;
7845 if (value > -tolerance) {
7846 if (value > tolerance || fabs(alpha) > bestAlphaDown) {
7847 thetaDown = oldValue / alpha;
7848 bestAlphaDown = fabs(alpha);
7849 sequenceDown = iSequence2;
7850 alphaDown = alpha;
7851 }
7852 }
7853 }
7854 break;
7855 case atLowerBound:
7856 alpha = work[i];
7857 oldValue = dj_[iSequence2];
7858 if (alpha <= -acceptablePivot) {
7859 // might do other way
7860 value = oldValue + thetaUp * alpha;
7861 if (value < tolerance) {
7862 if (value < -tolerance || fabs(alpha) > bestAlphaUp) {
7863 thetaUp = -oldValue / alpha;
7864 bestAlphaUp = fabs(alpha);
7865 sequenceUp = iSequence2;
7866 alphaUp = alpha;
7867 }
7868 }
7869 } else if (alpha >= acceptablePivot) {
7870 // might do this way
7871 value = oldValue - thetaDown * alpha;
7872 if (value < tolerance) {
7873 if (value < -tolerance || fabs(alpha) > bestAlphaDown) {
7874 thetaDown = oldValue / alpha;
7875 bestAlphaDown = fabs(alpha);
7876 sequenceDown = iSequence2;
7877 alphaDown = alpha;
7878 }
7879 }
7880 }
7881 break;
7882 }
7883 }
7884 }
7885 thetaUp *= -1.0;
7886 // largest
7887 if (bestAlphaDown < bestAlphaUp)
7888 sequenceDown = -1;
7889 else
7890 sequenceUp = -1;
7891
7892 sequenceIn_ = -1;
7893
7894 if (sequenceDown >= 0) {
7895 theta_ = thetaDown;
7896 sequenceIn_ = sequenceDown;
7897 alpha_ = alphaDown;
7898 #ifdef CLP_DEBUG
7899 if ((handler_->logLevel() & 32))
7900 printf("predicted way - dirout %d, theta %g\n",
7901 directionOut_, theta_);
7902 #endif
7903 } else if (sequenceUp >= 0) {
7904 theta_ = thetaUp;
7905 sequenceIn_ = sequenceUp;
7906 alpha_ = alphaUp;
7907 #ifdef CLP_DEBUG
7908 if ((handler_->logLevel() & 32))
7909 printf("opposite way - dirout %d,theta %g\n",
7910 directionOut_, theta_);
7911 #endif
7912 }
7913 if (sequenceIn_ >= 0) {
7914 lowerIn_ = lower_[sequenceIn_];
7915 upperIn_ = upper_[sequenceIn_];
7916 valueIn_ = solution_[sequenceIn_];
7917 dualIn_ = dj_[sequenceIn_];
7918
7919 if (alpha_ < 0.0) {
7920 // as if from upper bound
7921 directionIn_ = -1;
7922 upperIn_ = valueIn_;
7923 } else {
7924 // as if from lower bound
7925 directionIn_ = 1;
7926 lowerIn_ = valueIn_;
7927 }
7928 }
7929 }
7930 /*
7931 This sees if we can move duals in dual values pass.
7932 This is done before any pivoting
7933 */
doEasyOnesInValuesPass(double * dj)7934 void ClpSimplexDual::doEasyOnesInValuesPass(double *dj)
7935 {
7936 // Get column copy
7937 CoinPackedMatrix *columnCopy = matrix();
7938 // Get a row copy in standard format
7939 CoinPackedMatrix copy;
7940 copy.setExtraGap(0.0);
7941 copy.setExtraMajor(0.0);
7942 copy.reverseOrderedCopyOf(*columnCopy);
7943 // get matrix data pointers
7944 const int *column = copy.getIndices();
7945 const CoinBigIndex *rowStart = copy.getVectorStarts();
7946 const int *rowLength = copy.getVectorLengths();
7947 const double *elementByRow = copy.getElements();
7948 double tolerance = dualTolerance_ * 1.001;
7949
7950 int iRow;
7951 #ifdef CLP_DEBUG
7952 {
7953 double value5 = 0.0;
7954 int i;
7955 for (i = 0; i < numberRows_ + numberColumns_; i++) {
7956 if (dj[i] < -1.0e-6)
7957 value5 += dj[i] * upper_[i];
7958 else if (dj[i] > 1.0e-6)
7959 value5 += dj[i] * lower_[i];
7960 }
7961 printf("Values objective Value before %g\n", value5);
7962 }
7963 #endif
7964 // for scaled row
7965 double *scaled = NULL;
7966 if (rowScale_)
7967 scaled = new double[numberColumns_];
7968 for (iRow = 0; iRow < numberRows_; iRow++) {
7969
7970 int iSequence = iRow + numberColumns_;
7971 double djBasic = dj[iSequence];
7972 if (getRowStatus(iRow) == basic && fabs(djBasic) > tolerance) {
7973
7974 double changeUp;
7975 // always -1 in pivot row
7976 if (djBasic > 0.0) {
7977 // basic at lower bound
7978 changeUp = -lower_[iSequence];
7979 } else {
7980 // basic at upper bound
7981 changeUp = upper_[iSequence];
7982 }
7983 bool canMove = true;
7984 int i;
7985 const double *thisElements = elementByRow + rowStart[iRow];
7986 const int *thisIndices = column + rowStart[iRow];
7987 if (rowScale_) {
7988 // scale row
7989 double scale = rowScale_[iRow];
7990 for (i = 0; i < rowLength[iRow]; i++) {
7991 int iColumn = thisIndices[i];
7992 double alpha = thisElements[i];
7993 scaled[i] = scale * alpha * columnScale_[iColumn];
7994 }
7995 thisElements = scaled;
7996 }
7997 for (i = 0; i < rowLength[iRow]; i++) {
7998 int iColumn = thisIndices[i];
7999 double alpha = thisElements[i];
8000 double oldValue = dj[iColumn];
8001 ;
8002 double value;
8003
8004 switch (getStatus(iColumn)) {
8005
8006 case basic:
8007 if (dj[iColumn] < -tolerance && fabs(solution_[iColumn] - upper_[iColumn]) < 1.0e-8) {
8008 // at ub
8009 changeUp += alpha * upper_[iColumn];
8010 // might do other way
8011 value = oldValue + djBasic * alpha;
8012 if (value > tolerance)
8013 canMove = false;
8014 } else if (dj[iColumn] > tolerance && fabs(solution_[iColumn] - lower_[iColumn]) < 1.0e-8) {
8015 changeUp += alpha * lower_[iColumn];
8016 // might do other way
8017 value = oldValue + djBasic * alpha;
8018 if (value < -tolerance)
8019 canMove = false;
8020 } else {
8021 canMove = false;
8022 }
8023 break;
8024 case ClpSimplex::isFixed:
8025 changeUp += alpha * upper_[iColumn];
8026 break;
8027 case isFree:
8028 case superBasic:
8029 canMove = false;
8030 break;
8031 case atUpperBound:
8032 changeUp += alpha * upper_[iColumn];
8033 // might do other way
8034 value = oldValue + djBasic * alpha;
8035 if (value > tolerance)
8036 canMove = false;
8037 break;
8038 case atLowerBound:
8039 changeUp += alpha * lower_[iColumn];
8040 // might do other way
8041 value = oldValue + djBasic * alpha;
8042 if (value < -tolerance)
8043 canMove = false;
8044 break;
8045 }
8046 }
8047 if (canMove) {
8048 if (changeUp * djBasic > 1.0e-12 || fabs(changeUp) < 1.0e-8) {
8049 // move
8050 for (i = 0; i < rowLength[iRow]; i++) {
8051 int iColumn = thisIndices[i];
8052 double alpha = thisElements[i];
8053 dj[iColumn] += djBasic * alpha;
8054 }
8055 dj[iSequence] = 0.0;
8056 #ifdef CLP_DEBUG
8057 {
8058 double value5 = 0.0;
8059 int i;
8060 for (i = 0; i < numberRows_ + numberColumns_; i++) {
8061 if (dj[i] < -1.0e-6)
8062 value5 += dj[i] * upper_[i];
8063 else if (dj[i] > 1.0e-6)
8064 value5 += dj[i] * lower_[i];
8065 }
8066 printf("Values objective Value after row %d old dj %g %g\n",
8067 iRow, djBasic, value5);
8068 }
8069 #endif
8070 }
8071 }
8072 }
8073 }
8074 delete[] scaled;
8075 }
nextSuperBasic()8076 int ClpSimplexDual::nextSuperBasic()
8077 {
8078 if (firstFree_ >= 0) {
8079 int returnValue = firstFree_;
8080 int iColumn = firstFree_ + 1;
8081 for (; iColumn < numberRows_ + numberColumns_; iColumn++) {
8082 if (getStatus(iColumn) == isFree)
8083 if (fabs(dj_[iColumn]) > 1.0e2 * dualTolerance_)
8084 break;
8085 }
8086 firstFree_ = iColumn;
8087 if (firstFree_ == numberRows_ + numberColumns_)
8088 firstFree_ = -1;
8089 return returnValue;
8090 } else {
8091 return -1;
8092 }
8093 }
resetFakeBounds(int type)8094 void ClpSimplexDual::resetFakeBounds(int type)
8095 {
8096 if (type == 0) {
8097 // put back original bounds and then check
8098 createRim1(false);
8099 double dummyChangeCost = 0.0;
8100 changeBounds(3, NULL, dummyChangeCost);
8101 } else if (type < 0) {
8102 #ifndef NDEBUG
8103 // just check
8104 int nTotal = numberRows_ + numberColumns_;
8105 double *tempLower = CoinCopyOfArray(lower_, nTotal);
8106 double *tempUpper = CoinCopyOfArray(upper_, nTotal);
8107 int iSequence;
8108 // Get scaled true bounds
8109 if (columnScale_) {
8110 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
8111 // lower
8112 double value = columnLower_[iSequence];
8113 if (value > -1.0e30) {
8114 double multiplier = rhsScale_ * inverseColumnScale_[iSequence];
8115 value *= multiplier;
8116 }
8117 tempLower[iSequence] = value;
8118 // upper
8119 value = columnUpper_[iSequence];
8120 if (value < 1.0e30) {
8121 double multiplier = rhsScale_ * inverseColumnScale_[iSequence];
8122 value *= multiplier;
8123 }
8124 tempUpper[iSequence] = value;
8125 }
8126 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
8127 // lower
8128 double value = rowLower_[iSequence];
8129 if (value > -1.0e30) {
8130 double multiplier = rhsScale_ * rowScale_[iSequence];
8131 value *= multiplier;
8132 }
8133 tempLower[iSequence + numberColumns_] = value;
8134 // upper
8135 value = rowUpper_[iSequence];
8136 if (value < 1.0e30) {
8137 double multiplier = rhsScale_ * rowScale_[iSequence];
8138 value *= multiplier;
8139 }
8140 tempUpper[iSequence + numberColumns_] = value;
8141 }
8142 } else {
8143 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
8144 // lower
8145 tempLower[iSequence] = columnLower_[iSequence];
8146 // upper
8147 tempUpper[iSequence] = columnUpper_[iSequence];
8148 }
8149 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
8150 // lower
8151 tempLower[iSequence + numberColumns_] = rowLower_[iSequence];
8152 // upper
8153 tempUpper[iSequence + numberColumns_] = rowUpper_[iSequence];
8154 }
8155 }
8156 int nFake = 0;
8157 int nErrors = 0;
8158 int nSuperBasic = 0;
8159 int nWarnings = 0;
8160 for (iSequence = 0; iSequence < nTotal; iSequence++) {
8161 FakeBound fakeStatus = getFakeBound(iSequence);
8162 Status status = getStatus(iSequence);
8163 bool isFake = false;
8164 #ifdef CLP_INVESTIGATE
8165 char RC = 'C';
8166 #endif
8167 int jSequence = iSequence;
8168 if (jSequence >= numberColumns_) {
8169 #ifdef CLP_INVESTIGATE
8170 RC = 'R';
8171 #endif
8172 jSequence -= numberColumns_;
8173 }
8174 double lowerValue = tempLower[iSequence];
8175 double upperValue = tempUpper[iSequence];
8176 double value = solution_[iSequence];
8177 CoinRelFltEq equal;
8178 if (status == atUpperBound || status == atLowerBound) {
8179 if (fakeStatus == ClpSimplexDual::upperFake) {
8180 if (!equal(upper_[iSequence], (lowerValue + dualBound_)) || !(equal(upper_[iSequence], value) || equal(lower_[iSequence], value))) {
8181 nErrors++;
8182 #ifdef CLP_INVESTIGATE
8183 printf("** upperFake %c%d %g <= %g <= %g true %g, %g\n",
8184 RC, jSequence, lower_[iSequence], solution_[iSequence],
8185 upper_[iSequence], lowerValue, upperValue);
8186 #endif
8187 }
8188 isFake = true;
8189 ;
8190 } else if (fakeStatus == ClpSimplexDual::lowerFake) {
8191 if (!equal(lower_[iSequence], (upperValue - dualBound_)) || !(equal(upper_[iSequence], value) || equal(lower_[iSequence], value))) {
8192 nErrors++;
8193 #ifdef CLP_INVESTIGATE
8194 printf("** lowerFake %c%d %g <= %g <= %g true %g, %g\n",
8195 RC, jSequence, lower_[iSequence], solution_[iSequence],
8196 upper_[iSequence], lowerValue, upperValue);
8197 #endif
8198 }
8199 isFake = true;
8200 ;
8201 } else if (fakeStatus == ClpSimplexDual::bothFake) {
8202 nWarnings++;
8203 #ifdef CLP_INVESTIGATE
8204 printf("** %d at bothFake?\n", iSequence);
8205 #endif
8206 } else if (upper_[iSequence] - lower_[iSequence] > 2.0 * dualBound_) {
8207 nErrors++;
8208 #ifdef CLP_INVESTIGATE
8209 printf("** noFake! %c%d %g <= %g <= %g true %g, %g\n",
8210 RC, jSequence, lower_[iSequence], solution_[iSequence],
8211 upper_[iSequence], lowerValue, upperValue);
8212 #endif
8213 }
8214 } else if (status == superBasic || status == isFree) {
8215 nSuperBasic++;
8216 //printf("** free or superbasic %c%d %g <= %g <= %g true %g, %g - status %d\n",
8217 // RC,jSequence,lower_[iSequence],solution_[iSequence],
8218 // upper_[iSequence],lowerValue,upperValue,status);
8219 } else if (status == basic) {
8220 bool odd = false;
8221 if (!equal(lower_[iSequence], lowerValue))
8222 odd = true;
8223 if (!equal(upper_[iSequence], upperValue))
8224 odd = true;
8225 if (odd) {
8226 #ifdef CLP_INVESTIGATE
8227 printf("** basic %c%d %g <= %g <= %g true %g, %g\n",
8228 RC, jSequence, lower_[iSequence], solution_[iSequence],
8229 upper_[iSequence], lowerValue, upperValue);
8230 #endif
8231 nWarnings++;
8232 }
8233 } else if (status == isFixed) {
8234 if (!equal(upper_[iSequence], lower_[iSequence])) {
8235 nErrors++;
8236 #ifdef CLP_INVESTIGATE
8237 printf("** fixed! %c%d %g <= %g <= %g true %g, %g\n",
8238 RC, jSequence, lower_[iSequence], solution_[iSequence],
8239 upper_[iSequence], lowerValue, upperValue);
8240 #endif
8241 }
8242 }
8243 if (isFake) {
8244 nFake++;
8245 } else {
8246 if (fakeStatus != ClpSimplexDual::noFake) {
8247 nErrors++;
8248 #ifdef CLP_INVESTIGATE
8249 printf("** bad fake status %c%d %d\n",
8250 RC, jSequence, fakeStatus);
8251 #endif
8252 }
8253 }
8254 }
8255 if (nFake != numberFake_) {
8256 #ifdef CLP_INVESTIGATE
8257 printf("nfake %d numberFake %d\n", nFake, numberFake_);
8258 #endif
8259 nErrors++;
8260 }
8261 if (nErrors || type <= -1000) {
8262 #ifdef CLP_INVESTIGATE
8263 printf("%d errors, %d warnings, %d free/superbasic, %d fake\n",
8264 nErrors, nWarnings, nSuperBasic, numberFake_);
8265 printf("dualBound %g\n",
8266 dualBound_);
8267 #endif
8268 if (type <= -1000) {
8269 iSequence = -type;
8270 iSequence -= 1000;
8271 #ifdef CLP_INVESTIGATE
8272 char RC = 'C';
8273 #endif
8274 int jSequence = iSequence;
8275 if (jSequence >= numberColumns_) {
8276 #ifdef CLP_INVESTIGATE
8277 RC = 'R';
8278 #endif
8279 jSequence -= numberColumns_;
8280 }
8281 #ifdef CLP_INVESTIGATE
8282 double lowerValue = tempLower[iSequence];
8283 double upperValue = tempUpper[iSequence];
8284 printf("*** movement>1.0e30 for %c%d %g <= %g <= %g true %g, %g - status %d\n",
8285 RC, jSequence, lower_[iSequence], solution_[iSequence],
8286 upper_[iSequence], lowerValue, upperValue, status_[iSequence]);
8287 #endif
8288 assert(nErrors); // should have been picked up
8289 }
8290 assert(!nErrors);
8291 }
8292 delete[] tempLower;
8293 delete[] tempUpper;
8294 #endif
8295 } else if (lower_) {
8296 // reset using status
8297 int nTotal = numberRows_ + numberColumns_;
8298 int iSequence;
8299 if (columnScale_) {
8300 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
8301 double multiplier = rhsScale_ * inverseColumnScale_[iSequence];
8302 // lower
8303 double value = columnLower_[iSequence];
8304 if (value > -1.0e30) {
8305 value *= multiplier;
8306 }
8307 lower_[iSequence] = value;
8308 // upper
8309 value = columnUpper_[iSequence];
8310 if (value < 1.0e30) {
8311 value *= multiplier;
8312 }
8313 upper_[iSequence] = value;
8314 }
8315 for (iSequence = 0; iSequence < numberRows_; iSequence++) {
8316 // lower
8317 double multiplier = rhsScale_ * rowScale_[iSequence];
8318 double value = rowLower_[iSequence];
8319 if (value > -1.0e30) {
8320 value *= multiplier;
8321 }
8322 lower_[iSequence + numberColumns_] = value;
8323 // upper
8324 value = rowUpper_[iSequence];
8325 if (value < 1.0e30) {
8326 value *= multiplier;
8327 }
8328 upper_[iSequence + numberColumns_] = value;
8329 }
8330 } else {
8331 memcpy(lower_, columnLower_, numberColumns_ * sizeof(double));
8332 memcpy(upper_, columnUpper_, numberColumns_ * sizeof(double));
8333 memcpy(lower_ + numberColumns_, rowLower_, numberRows_ * sizeof(double));
8334 memcpy(upper_ + numberColumns_, rowUpper_, numberRows_ * sizeof(double));
8335 }
8336 numberFake_ = 0;
8337 for (iSequence = 0; iSequence < nTotal; iSequence++) {
8338 FakeBound fakeStatus = getFakeBound(iSequence);
8339 if (fakeStatus != ClpSimplexDual::noFake) {
8340 Status status = getStatus(iSequence);
8341 if (status == basic || status == isFixed) {
8342 setFakeBound(iSequence, ClpSimplexDual::noFake);
8343 continue;
8344 }
8345 double lowerValue = lower_[iSequence];
8346 double upperValue = upper_[iSequence];
8347 double value = solution_[iSequence];
8348 numberFake_++;
8349 if (fakeStatus == ClpSimplexDual::upperFake) {
8350 upper_[iSequence] = lowerValue + dualBound_;
8351 if (status == ClpSimplex::atLowerBound) {
8352 solution_[iSequence] = lowerValue;
8353 } else if (status == ClpSimplex::atUpperBound) {
8354 solution_[iSequence] = upper_[iSequence];
8355 } else {
8356 printf("Unknown status %d for variable %d in %s line %d\n",
8357 status, iSequence, __FILE__, __LINE__);
8358 abort();
8359 }
8360 } else if (fakeStatus == ClpSimplexDual::lowerFake) {
8361 lower_[iSequence] = upperValue - dualBound_;
8362 if (status == ClpSimplex::atLowerBound) {
8363 solution_[iSequence] = lower_[iSequence];
8364 } else if (status == ClpSimplex::atUpperBound) {
8365 solution_[iSequence] = upperValue;
8366 } else {
8367 printf("Unknown status %d for variable %d in %s line %d\n",
8368 status, iSequence, __FILE__, __LINE__);
8369 abort();
8370 }
8371 } else {
8372 assert(fakeStatus == ClpSimplexDual::bothFake);
8373 if (status == ClpSimplex::atLowerBound) {
8374 lower_[iSequence] = value;
8375 upper_[iSequence] = value + dualBound_;
8376 } else if (status == ClpSimplex::atUpperBound) {
8377 upper_[iSequence] = value;
8378 lower_[iSequence] = value - dualBound_;
8379 } else if (status == ClpSimplex::isFree || status == ClpSimplex::superBasic) {
8380 lower_[iSequence] = value - 0.5 * dualBound_;
8381 upper_[iSequence] = value + 0.5 * dualBound_;
8382 } else {
8383 printf("Unknown status %d for variable %d in %s line %d\n",
8384 status, iSequence, __FILE__, __LINE__);
8385 abort();
8386 }
8387 }
8388 }
8389 }
8390 #ifndef NDEBUG
8391 } else {
8392 COIN_DETAIL_PRINT(printf("NULL lower\n"));
8393 #endif
8394 }
8395 }
8396
8397 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
8398 */
8399