1 /* $Id: ClpSimplexOther.cpp 2388 2019-01-07 19:04:36Z unxusr $ */
2 // Copyright (C) 2004, International Business Machines
3 // Corporation and others. All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5
6 #include "CoinPragma.hpp"
7
8 #include <math.h>
9
10 #include "CoinHelperFunctions.hpp"
11 #include "ClpSimplexOther.hpp"
12 #include "ClpSimplexDual.hpp"
13 #include "ClpSimplexPrimal.hpp"
14 #include "ClpEventHandler.hpp"
15 #include "ClpHelperFunctions.hpp"
16 #include "ClpFactorization.hpp"
17 #include "ClpDualRowDantzig.hpp"
18 #include "ClpNonLinearCost.hpp"
19 #include "ClpDynamicMatrix.hpp"
20 #include "CoinPackedMatrix.hpp"
21 #include "CoinIndexedVector.hpp"
22 #include "CoinBuild.hpp"
23 #include "CoinMpsIO.hpp"
24 #include "CoinFloatEqual.hpp"
25 #include "ClpMessage.hpp"
26 #include <cfloat>
27 #include <cassert>
28 #include <string>
29 #include <stdio.h>
30 #include <iostream>
31 #ifdef INT_IS_8
32 #define COIN_ANY_BITS_PER_INT 64
33 #define COIN_ANY_SHIFT_PER_INT 6
34 #define COIN_ANY_MASK_PER_INT 0x3f
35 #else
36 #define COIN_ANY_BITS_PER_INT 32
37 #define COIN_ANY_SHIFT_PER_INT 5
38 #define COIN_ANY_MASK_PER_INT 0x1f
39 #endif
40 /* Dual ranging.
41 This computes increase/decrease in cost for each given variable and corresponding
42 sequence numbers which would change basis. Sequence numbers are 0..numberColumns
43 and numberColumns.. for artificials/slacks.
44 For non-basic variables the sequence number will be that of the non-basic variables.
45
46 Up to user to provide correct length arrays.
47
48 */
dualRanging(int numberCheck,const int * which,double * costIncreased,int * sequenceIncreased,double * costDecreased,int * sequenceDecreased,double * valueIncrease,double * valueDecrease)49 void ClpSimplexOther::dualRanging(int numberCheck, const int *which,
50 double *costIncreased, int *sequenceIncreased,
51 double *costDecreased, int *sequenceDecreased,
52 double *valueIncrease, double *valueDecrease)
53 {
54 rowArray_[1]->clear();
55 #ifdef LONG_REGION_2
56 rowArray_[2]->clear();
57 #else
58 columnArray_[1]->clear();
59 #endif
60 // long enough for rows+columns
61 int *backPivot = new int[numberRows_ + numberColumns_];
62 int i;
63 for (i = 0; i < numberRows_ + numberColumns_; i++) {
64 backPivot[i] = -1;
65 }
66 for (i = 0; i < numberRows_; i++) {
67 int iSequence = pivotVariable_[i];
68 backPivot[iSequence] = i;
69 }
70 // dualTolerance may be zero if from CBC. In fact use that fact
71 bool inCBC = !dualTolerance_;
72 if (inCBC)
73 assert(integerType_);
74 dualTolerance_ = dblParam_[ClpDualTolerance];
75 double *arrayX = rowArray_[0]->denseVector();
76 for (i = 0; i < numberCheck; i++) {
77 rowArray_[0]->clear();
78 //rowArray_[0]->checkClear();
79 //rowArray_[1]->checkClear();
80 //columnArray_[1]->checkClear();
81 columnArray_[0]->clear();
82 //columnArray_[0]->checkClear();
83 int iSequence = which[i];
84 if (iSequence < 0) {
85 costIncreased[i] = 0.0;
86 sequenceIncreased[i] = -1;
87 costDecreased[i] = 0.0;
88 sequenceDecreased[i] = -1;
89 continue;
90 }
91 double costIncrease = COIN_DBL_MAX;
92 double costDecrease = COIN_DBL_MAX;
93 int sequenceIncrease = -1;
94 int sequenceDecrease = -1;
95 if (valueIncrease) {
96 assert(valueDecrease);
97 valueIncrease[i] = iSequence < numberColumns_ ? columnActivity_[iSequence] : rowActivity_[iSequence - numberColumns_];
98 valueDecrease[i] = valueIncrease[i];
99 }
100
101 switch (getStatus(iSequence)) {
102
103 case basic: {
104 // non-trvial
105 // Get pivot row
106 int iRow = backPivot[iSequence];
107 assert(iRow >= 0);
108 #ifndef COIN_FAC_NEW
109 double plusOne = 1.0;
110 rowArray_[0]->createPacked(1, &iRow, &plusOne);
111 #else
112 rowArray_[0]->createOneUnpackedElement(iRow, 1.0);
113 #endif
114 factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]);
115 // put row of tableau in rowArray[0] and columnArray[0]
116 matrix_->transposeTimes(this, -1.0,
117 rowArray_[0],
118 #ifdef LONG_REGION_2
119 rowArray_[2],
120 #else
121 columnArray_[1],
122 #endif
123 columnArray_[0]);
124 #ifdef COIN_FAC_NEW
125 assert(!rowArray_[0]->packedMode());
126 #endif
127 double alphaIncrease;
128 double alphaDecrease;
129 // do ratio test up and down
130 checkDualRatios(rowArray_[0], columnArray_[0], costIncrease, sequenceIncrease, alphaIncrease,
131 costDecrease, sequenceDecrease, alphaDecrease);
132 if (!inCBC) {
133 if (valueIncrease) {
134 if (sequenceIncrease >= 0)
135 valueIncrease[i] = primalRanging1(sequenceIncrease, iSequence);
136 if (sequenceDecrease >= 0)
137 valueDecrease[i] = primalRanging1(sequenceDecrease, iSequence);
138 }
139 } else {
140 int number = rowArray_[0]->getNumElements();
141 #ifdef COIN_FAC_NEW
142 const int *index = rowArray_[0]->getIndices();
143 #endif
144 double scale2 = 0.0;
145 int j;
146 for (j = 0; j < number; j++) {
147 #ifndef COIN_FAC_NEW
148 scale2 += arrayX[j] * arrayX[j];
149 #else
150 int iRow = index[j];
151 scale2 += arrayX[iRow] * arrayX[iRow];
152 #endif
153 }
154 scale2 = 1.0 / sqrt(scale2);
155 //valueIncrease[i] = scale2;
156 if (sequenceIncrease >= 0) {
157 double djValue = dj_[sequenceIncrease];
158 if (fabs(djValue) > 10.0 * dualTolerance_) {
159 // we are going to use for cutoff so be exact
160 costIncrease = fabs(djValue / alphaIncrease);
161 /* Not sure this is good idea as I don't think correct e.g.
162 suppose a continuous variable has dj slightly greater. */
163 if (false && sequenceIncrease < numberColumns_ && integerType_[sequenceIncrease]) {
164 // can improve
165 double movement = (columnScale_ == NULL) ? 1.0 : rhsScale_ * inverseColumnScale_[sequenceIncrease];
166 costIncrease = CoinMax(fabs(djValue * movement), costIncrease);
167 }
168 } else {
169 costIncrease = 0.0;
170 }
171 }
172 if (sequenceDecrease >= 0) {
173 double djValue = dj_[sequenceDecrease];
174 if (fabs(djValue) > 10.0 * dualTolerance_) {
175 // we are going to use for cutoff so be exact
176 costDecrease = fabs(djValue / alphaDecrease);
177 if (sequenceDecrease < numberColumns_ && integerType_[sequenceDecrease]) {
178 // can improve
179 double movement = (columnScale_ == NULL) ? 1.0 : rhsScale_ * inverseColumnScale_[sequenceDecrease];
180 costDecrease = CoinMax(fabs(djValue * movement), costDecrease);
181 }
182 } else {
183 costDecrease = 0.0;
184 }
185 }
186 costIncrease *= scale2;
187 costDecrease *= scale2;
188 }
189 } break;
190 case isFixed:
191 break;
192 case isFree:
193 case superBasic:
194 costIncrease = 0.0;
195 costDecrease = 0.0;
196 sequenceIncrease = iSequence;
197 sequenceDecrease = iSequence;
198 break;
199 case atUpperBound:
200 costIncrease = CoinMax(0.0, -dj_[iSequence]);
201 sequenceIncrease = iSequence;
202 if (valueIncrease)
203 valueIncrease[i] = primalRanging1(iSequence, iSequence);
204 break;
205 case atLowerBound:
206 costDecrease = CoinMax(0.0, dj_[iSequence]);
207 sequenceDecrease = iSequence;
208 if (valueIncrease)
209 valueDecrease[i] = primalRanging1(iSequence, iSequence);
210 break;
211 }
212 double scaleFactor;
213 if (rowScale_) {
214 if (iSequence < numberColumns_)
215 scaleFactor = 1.0 / (objectiveScale_ * columnScale_[iSequence]);
216 else
217 scaleFactor = rowScale_[iSequence - numberColumns_] / objectiveScale_;
218 } else {
219 scaleFactor = 1.0 / objectiveScale_;
220 }
221 if (costIncrease < 1.0e30)
222 costIncrease *= scaleFactor;
223 if (costDecrease < 1.0e30)
224 costDecrease *= scaleFactor;
225 if (optimizationDirection_ == 1.0) {
226 costIncreased[i] = costIncrease;
227 sequenceIncreased[i] = sequenceIncrease;
228 costDecreased[i] = costDecrease;
229 sequenceDecreased[i] = sequenceDecrease;
230 } else if (optimizationDirection_ == -1.0) {
231 costIncreased[i] = costDecrease;
232 sequenceIncreased[i] = sequenceDecrease;
233 costDecreased[i] = costIncrease;
234 sequenceDecreased[i] = sequenceIncrease;
235 if (valueIncrease) {
236 double temp = valueIncrease[i];
237 valueIncrease[i] = valueDecrease[i];
238 valueDecrease[i] = temp;
239 }
240 } else if (optimizationDirection_ == 0.0) {
241 // !!!!!! ???
242 costIncreased[i] = COIN_DBL_MAX;
243 sequenceIncreased[i] = -1;
244 costDecreased[i] = COIN_DBL_MAX;
245 sequenceDecreased[i] = -1;
246 } else {
247 abort();
248 }
249 }
250 rowArray_[0]->clear();
251 //rowArray_[1]->clear();
252 //columnArray_[1]->clear();
253 columnArray_[0]->clear();
254 delete[] backPivot;
255 if (!optimizationDirection_)
256 printf("*** ????? Ranging with zero optimization costs\n");
257 }
258 /*
259 Row array has row part of pivot row
260 Column array has column part.
261 This is used in dual ranging
262 */
checkDualRatios(CoinIndexedVector * rowArray,CoinIndexedVector * columnArray,double & costIncrease,int & sequenceIncrease,double & alphaIncrease,double & costDecrease,int & sequenceDecrease,double & alphaDecrease)263 void ClpSimplexOther::checkDualRatios(CoinIndexedVector *rowArray,
264 CoinIndexedVector *columnArray,
265 double &costIncrease, int &sequenceIncrease, double &alphaIncrease,
266 double &costDecrease, int &sequenceDecrease, double &alphaDecrease)
267 {
268 double acceptablePivot = 1.0e-9;
269 double *work;
270 int number;
271 int *which;
272 int iSection;
273
274 double thetaDown = 1.0e31;
275 double thetaUp = 1.0e31;
276 int sequenceDown = -1;
277 int sequenceUp = -1;
278 double alphaDown = 0.0;
279 double alphaUp = 0.0;
280
281 int addSequence;
282
283 for (iSection = 0; iSection < 2; iSection++) {
284
285 int i;
286 if (!iSection) {
287 work = rowArray->denseVector();
288 number = rowArray->getNumElements();
289 which = rowArray->getIndices();
290 addSequence = numberColumns_;
291 } else {
292 work = columnArray->denseVector();
293 number = columnArray->getNumElements();
294 which = columnArray->getIndices();
295 addSequence = 0;
296 }
297
298 for (i = 0; i < number; i++) {
299 int iSequence = which[i];
300 int iSequence2 = iSequence + addSequence;
301 #ifndef COIN_FAC_NEW
302 double alpha = work[i];
303 #else
304 double alpha = !addSequence ? work[i] : work[iSequence];
305 #endif
306 if (fabs(alpha) < acceptablePivot)
307 continue;
308 double oldValue = dj_[iSequence2];
309
310 switch (getStatus(iSequence2)) {
311
312 case basic:
313 break;
314 case ClpSimplex::isFixed:
315 break;
316 case isFree:
317 case superBasic:
318 // treat dj as if zero
319 thetaDown = 0.0;
320 thetaUp = 0.0;
321 sequenceDown = iSequence2;
322 sequenceUp = iSequence2;
323 break;
324 case atUpperBound:
325 if (alpha > 0.0) {
326 // test up
327 if (oldValue + thetaUp * alpha > dualTolerance_) {
328 thetaUp = (dualTolerance_ - oldValue) / alpha;
329 sequenceUp = iSequence2;
330 alphaUp = alpha;
331 }
332 } else {
333 // test down
334 if (oldValue - thetaDown * alpha > dualTolerance_) {
335 thetaDown = -(dualTolerance_ - oldValue) / alpha;
336 sequenceDown = iSequence2;
337 alphaDown = alpha;
338 }
339 }
340 break;
341 case atLowerBound:
342 if (alpha < 0.0) {
343 // test up
344 if (oldValue + thetaUp * alpha < -dualTolerance_) {
345 thetaUp = -(dualTolerance_ + oldValue) / alpha;
346 sequenceUp = iSequence2;
347 alphaUp = alpha;
348 }
349 } else {
350 // test down
351 if (oldValue - thetaDown * alpha < -dualTolerance_) {
352 thetaDown = (dualTolerance_ + oldValue) / alpha;
353 sequenceDown = iSequence2;
354 alphaDown = alpha;
355 }
356 }
357 break;
358 }
359 }
360 }
361 if (sequenceUp >= 0) {
362 costIncrease = thetaUp;
363 sequenceIncrease = sequenceUp;
364 alphaIncrease = alphaUp;
365 }
366 if (sequenceDown >= 0) {
367 costDecrease = thetaDown;
368 sequenceDecrease = sequenceDown;
369 alphaDecrease = alphaDown;
370 }
371 }
372 /** Primal ranging.
373 This computes increase/decrease in value for each given variable and corresponding
374 sequence numbers which would change basis. Sequence numbers are 0..numberColumns
375 and numberColumns.. for artificials/slacks.
376 For basic variables the sequence number will be that of the basic variables.
377
378 Up to user to provide correct length arrays.
379
380 When here - guaranteed optimal
381 */
primalRanging(int numberCheck,const int * which,double * valueIncreased,int * sequenceIncreased,double * valueDecreased,int * sequenceDecreased)382 void ClpSimplexOther::primalRanging(int numberCheck, const int *which,
383 double *valueIncreased, int *sequenceIncreased,
384 double *valueDecreased, int *sequenceDecreased)
385 {
386 rowArray_[0]->clear();
387 rowArray_[1]->clear();
388 lowerIn_ = -COIN_DBL_MAX;
389 upperIn_ = COIN_DBL_MAX;
390 valueIn_ = 0.0;
391 for (int i = 0; i < numberCheck; i++) {
392 int iSequence = which[i];
393 double valueIncrease = COIN_DBL_MAX;
394 double valueDecrease = COIN_DBL_MAX;
395 int sequenceIncrease = -1;
396 int sequenceDecrease = -1;
397
398 switch (getStatus(iSequence)) {
399
400 case basic:
401 case isFree:
402 case superBasic:
403 // Easy
404 valueDecrease = CoinMax(0.0, upper_[iSequence] - solution_[iSequence]);
405 valueIncrease = CoinMax(0.0, solution_[iSequence] - lower_[iSequence]);
406 sequenceDecrease = iSequence;
407 sequenceIncrease = iSequence;
408 break;
409 case isFixed:
410 case atUpperBound:
411 case atLowerBound: {
412 // Non trivial
413 // Other bound is ignored
414 #ifndef COIN_FAC_NEW
415 unpackPacked(rowArray_[1], iSequence);
416 #else
417 unpack(rowArray_[1], iSequence);
418 #endif
419 factorization_->updateColumn(rowArray_[2], rowArray_[1]);
420 // Get extra rows
421 matrix_->extendUpdated(this, rowArray_[1], 0);
422 // do ratio test
423 checkPrimalRatios(rowArray_[1], 1);
424 if (pivotRow_ >= 0) {
425 valueIncrease = theta_;
426 sequenceIncrease = pivotVariable_[pivotRow_];
427 }
428 checkPrimalRatios(rowArray_[1], -1);
429 if (pivotRow_ >= 0) {
430 valueDecrease = theta_;
431 sequenceDecrease = pivotVariable_[pivotRow_];
432 }
433 rowArray_[1]->clear();
434 } break;
435 }
436 double scaleFactor;
437 if (rowScale_) {
438 if (iSequence < numberColumns_)
439 scaleFactor = columnScale_[iSequence] / rhsScale_;
440 else
441 scaleFactor = 1.0 / (rowScale_[iSequence - numberColumns_] * rhsScale_);
442 } else {
443 scaleFactor = 1.0 / rhsScale_;
444 }
445 if (valueIncrease < 1.0e30)
446 valueIncrease *= scaleFactor;
447 else
448 valueIncrease = COIN_DBL_MAX;
449 if (valueDecrease < 1.0e30)
450 valueDecrease *= scaleFactor;
451 else
452 valueDecrease = COIN_DBL_MAX;
453 valueIncreased[i] = valueIncrease;
454 sequenceIncreased[i] = sequenceIncrease;
455 valueDecreased[i] = valueDecrease;
456 sequenceDecreased[i] = sequenceDecrease;
457 }
458 }
459 // Returns new value of whichOther when whichIn enters basis
460 double
primalRanging1(int whichIn,int whichOther)461 ClpSimplexOther::primalRanging1(int whichIn, int whichOther)
462 {
463 rowArray_[0]->clear();
464 rowArray_[1]->clear();
465 int iSequence = whichIn;
466 double newValue = solution_[whichOther];
467 double alphaOther = 0.0;
468 Status status = getStatus(iSequence);
469 assert(status == atLowerBound || status == atUpperBound);
470 int wayIn = (status == atLowerBound) ? 1 : -1;
471
472 switch (getStatus(iSequence)) {
473
474 case basic:
475 case isFree:
476 case superBasic:
477 assert(whichIn == whichOther);
478 // Easy
479 newValue = wayIn > 0 ? upper_[iSequence] : lower_[iSequence];
480 break;
481 case isFixed:
482 case atUpperBound:
483 case atLowerBound:
484 // Non trivial
485 {
486 // Other bound is ignored
487 #ifndef COIN_FAC_NEW
488 unpackPacked(rowArray_[1], iSequence);
489 #else
490 unpack(rowArray_[1], iSequence);
491 #endif
492 factorization_->updateColumn(rowArray_[2], rowArray_[1]);
493 // Get extra rows
494 matrix_->extendUpdated(this, rowArray_[1], 0);
495 // do ratio test
496 double acceptablePivot = 1.0e-7;
497 double *work = rowArray_[1]->denseVector();
498 int number = rowArray_[1]->getNumElements();
499 int *which = rowArray_[1]->getIndices();
500
501 // we may need to swap sign
502 double way = wayIn;
503 double theta = 1.0e30;
504 for (int iIndex = 0; iIndex < number; iIndex++) {
505
506 int iRow = which[iIndex];
507 #ifndef COIN_FAC_NEW
508 double alpha = work[iIndex] * way;
509 #else
510 double alpha = work[iRow] * way;
511 #endif
512 int iPivot = pivotVariable_[iRow];
513 if (iPivot == whichOther) {
514 alphaOther = alpha;
515 continue;
516 }
517 double oldValue = solution_[iPivot];
518 if (fabs(alpha) > acceptablePivot) {
519 if (alpha > 0.0) {
520 // basic variable going towards lower bound
521 double bound = lower_[iPivot];
522 oldValue -= bound;
523 if (oldValue - theta * alpha < 0.0) {
524 theta = CoinMax(0.0, oldValue / alpha);
525 }
526 } else {
527 // basic variable going towards upper bound
528 double bound = upper_[iPivot];
529 oldValue = oldValue - bound;
530 if (oldValue - theta * alpha > 0.0) {
531 theta = CoinMax(0.0, oldValue / alpha);
532 }
533 }
534 }
535 }
536 if (whichIn != whichOther) {
537 if (theta < 1.0e30)
538 newValue -= theta * alphaOther;
539 else
540 newValue = alphaOther > 0.0 ? -1.0e30 : 1.0e30;
541 } else {
542 newValue += theta * wayIn;
543 }
544 }
545 rowArray_[1]->clear();
546 break;
547 }
548 double scaleFactor;
549 if (rowScale_) {
550 if (whichOther < numberColumns_)
551 scaleFactor = columnScale_[whichOther] / rhsScale_;
552 else
553 scaleFactor = 1.0 / (rowScale_[whichOther - numberColumns_] * rhsScale_);
554 } else {
555 scaleFactor = 1.0 / rhsScale_;
556 }
557 if (newValue < 1.0e29)
558 if (newValue > -1.0e29)
559 newValue *= scaleFactor;
560 else
561 newValue = -COIN_DBL_MAX;
562 else
563 newValue = COIN_DBL_MAX;
564 return newValue;
565 }
566 /*
567 Row array has pivot column
568 This is used in primal ranging
569 */
checkPrimalRatios(CoinIndexedVector * rowArray,int direction)570 void ClpSimplexOther::checkPrimalRatios(CoinIndexedVector *rowArray,
571 int direction)
572 {
573 // sequence stays as row number until end
574 pivotRow_ = -1;
575 double acceptablePivot = 1.0e-7;
576 double *work = rowArray->denseVector();
577 int number = rowArray->getNumElements();
578 int *which = rowArray->getIndices();
579
580 // we need to swap sign if going down
581 double way = direction;
582 theta_ = 1.0e30;
583 for (int iIndex = 0; iIndex < number; iIndex++) {
584
585 int iRow = which[iIndex];
586 #ifndef COIN_FAC_NEW
587 double alpha = work[iIndex] * way;
588 #else
589 double alpha = work[iRow] * way;
590 #endif
591 int iPivot = pivotVariable_[iRow];
592 double oldValue = solution_[iPivot];
593 if (fabs(alpha) > acceptablePivot) {
594 if (alpha > 0.0) {
595 // basic variable going towards lower bound
596 double bound = lower_[iPivot];
597 oldValue -= bound;
598 if (oldValue - theta_ * alpha < 0.0) {
599 pivotRow_ = iRow;
600 theta_ = CoinMax(0.0, oldValue / alpha);
601 }
602 } else {
603 // basic variable going towards upper bound
604 double bound = upper_[iPivot];
605 oldValue = oldValue - bound;
606 if (oldValue - theta_ * alpha > 0.0) {
607 pivotRow_ = iRow;
608 theta_ = CoinMax(0.0, oldValue / alpha);
609 }
610 }
611 }
612 }
613 }
614 /* Write the basis in MPS format to the specified file.
615 If writeValues true writes values of structurals
616 (and adds VALUES to end of NAME card)
617
618 Row and column names may be null.
619 formatType is
620 <ul>
621 <li> 0 - normal
622 <li> 1 - extra accuracy
623 <li> 2 - IEEE hex (later)
624 </ul>
625
626 Returns non-zero on I/O error
627
628 This is based on code contributed by Thorsten Koch
629 */
writeBasis(const char * filename,bool writeValues,int formatType) const630 int ClpSimplexOther::writeBasis(const char *filename,
631 bool writeValues,
632 int formatType) const
633 {
634 formatType = CoinMax(0, formatType);
635 formatType = CoinMin(2, formatType);
636 if (!writeValues)
637 formatType = 0;
638 // See if INTEL if IEEE
639 if (formatType == 2) {
640 // test intel here and add 1 if not intel
641 double value = 1.0;
642 char x[8];
643 memcpy(x, &value, 8);
644 if (x[0] == 63) {
645 formatType++; // not intel
646 } else {
647 assert(x[0] == 0);
648 }
649 }
650
651 char number[20];
652 FILE *fp = fopen(filename, "w");
653 if (!fp)
654 return -1;
655
656 // NAME card
657
658 // Set locale so won't get , instead of .
659 char *saveLocale = strdup(setlocale(LC_ALL, NULL));
660 setlocale(LC_ALL, "C");
661 if (strcmp(strParam_[ClpProbName].c_str(), "") == 0) {
662 fprintf(fp, "NAME BLANK ");
663 } else {
664 fprintf(fp, "NAME %s ", strParam_[ClpProbName].c_str());
665 }
666 if (formatType >= 2)
667 fprintf(fp, "FREEIEEE");
668 else if (writeValues)
669 fprintf(fp, "VALUES");
670 // finish off name
671 fprintf(fp, "\n");
672 int iRow = 0;
673 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
674 bool printit = false;
675 if (getColumnStatus(iColumn) == ClpSimplex::basic) {
676 printit = true;
677 // Find non basic row
678 for (; iRow < numberRows_; iRow++) {
679 if (getRowStatus(iRow) != ClpSimplex::basic)
680 break;
681 }
682 if (lengthNames_) {
683 if (iRow != numberRows_) {
684 fprintf(fp, " %s %-8s %s",
685 getRowStatus(iRow) == ClpSimplex::atUpperBound ? "XU" : "XL",
686 columnNames_[iColumn].c_str(),
687 rowNames_[iRow].c_str());
688 iRow++;
689 } else {
690 // Allow for too many basics!
691 fprintf(fp, " BS %-8s ",
692 columnNames_[iColumn].c_str());
693 // Dummy row name if values
694 if (writeValues)
695 fprintf(fp, " _dummy_");
696 }
697 } else {
698 // no names
699 if (iRow != numberRows_) {
700 fprintf(fp, " %s C%7.7d R%7.7d",
701 getRowStatus(iRow) == ClpSimplex::atUpperBound ? "XU" : "XL",
702 iColumn, iRow);
703 iRow++;
704 } else {
705 // Allow for too many basics!
706 fprintf(fp, " BS C%7.7d", iColumn);
707 // Dummy row name if values
708 if (writeValues)
709 fprintf(fp, " _dummy_");
710 }
711 }
712 } else {
713 if (getColumnStatus(iColumn) == ClpSimplex::atUpperBound) {
714 printit = true;
715 if (lengthNames_)
716 fprintf(fp, " UL %s", columnNames_[iColumn].c_str());
717 else
718 fprintf(fp, " UL C%7.7d", iColumn);
719 // Dummy row name if values
720 if (writeValues)
721 fprintf(fp, " _dummy_");
722 } else if ((getColumnStatus(iColumn) == ClpSimplex::superBasic || getColumnStatus(iColumn) == ClpSimplex::isFree) && writeValues) {
723 printit = true;
724 if (lengthNames_)
725 fprintf(fp, " BS %s", columnNames_[iColumn].c_str());
726 else
727 fprintf(fp, " BS C%7.7d", iColumn);
728 // Dummy row name if values
729 if (writeValues)
730 fprintf(fp, " _dummy_");
731 }
732 }
733 if (printit && writeValues) {
734 // add value
735 CoinConvertDouble(0, formatType, columnActivity_[iColumn], number);
736 fprintf(fp, " %s", number);
737 }
738 if (printit)
739 fprintf(fp, "\n");
740 }
741 fprintf(fp, "ENDATA\n");
742 fclose(fp);
743 setlocale(LC_ALL, saveLocale);
744 free(saveLocale);
745 return 0;
746 }
747 // Read a basis from the given filename
readBasis(const char * fileName)748 int ClpSimplexOther::readBasis(const char *fileName)
749 {
750 int status = 0;
751 if (strcmp(fileName, "-") != 0 && strcmp(fileName, "stdin") != 0) {
752 FILE *fp = fopen(fileName, "r");
753 if (fp) {
754 // can open - lets go for it
755 fclose(fp);
756 } else {
757 handler_->message(CLP_UNABLE_OPEN, messages_)
758 << fileName << CoinMessageEol;
759 return -1;
760 }
761 }
762 CoinMpsIO m;
763 m.passInMessageHandler(handler_);
764 *m.messagesPointer() = coinMessages();
765 bool savePrefix = m.messageHandler()->prefix();
766 m.messageHandler()->setPrefix(handler_->prefix());
767 status = m.readBasis(fileName, "", columnActivity_, status_ + numberColumns_,
768 status_,
769 columnNames_, numberColumns_,
770 rowNames_, numberRows_);
771 m.messageHandler()->setPrefix(savePrefix);
772 if (status >= 0) {
773 if (!status) {
774 // set values
775 int iColumn, iRow;
776 for (iRow = 0; iRow < numberRows_; iRow++) {
777 if (getRowStatus(iRow) == atLowerBound)
778 rowActivity_[iRow] = rowLower_[iRow];
779 else if (getRowStatus(iRow) == atUpperBound)
780 rowActivity_[iRow] = rowUpper_[iRow];
781 }
782 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
783 if (getColumnStatus(iColumn) == atLowerBound)
784 columnActivity_[iColumn] = columnLower_[iColumn];
785 else if (getColumnStatus(iColumn) == atUpperBound)
786 columnActivity_[iColumn] = columnUpper_[iColumn];
787 }
788 } else {
789 memset(rowActivity_, 0, numberRows_ * sizeof(double));
790 matrix_->times(-1.0, columnActivity_, rowActivity_);
791 }
792 } else {
793 // errors
794 handler_->message(CLP_IMPORT_ERRORS, messages_)
795 << status << fileName << CoinMessageEol;
796 }
797 return status;
798 }
799 /* Creates dual of a problem if looks plausible
800 (defaults will always create model)
801 fractionRowRanges is fraction of rows allowed to have ranges
802 fractionColumnRanges is fraction of columns allowed to have ranges
803 */
804 ClpSimplex *
dualOfModel(double fractionRowRanges,double fractionColumnRanges) const805 ClpSimplexOther::dualOfModel(double fractionRowRanges, double fractionColumnRanges) const
806 {
807 const ClpSimplex *model2 = static_cast< const ClpSimplex * >(this);
808 bool changed = false;
809 int numberChanged = 0;
810 int numberFreeColumnsInPrimal = 0;
811 int iColumn;
812 // check if we need to change bounds to rows
813 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
814 if (columnUpper_[iColumn] < 1.0e20) {
815 if (columnLower_[iColumn] > -1.0e20) {
816 changed = true;
817 numberChanged++;
818 }
819 } else if (columnLower_[iColumn] < -1.0e20) {
820 numberFreeColumnsInPrimal++;
821 }
822 }
823 int iRow;
824 int numberExtraRows = 0;
825 int numberFreeColumnsInDual = 0;
826 if (numberChanged <= fractionColumnRanges * numberColumns_) {
827 for (iRow = 0; iRow < numberRows_; iRow++) {
828 if (rowLower_[iRow] > -1.0e20 && rowUpper_[iRow] < 1.0e20) {
829 if (rowUpper_[iRow] != rowLower_[iRow])
830 numberExtraRows++;
831 else
832 numberFreeColumnsInDual++;
833 }
834 }
835 if (numberExtraRows > fractionRowRanges * numberRows_)
836 return NULL;
837 } else {
838 return NULL;
839 }
840 printf("would have %d free columns in primal, %d in dual\n",
841 numberFreeColumnsInPrimal, numberFreeColumnsInDual);
842 if (4 * (numberFreeColumnsInDual - numberFreeColumnsInPrimal) > numberColumns_ && fractionRowRanges < 1.0)
843 return NULL; //dangerous (well anyway in dual)
844 if (changed) {
845 ClpSimplex *model3 = new ClpSimplex(*model2);
846 CoinBuild build;
847 double one = 1.0;
848 int numberColumns = model3->numberColumns();
849 const double *columnLower = model3->columnLower();
850 const double *columnUpper = model3->columnUpper();
851 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
852 if (columnUpper[iColumn] < 1.0e20 && columnLower[iColumn] > -1.0e20) {
853 if (fabs(columnLower[iColumn]) < fabs(columnUpper[iColumn])) {
854 double value = columnUpper[iColumn];
855 model3->setColumnUpper(iColumn, COIN_DBL_MAX);
856 build.addRow(1, &iColumn, &one, -COIN_DBL_MAX, value);
857 } else {
858 double value = columnLower[iColumn];
859 model3->setColumnLower(iColumn, -COIN_DBL_MAX);
860 build.addRow(1, &iColumn, &one, value, COIN_DBL_MAX);
861 }
862 }
863 }
864 model3->addRows(build);
865 model2 = model3;
866 }
867 int numberColumns = model2->numberColumns();
868 const double *columnLower = model2->columnLower();
869 const double *columnUpper = model2->columnUpper();
870 int numberRows = model2->numberRows();
871 double *rowLower = CoinCopyOfArray(model2->rowLower(), numberRows);
872 double *rowUpper = CoinCopyOfArray(model2->rowUpper(), numberRows);
873
874 const double *objective = model2->objective();
875 CoinPackedMatrix *matrix = model2->matrix();
876 // get transpose
877 CoinPackedMatrix rowCopy = *matrix;
878 const int *row = matrix->getIndices();
879 const int *columnLength = matrix->getVectorLengths();
880 const CoinBigIndex *columnStart = matrix->getVectorStarts();
881 const double *elementByColumn = matrix->getElements();
882 double objOffset = 0.0;
883 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
884 double offset = 0.0;
885 double objValue = optimizationDirection_ * objective[iColumn];
886 if (columnUpper[iColumn] > 1.0e20) {
887 if (columnLower[iColumn] > -1.0e20)
888 offset = columnLower[iColumn];
889 } else if (columnLower[iColumn] < -1.0e20) {
890 offset = columnUpper[iColumn];
891 } else {
892 // taken care of before
893 abort();
894 }
895 if (offset) {
896 objOffset += offset * objValue;
897 for (CoinBigIndex j = columnStart[iColumn];
898 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
899 int iRow = row[j];
900 if (rowLower[iRow] > -1.0e20)
901 rowLower[iRow] -= offset * elementByColumn[j];
902 if (rowUpper[iRow] < 1.0e20)
903 rowUpper[iRow] -= offset * elementByColumn[j];
904 }
905 }
906 }
907 int *which = new int[numberRows + numberExtraRows];
908 rowCopy.reverseOrdering();
909 rowCopy.transpose();
910 double *fromRowsLower = new double[numberRows + numberExtraRows];
911 double *fromRowsUpper = new double[numberRows + numberExtraRows];
912 double *newObjective = new double[numberRows + numberExtraRows];
913 double *fromColumnsLower = new double[numberColumns];
914 double *fromColumnsUpper = new double[numberColumns];
915 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
916 double objValue = optimizationDirection_ * objective[iColumn];
917 // Offset is already in
918 if (columnUpper[iColumn] > 1.0e20) {
919 if (columnLower[iColumn] > -1.0e20) {
920 fromColumnsLower[iColumn] = -COIN_DBL_MAX;
921 fromColumnsUpper[iColumn] = objValue;
922 } else {
923 // free
924 fromColumnsLower[iColumn] = objValue;
925 fromColumnsUpper[iColumn] = objValue;
926 }
927 } else if (columnLower[iColumn] < -1.0e20) {
928 fromColumnsLower[iColumn] = objValue;
929 fromColumnsUpper[iColumn] = COIN_DBL_MAX;
930 } else {
931 abort();
932 }
933 }
934 int kRow = 0;
935 int kExtraRow = numberRows;
936 for (iRow = 0; iRow < numberRows; iRow++) {
937 if (rowLower[iRow] < -1.0e20) {
938 assert(rowUpper[iRow] < 1.0e20);
939 newObjective[kRow] = -rowUpper[iRow];
940 fromRowsLower[kRow] = -COIN_DBL_MAX;
941 fromRowsUpper[kRow] = 0.0;
942 which[kRow] = iRow;
943 kRow++;
944 } else if (rowUpper[iRow] > 1.0e20) {
945 newObjective[kRow] = -rowLower[iRow];
946 fromRowsLower[kRow] = 0.0;
947 fromRowsUpper[kRow] = COIN_DBL_MAX;
948 which[kRow] = iRow;
949 kRow++;
950 } else {
951 if (rowUpper[iRow] == rowLower[iRow]) {
952 newObjective[kRow] = -rowLower[iRow];
953 fromRowsLower[kRow] = -COIN_DBL_MAX;
954 ;
955 fromRowsUpper[kRow] = COIN_DBL_MAX;
956 which[kRow] = iRow;
957 kRow++;
958 } else {
959 // range
960 newObjective[kRow] = -rowUpper[iRow];
961 fromRowsLower[kRow] = -COIN_DBL_MAX;
962 fromRowsUpper[kRow] = 0.0;
963 which[kRow] = iRow;
964 kRow++;
965 newObjective[kExtraRow] = -rowLower[iRow];
966 fromRowsLower[kExtraRow] = 0.0;
967 fromRowsUpper[kExtraRow] = COIN_DBL_MAX;
968 which[kExtraRow] = iRow;
969 kExtraRow++;
970 }
971 }
972 }
973 if (numberExtraRows) {
974 CoinPackedMatrix newCopy;
975 newCopy.setExtraGap(0.0);
976 newCopy.setExtraMajor(0.0);
977 newCopy.submatrixOfWithDuplicates(rowCopy, kExtraRow, which);
978 rowCopy = newCopy;
979 }
980 ClpSimplex *modelDual = new ClpSimplex();
981 modelDual->passInEventHandler(eventHandler_);
982 modelDual->loadProblem(rowCopy, fromRowsLower, fromRowsUpper, newObjective,
983 fromColumnsLower, fromColumnsUpper);
984 modelDual->setObjectiveOffset(objOffset);
985 modelDual->setDualBound(model2->dualBound());
986 modelDual->setInfeasibilityCost(model2->infeasibilityCost());
987 modelDual->setDualTolerance(model2->dualTolerance());
988 modelDual->setPrimalTolerance(model2->primalTolerance());
989 modelDual->setPerturbation(model2->perturbation());
990 modelDual->setSpecialOptions(model2->specialOptions());
991 modelDual->setMoreSpecialOptions(model2->moreSpecialOptions());
992 modelDual->setMaximumIterations(model2->maximumIterations());
993 modelDual->setFactorizationFrequency(model2->factorizationFrequency());
994 modelDual->setLogLevel(model2->logLevel());
995 delete[] fromRowsLower;
996 delete[] fromRowsUpper;
997 delete[] fromColumnsLower;
998 delete[] fromColumnsUpper;
999 delete[] newObjective;
1000 delete[] which;
1001 delete[] rowLower;
1002 delete[] rowUpper;
1003 if (changed)
1004 delete model2;
1005 modelDual->createStatus();
1006 return modelDual;
1007 }
1008 // Restores solution from dualized problem
restoreFromDual(const ClpSimplex * dualProblem,bool checkAccuracy)1009 int ClpSimplexOther::restoreFromDual(const ClpSimplex *dualProblem,
1010 bool checkAccuracy)
1011 {
1012 int returnCode = 0;
1013 ;
1014 createStatus();
1015 // Number of rows in dual problem was original number of columns
1016 assert(numberColumns_ == dualProblem->numberRows());
1017 // If slack on d-row basic then column at bound otherwise column basic
1018 // If d-column basic then rhs tight
1019 int numberBasic = 0;
1020 int iRow, iColumn = 0;
1021 // Get number of extra rows from ranges
1022 int numberExtraRows = 0;
1023 for (iRow = 0; iRow < numberRows_; iRow++) {
1024 if (rowLower_[iRow] > -1.0e20 && rowUpper_[iRow] < 1.0e20) {
1025 if (rowUpper_[iRow] != rowLower_[iRow])
1026 numberExtraRows++;
1027 }
1028 }
1029 const double *objective = this->objective();
1030 const double *dualDual = dualProblem->dualRowSolution();
1031 const double *dualDj = dualProblem->dualColumnSolution();
1032 const double *dualSol = dualProblem->primalColumnSolution();
1033 const double *dualActs = dualProblem->primalRowSolution();
1034 #if 0
1035 ClpSimplex thisCopy = *this;
1036 thisCopy.dual(); // for testing
1037 const double * primalDual = thisCopy.dualRowSolution();
1038 const double * primalDj = thisCopy.dualColumnSolution();
1039 const double * primalSol = thisCopy.primalColumnSolution();
1040 const double * primalActs = thisCopy.primalRowSolution();
1041 char ss[] = {'F', 'B', 'U', 'L', 'S', 'F'};
1042 printf ("Dual problem row info %d rows\n", dualProblem->numberRows());
1043 for (iRow = 0; iRow < dualProblem->numberRows(); iRow++)
1044 printf("%d at %c primal %g dual %g\n",
1045 iRow, ss[dualProblem->getRowStatus(iRow)],
1046 dualActs[iRow], dualDual[iRow]);
1047 printf ("Dual problem column info %d columns\n", dualProblem->numberColumns());
1048 for (iColumn = 0; iColumn < dualProblem->numberColumns(); iColumn++)
1049 printf("%d at %c primal %g dual %g\n",
1050 iColumn, ss[dualProblem->getColumnStatus(iColumn)],
1051 dualSol[iColumn], dualDj[iColumn]);
1052 printf ("Primal problem row info %d rows\n", thisCopy.numberRows());
1053 for (iRow = 0; iRow < thisCopy.numberRows(); iRow++)
1054 printf("%d at %c primal %g dual %g\n",
1055 iRow, ss[thisCopy.getRowStatus(iRow)],
1056 primalActs[iRow], primalDual[iRow]);
1057 printf ("Primal problem column info %d columns\n", thisCopy.numberColumns());
1058 for (iColumn = 0; iColumn < thisCopy.numberColumns(); iColumn++)
1059 printf("%d at %c primal %g dual %g\n",
1060 iColumn, ss[thisCopy.getColumnStatus(iColumn)],
1061 primalSol[iColumn], primalDj[iColumn]);
1062 #endif
1063 // position at bound information
1064 int jColumn = numberRows_;
1065 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1066 double objValue = optimizationDirection_ * objective[iColumn];
1067 Status status = dualProblem->getRowStatus(iColumn);
1068 double otherValue = COIN_DBL_MAX;
1069 if (columnUpper_[iColumn] < 1.0e20 && columnLower_[iColumn] > -1.0e20) {
1070 if (fabs(columnLower_[iColumn]) < fabs(columnUpper_[iColumn])) {
1071 otherValue = columnUpper_[iColumn] + dualDj[jColumn];
1072 } else {
1073 otherValue = columnLower_[iColumn] + dualDj[jColumn];
1074 }
1075 jColumn++;
1076 }
1077 if (status == basic) {
1078 // column is at bound
1079 if (otherValue == COIN_DBL_MAX) {
1080 reducedCost_[iColumn] = objValue - dualActs[iColumn];
1081 if (columnUpper_[iColumn] > 1.0e20) {
1082 if (columnLower_[iColumn] > -1.0e20) {
1083 if (columnUpper_[iColumn] > columnLower_[iColumn])
1084 setColumnStatus(iColumn, atLowerBound);
1085 else
1086 setColumnStatus(iColumn, isFixed);
1087 columnActivity_[iColumn] = columnLower_[iColumn];
1088 } else {
1089 // free
1090 setColumnStatus(iColumn, isFree);
1091 columnActivity_[iColumn] = 0.0;
1092 }
1093 } else {
1094 setColumnStatus(iColumn, atUpperBound);
1095 columnActivity_[iColumn] = columnUpper_[iColumn];
1096 }
1097 } else {
1098 reducedCost_[iColumn] = objValue - dualActs[iColumn];
1099 //printf("other dual sol %g\n",otherValue);
1100 if (fabs(otherValue - columnLower_[iColumn]) < 1.0e-5) {
1101 if (columnUpper_[iColumn] > columnLower_[iColumn])
1102 setColumnStatus(iColumn, atLowerBound);
1103 else
1104 setColumnStatus(iColumn, isFixed);
1105 columnActivity_[iColumn] = columnLower_[iColumn];
1106 } else if (fabs(otherValue - columnUpper_[iColumn]) < 1.0e-5) {
1107 if (columnUpper_[iColumn] > columnLower_[iColumn])
1108 setColumnStatus(iColumn, atUpperBound);
1109 else
1110 setColumnStatus(iColumn, isFixed);
1111 columnActivity_[iColumn] = columnUpper_[iColumn];
1112 } else {
1113 setColumnStatus(iColumn, superBasic);
1114 columnActivity_[iColumn] = otherValue;
1115 }
1116 }
1117 } else {
1118 if (otherValue == COIN_DBL_MAX) {
1119 // column basic
1120 setColumnStatus(iColumn, basic);
1121 numberBasic++;
1122 if (columnLower_[iColumn] > -1.0e20) {
1123 columnActivity_[iColumn] = -dualDual[iColumn] + columnLower_[iColumn];
1124 } else if (columnUpper_[iColumn] < 1.0e20) {
1125 columnActivity_[iColumn] = -dualDual[iColumn] + columnUpper_[iColumn];
1126 } else {
1127 columnActivity_[iColumn] = -dualDual[iColumn];
1128 }
1129 reducedCost_[iColumn] = 0.0;
1130 } else {
1131 // may be at other bound
1132 //printf("xx %d %g jcol %d\n",iColumn,otherValue,jColumn-1);
1133 if (dualProblem->getColumnStatus(jColumn - 1) != basic) {
1134 // column basic
1135 setColumnStatus(iColumn, basic);
1136 numberBasic++;
1137 //printf("Col %d otherV %g dualDual %g\n",iColumn,
1138 // otherValue,dualDual[iColumn]);
1139 columnActivity_[iColumn] = -dualDual[iColumn];
1140 columnActivity_[iColumn] = otherValue;
1141 reducedCost_[iColumn] = 0.0;
1142 } else {
1143 reducedCost_[iColumn] = objValue - dualActs[iColumn];
1144 if (fabs(otherValue - columnLower_[iColumn]) < 1.0e-5) {
1145 if (columnUpper_[iColumn] > columnLower_[iColumn])
1146 setColumnStatus(iColumn, atLowerBound);
1147 else
1148 setColumnStatus(iColumn, isFixed);
1149 columnActivity_[iColumn] = columnLower_[iColumn];
1150 } else if (fabs(otherValue - columnUpper_[iColumn]) < 1.0e-5) {
1151 if (columnUpper_[iColumn] > columnLower_[iColumn])
1152 setColumnStatus(iColumn, atUpperBound);
1153 else
1154 setColumnStatus(iColumn, isFixed);
1155 columnActivity_[iColumn] = columnUpper_[iColumn];
1156 } else {
1157 setColumnStatus(iColumn, superBasic);
1158 columnActivity_[iColumn] = otherValue;
1159 }
1160 }
1161 }
1162 }
1163 }
1164 // now rows
1165 int kExtraRow = jColumn;
1166 int numberRanges = 0;
1167 for (iRow = 0; iRow < numberRows_; iRow++) {
1168 Status status = dualProblem->getColumnStatus(iRow);
1169 if (status == basic) {
1170 // row is at bound
1171 dual_[iRow] = dualSol[iRow];
1172 ;
1173 } else {
1174 // row basic
1175 setRowStatus(iRow, basic);
1176 numberBasic++;
1177 dual_[iRow] = 0.0;
1178 }
1179 if (rowLower_[iRow] < -1.0e20) {
1180 if (status == basic) {
1181 rowActivity_[iRow] = rowUpper_[iRow];
1182 setRowStatus(iRow, atUpperBound);
1183 } else {
1184 // might be stopped assert (dualDj[iRow] < 1.0e-5);
1185 rowActivity_[iRow] = rowUpper_[iRow] + dualDj[iRow];
1186 }
1187 } else if (rowUpper_[iRow] > 1.0e20) {
1188 if (status == basic) {
1189 rowActivity_[iRow] = rowLower_[iRow];
1190 setRowStatus(iRow, atLowerBound);
1191 } else {
1192 rowActivity_[iRow] = rowLower_[iRow] + dualDj[iRow];
1193 // might be stopped assert (dualDj[iRow] > -1.0e-5);
1194 }
1195 } else {
1196 if (rowUpper_[iRow] == rowLower_[iRow]) {
1197 rowActivity_[iRow] = rowLower_[iRow];
1198 if (status == basic) {
1199 setRowStatus(iRow, isFixed);
1200 }
1201 } else {
1202 // range
1203 numberRanges++;
1204 Status statusL = dualProblem->getColumnStatus(kExtraRow);
1205 //printf("range row %d (%d), extra %d (%d) - dualSol %g,%g dualDj %g,%g\n",
1206 // iRow,status,kExtraRow,statusL, dualSol[iRow],
1207 // dualSol[kExtraRow],dualDj[iRow],dualDj[kExtraRow]);
1208 if (status == basic) {
1209 // might be stopped assert (statusL != basic);
1210 rowActivity_[iRow] = rowUpper_[iRow];
1211 setRowStatus(iRow, atUpperBound);
1212 } else if (statusL == basic) {
1213 numberBasic--; // already counted
1214 rowActivity_[iRow] = rowLower_[iRow];
1215 setRowStatus(iRow, atLowerBound);
1216 dual_[iRow] = dualSol[kExtraRow];
1217 ;
1218 } else {
1219 rowActivity_[iRow] = rowLower_[iRow] - dualDj[iRow];
1220 // might be stopped assert (dualDj[iRow] < 1.0e-5);
1221 // row basic
1222 //setRowStatus(iRow,basic);
1223 //numberBasic++;
1224 dual_[iRow] = 0.0;
1225 }
1226 kExtraRow++;
1227 }
1228 }
1229 }
1230 if (numberBasic != numberRows_ && 0) {
1231 printf("Bad basis - ranges - coding needed\n");
1232 assert(numberRanges);
1233 abort();
1234 }
1235 if (optimizationDirection_ < 0.0) {
1236 for (iRow = 0; iRow < numberRows_; iRow++) {
1237 dual_[iRow] = -dual_[iRow];
1238 }
1239 }
1240 // redo row activities
1241 memset(rowActivity_, 0, numberRows_ * sizeof(double));
1242 matrix_->times(1.0, columnActivity_, rowActivity_);
1243 // redo reduced costs
1244 memcpy(reducedCost_, this->objective(), numberColumns_ * sizeof(double));
1245 matrix_->transposeTimes(-1.0, dual_, reducedCost_);
1246 checkSolutionInternal();
1247 if (sumDualInfeasibilities_ > 1.0e-5 || sumPrimalInfeasibilities_ > 1.0e-5) {
1248 returnCode = 1;
1249 #ifdef CLP_INVESTIGATE
1250 printf("There are %d dual infeasibilities summing to %g ",
1251 numberDualInfeasibilities_, sumDualInfeasibilities_);
1252 printf("and %d primal infeasibilities summing to %g\n",
1253 numberPrimalInfeasibilities_, sumPrimalInfeasibilities_);
1254 #endif
1255 }
1256 // Below will go to ..DEBUG later
1257 #if 1 //ndef NDEBUG
1258 if (checkAccuracy) {
1259 // Check if correct
1260 double *columnActivity = CoinCopyOfArray(columnActivity_, numberColumns_);
1261 double *rowActivity = CoinCopyOfArray(rowActivity_, numberRows_);
1262 double *reducedCost = CoinCopyOfArray(reducedCost_, numberColumns_);
1263 double *dual = CoinCopyOfArray(dual_, numberRows_);
1264 this->dual(); //primal();
1265 CoinRelFltEq eq(1.0e-5);
1266 for (iRow = 0; iRow < numberRows_; iRow++) {
1267 assert(eq(dual[iRow], dual_[iRow]));
1268 }
1269 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1270 assert(eq(columnActivity[iColumn], columnActivity_[iColumn]));
1271 }
1272 for (iRow = 0; iRow < numberRows_; iRow++) {
1273 assert(eq(rowActivity[iRow], rowActivity_[iRow]));
1274 }
1275 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1276 assert(eq(reducedCost[iColumn], reducedCost_[iColumn]));
1277 }
1278 delete[] columnActivity;
1279 delete[] rowActivity;
1280 delete[] reducedCost;
1281 delete[] dual;
1282 }
1283 #endif
1284 return returnCode;
1285 }
1286 /* Sets solution in dualized problem
1287 non-zero return code indicates minor problems
1288 */
setInDual(ClpSimplex * dualProblem)1289 int ClpSimplexOther::setInDual(ClpSimplex *dualProblem)
1290 {
1291 // Number of rows in dual problem was original number of columns
1292 assert(numberColumns_ == dualProblem->numberRows());
1293 // out If slack on d-row basic then column at bound otherwise column basic
1294 // out If d-column basic then rhs tight
1295 // if column at bound then slack on d-row basic
1296 // if column basic then slack on d-row at bound
1297 // if rhs non-basic then d-column basic
1298 // if rhs basic then d-column ?
1299 int numberBasic = 0;
1300 int iRow, iColumn = 0;
1301 //int numberExtraRows = dualProblem->numberColumns()-numberRows_;
1302 //const double * objective = this->objective();
1303 //double * dualDual = dualProblem->dualRowSolution();
1304 //double * dualDj = dualProblem->dualColumnSolution();
1305 double *dualSol = dualProblem->primalColumnSolution();
1306 //double * dualActs = dualProblem->primalRowSolution();
1307 const double *lower = dualProblem->columnLower();
1308 const double *upper = dualProblem->columnUpper();
1309 // position at bound information
1310 int jColumn = numberRows_;
1311 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1312 Status status = getColumnStatus(iColumn);
1313 Status statusD = dualProblem->getRowStatus(iColumn);
1314 Status statusDJ = dualProblem->getColumnStatus(jColumn);
1315 if (status == atLowerBound || status == isFixed || status == atUpperBound) {
1316 dualProblem->setRowStatus(iColumn, basic);
1317 numberBasic++;
1318 if (columnUpper_[iColumn] < 1.0e20 && columnLower_[iColumn] > -1.0e20) {
1319 bool mainLower = (fabs(columnLower_[iColumn]) < fabs(columnUpper_[iColumn]));
1320 // fix this
1321 if (mainLower) {
1322 if (status == atUpperBound) {
1323 dualProblem->setColumnStatus(jColumn, atUpperBound);
1324 } else {
1325 dualProblem->setColumnStatus(jColumn, atUpperBound);
1326 }
1327 } else {
1328 if (status == atUpperBound) {
1329 dualProblem->setColumnStatus(jColumn, atLowerBound);
1330 } else {
1331 dualProblem->setColumnStatus(jColumn, atLowerBound);
1332 }
1333 }
1334 assert(statusDJ == dualProblem->getColumnStatus(jColumn));
1335 jColumn++;
1336 }
1337 } else if (status == isFree) {
1338 dualProblem->setRowStatus(iColumn, basic);
1339 numberBasic++;
1340 } else {
1341 assert(status == basic);
1342 //numberBasic++;
1343 }
1344 assert(statusD == dualProblem->getRowStatus(iColumn));
1345 }
1346 // now rows (no ranges at first)
1347 for (iRow = 0; iRow < numberRows_; iRow++) {
1348 Status status = getRowStatus(iRow);
1349 Status statusD = dualProblem->getColumnStatus(iRow);
1350 if (status == basic) {
1351 // dual variable is at bound
1352 if (!lower[iRow]) {
1353 dualProblem->setColumnStatus(iRow, atLowerBound);
1354 } else if (!upper[iRow]) {
1355 dualProblem->setColumnStatus(iRow, atUpperBound);
1356 } else {
1357 dualProblem->setColumnStatus(iRow, isFree);
1358 dualSol[iRow] = 0.0;
1359 }
1360 } else {
1361 // dual variable is basic
1362 dualProblem->setColumnStatus(iRow, basic);
1363 numberBasic++;
1364 }
1365 if (rowLower_[iRow] < -1.0e20 && rowUpper_[iRow] > 1.0e20) {
1366 if (rowUpper_[iRow] != rowLower_[iRow]) {
1367 printf("can't handle ranges yet\n");
1368 abort();
1369 }
1370 }
1371 assert(statusD == dualProblem->getColumnStatus(iRow));
1372 }
1373 if (numberBasic != numberColumns_) {
1374 printf("Bad basis - ranges - coding needed ??\n");
1375 abort();
1376 }
1377 return 0;
1378 }
1379 /* Does very cursory presolve.
1380 rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns
1381 */
1382 ClpSimplex *
crunch(double * rhs,int * whichRow,int * whichColumn,int & nBound,bool moreBounds,bool tightenBounds)1383 ClpSimplexOther::crunch(double *rhs, int *whichRow, int *whichColumn,
1384 int &nBound, bool moreBounds, bool tightenBounds)
1385 {
1386 //#define CHECK_STATUS
1387 #ifdef CHECK_STATUS
1388 {
1389 int n = 0;
1390 int i;
1391 for (i = 0; i < numberColumns_; i++)
1392 if (getColumnStatus(i) == ClpSimplex::basic)
1393 n++;
1394 for (i = 0; i < numberRows_; i++)
1395 if (getRowStatus(i) == ClpSimplex::basic)
1396 n++;
1397 assert(n == numberRows_);
1398 }
1399 #endif
1400
1401 const double *element = matrix_->getElements();
1402 const int *row = matrix_->getIndices();
1403 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
1404 const int *columnLength = matrix_->getVectorLengths();
1405
1406 CoinZeroN(rhs, numberRows_);
1407 int iColumn;
1408 int iRow;
1409 CoinZeroN(whichRow, numberRows_);
1410 int *backColumn = whichColumn + numberColumns_;
1411 int numberRows2 = 0;
1412 int numberColumns2 = 0;
1413 double offset = 0.0;
1414 const double *objective = this->objective();
1415 double *solution = columnActivity_;
1416 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1417 double lower = columnLower_[iColumn];
1418 double upper = columnUpper_[iColumn];
1419 if (upper > lower || getColumnStatus(iColumn) == ClpSimplex::basic) {
1420 backColumn[iColumn] = numberColumns2;
1421 whichColumn[numberColumns2++] = iColumn;
1422 for (CoinBigIndex j = columnStart[iColumn];
1423 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1424 int iRow = row[j];
1425 int n = whichRow[iRow];
1426 if (n == 0 && element[j])
1427 whichRow[iRow] = -iColumn - 1;
1428 else if (n < 0)
1429 whichRow[iRow] = 2;
1430 }
1431 } else {
1432 // fixed
1433 backColumn[iColumn] = -1;
1434 solution[iColumn] = upper;
1435 if (upper) {
1436 offset += objective[iColumn] * upper;
1437 for (CoinBigIndex j = columnStart[iColumn];
1438 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1439 int iRow = row[j];
1440 double value = element[j];
1441 rhs[iRow] += upper * value;
1442 }
1443 }
1444 }
1445 }
1446 int returnCode = 0;
1447 double tolerance = primalTolerance();
1448 nBound = 2 * numberRows_;
1449 for (iRow = 0; iRow < numberRows_; iRow++) {
1450 int n = whichRow[iRow];
1451 if (n > 0) {
1452 whichRow[numberRows2++] = iRow;
1453 } else if (n < 0) {
1454 //whichRow[numberRows2++]=iRow;
1455 //continue;
1456 // Can only do in certain circumstances as we don't know current value
1457 if (rowLower_[iRow] == rowUpper_[iRow] || getRowStatus(iRow) == ClpSimplex::basic) {
1458 // save row and column for bound
1459 whichRow[--nBound] = iRow;
1460 whichRow[nBound + numberRows_] = -n - 1;
1461 } else if (moreBounds) {
1462 // save row and column for bound
1463 whichRow[--nBound] = iRow;
1464 whichRow[nBound + numberRows_] = -n - 1;
1465 } else {
1466 whichRow[numberRows2++] = iRow;
1467 }
1468 } else {
1469 // empty
1470 double rhsValue = rhs[iRow];
1471 if (rhsValue < rowLower_[iRow] - tolerance || rhsValue > rowUpper_[iRow] + tolerance) {
1472 returnCode = 1; // infeasible
1473 }
1474 }
1475 }
1476 ClpSimplex *small = NULL;
1477 if (!returnCode) {
1478 //printf("CRUNCH from (%d,%d) to (%d,%d)\n",
1479 // numberRows_,numberColumns_,numberRows2,numberColumns2);
1480 small = new ClpSimplex(this, numberRows2, whichRow,
1481 numberColumns2, whichColumn, true, false);
1482 #if 0
1483 ClpPackedMatrix * rowCopy = dynamic_cast<ClpPackedMatrix *>(rowCopy_);
1484 if (rowCopy) {
1485 assert(!small->rowCopy());
1486 small->setNewRowCopy(new ClpPackedMatrix(*rowCopy, numberRows2, whichRow,
1487 numberColumns2, whichColumn));
1488 }
1489 #endif
1490 // Set some stuff
1491 small->setDualBound(dualBound_);
1492 small->setInfeasibilityCost(infeasibilityCost_);
1493 small->setSpecialOptions(specialOptions_);
1494 small->setPerturbation(perturbation_);
1495 small->defaultFactorizationFrequency();
1496 small->setAlphaAccuracy(alphaAccuracy_);
1497 // If no rows left then no tightening!
1498 if (!numberRows2 || !numberColumns2)
1499 tightenBounds = false;
1500
1501 CoinBigIndex numberElements = getNumElements();
1502 CoinBigIndex numberElements2 = small->getNumElements();
1503 small->setObjectiveOffset(objectiveOffset() - offset);
1504 handler_->message(CLP_CRUNCH_STATS, messages_)
1505 << numberRows2 << -(numberRows_ - numberRows2)
1506 << numberColumns2 << -(numberColumns_ - numberColumns2)
1507 << numberElements2 << -(numberElements - numberElements2)
1508 << CoinMessageEol;
1509 // And set objective value to match
1510 small->setObjectiveValue(this->objectiveValue());
1511 double *rowLower2 = small->rowLower();
1512 double *rowUpper2 = small->rowUpper();
1513 int jRow;
1514 for (jRow = 0; jRow < numberRows2; jRow++) {
1515 iRow = whichRow[jRow];
1516 if (rowLower2[jRow] > -1.0e20)
1517 rowLower2[jRow] -= rhs[iRow];
1518 if (rowUpper2[jRow] < 1.0e20)
1519 rowUpper2[jRow] -= rhs[iRow];
1520 }
1521 // and bounds
1522 double *columnLower2 = small->columnLower();
1523 double *columnUpper2 = small->columnUpper();
1524 const char *integerInformation = integerType_;
1525 for (jRow = nBound; jRow < 2 * numberRows_; jRow++) {
1526 iRow = whichRow[jRow];
1527 iColumn = whichRow[jRow + numberRows_];
1528 double lowerRow = rowLower_[iRow];
1529 if (lowerRow > -1.0e20)
1530 lowerRow -= rhs[iRow];
1531 double upperRow = rowUpper_[iRow];
1532 if (upperRow < 1.0e20)
1533 upperRow -= rhs[iRow];
1534 int jColumn = backColumn[iColumn];
1535 double lower = columnLower2[jColumn];
1536 double upper = columnUpper2[jColumn];
1537 double value = 0.0;
1538 for (CoinBigIndex j = columnStart[iColumn];
1539 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1540 if (iRow == row[j]) {
1541 value = element[j];
1542 break;
1543 }
1544 }
1545 assert(value);
1546 // convert rowLower and Upper to implied bounds on column
1547 double newLower = -COIN_DBL_MAX;
1548 double newUpper = COIN_DBL_MAX;
1549 if (value > 0.0) {
1550 if (lowerRow > -1.0e20)
1551 newLower = lowerRow / value;
1552 if (upperRow < 1.0e20)
1553 newUpper = upperRow / value;
1554 } else {
1555 if (upperRow < 1.0e20)
1556 newLower = upperRow / value;
1557 if (lowerRow > -1.0e20)
1558 newUpper = lowerRow / value;
1559 }
1560 if (integerInformation && integerInformation[iColumn]) {
1561 if (newLower - floor(newLower) < 10.0 * tolerance)
1562 newLower = floor(newLower);
1563 else
1564 newLower = ceil(newLower);
1565 if (ceil(newUpper) - newUpper < 10.0 * tolerance)
1566 newUpper = ceil(newUpper);
1567 else
1568 newUpper = floor(newUpper);
1569 }
1570 newLower = CoinMax(lower, newLower);
1571 newUpper = CoinMin(upper, newUpper);
1572 if (newLower > newUpper + tolerance) {
1573 //printf("XXYY inf on bound\n");
1574 returnCode = 1;
1575 }
1576 columnLower2[jColumn] = newLower;
1577 columnUpper2[jColumn] = CoinMax(newLower, newUpper);
1578 if (getRowStatus(iRow) != ClpSimplex::basic) {
1579 if (getColumnStatus(iColumn) == ClpSimplex::basic) {
1580 if (columnLower2[jColumn] == columnUpper2[jColumn]) {
1581 // can only get here if will be fixed
1582 small->setColumnStatus(jColumn, ClpSimplex::isFixed);
1583 } else {
1584 // solution is valid
1585 if (fabs(columnActivity_[iColumn] - columnLower2[jColumn]) < fabs(columnActivity_[iColumn] - columnUpper2[jColumn]))
1586 small->setColumnStatus(jColumn, ClpSimplex::atLowerBound);
1587 else
1588 small->setColumnStatus(jColumn, ClpSimplex::atUpperBound);
1589 }
1590 } else {
1591 //printf("what now neither basic\n");
1592 }
1593 }
1594 }
1595 if (returnCode) {
1596 delete small;
1597 small = NULL;
1598 } else if (tightenBounds && integerInformation) {
1599 // See if we can tighten any bounds
1600 // use rhs for upper and small duals for lower
1601 double *up = rhs;
1602 double *lo = small->dualRowSolution();
1603 const double *element = small->clpMatrix()->getElements();
1604 const int *row = small->clpMatrix()->getIndices();
1605 const CoinBigIndex *columnStart = small->clpMatrix()->getVectorStarts();
1606 //const int * columnLength = small->clpMatrix()->getVectorLengths();
1607 CoinZeroN(lo, numberRows2);
1608 CoinZeroN(up, numberRows2);
1609 for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
1610 double upper = columnUpper2[iColumn];
1611 double lower = columnLower2[iColumn];
1612 //assert (columnLength[iColumn]==columnStart[iColumn+1]-columnStart[iColumn]);
1613 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) {
1614 int iRow = row[j];
1615 double value = element[j];
1616 if (value > 0.0) {
1617 if (upper < 1.0e20)
1618 up[iRow] += upper * value;
1619 else
1620 up[iRow] = COIN_DBL_MAX;
1621 if (lower > -1.0e20)
1622 lo[iRow] += lower * value;
1623 else
1624 lo[iRow] = -COIN_DBL_MAX;
1625 } else {
1626 if (upper < 1.0e20)
1627 lo[iRow] += upper * value;
1628 else
1629 lo[iRow] = -COIN_DBL_MAX;
1630 if (lower > -1.0e20)
1631 up[iRow] += lower * value;
1632 else
1633 up[iRow] = COIN_DBL_MAX;
1634 }
1635 }
1636 }
1637 double *rowLower2 = small->rowLower();
1638 double *rowUpper2 = small->rowUpper();
1639 bool feasible = true;
1640 // make safer
1641 for (int iRow = 0; iRow < numberRows2; iRow++) {
1642 double lower = lo[iRow];
1643 if (lower > rowUpper2[iRow] + tolerance) {
1644 feasible = false;
1645 break;
1646 } else {
1647 lo[iRow] = CoinMin(lower - rowUpper2[iRow], 0.0) - tolerance;
1648 }
1649 double upper = up[iRow];
1650 if (upper < rowLower2[iRow] - tolerance) {
1651 feasible = false;
1652 break;
1653 } else {
1654 up[iRow] = CoinMax(upper - rowLower2[iRow], 0.0) + tolerance;
1655 }
1656 // tighten row bounds
1657 if (lower > -1.0e10)
1658 rowLower2[iRow] = CoinMax(rowLower2[iRow],
1659 lower - 1.0e-6 * (1.0 + fabs(lower)));
1660 if (upper < 1.0e10)
1661 rowUpper2[iRow] = CoinMin(rowUpper2[iRow],
1662 upper + 1.0e-6 * (1.0 + fabs(upper)));
1663 }
1664 if (!feasible) {
1665 delete small;
1666 small = NULL;
1667 } else {
1668 // and tighten
1669 for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
1670 if (integerInformation[whichColumn[iColumn]]) {
1671 double upper = columnUpper2[iColumn];
1672 double lower = columnLower2[iColumn];
1673 double newUpper = upper;
1674 double newLower = lower;
1675 double difference = upper - lower;
1676 if (lower > -1000.0 && upper < 1000.0) {
1677 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) {
1678 int iRow = row[j];
1679 double value = element[j];
1680 if (value > 0.0) {
1681 double upWithOut = up[iRow] - value * difference;
1682 if (upWithOut < 0.0) {
1683 newLower = CoinMax(newLower, lower - (upWithOut + tolerance) / value);
1684 }
1685 double lowWithOut = lo[iRow] + value * difference;
1686 if (lowWithOut > 0.0) {
1687 newUpper = CoinMin(newUpper, upper - (lowWithOut - tolerance) / value);
1688 }
1689 } else {
1690 double upWithOut = up[iRow] + value * difference;
1691 if (upWithOut < 0.0) {
1692 newUpper = CoinMin(newUpper, upper - (upWithOut + tolerance) / value);
1693 }
1694 double lowWithOut = lo[iRow] - value * difference;
1695 if (lowWithOut > 0.0) {
1696 newLower = CoinMax(newLower, lower - (lowWithOut - tolerance) / value);
1697 }
1698 }
1699 }
1700 if (newLower > lower || newUpper < upper) {
1701 if (fabs(newUpper - floor(newUpper + 0.5)) > 1.0e-6)
1702 newUpper = floor(newUpper);
1703 else
1704 newUpper = floor(newUpper + 0.5);
1705 if (fabs(newLower - ceil(newLower - 0.5)) > 1.0e-6)
1706 newLower = ceil(newLower);
1707 else
1708 newLower = ceil(newLower - 0.5);
1709 // change may be too small - check
1710 if (newLower > lower || newUpper < upper) {
1711 if (newUpper >= newLower) {
1712 // Could also tighten in this
1713 //printf("%d bounds %g %g tightened to %g %g\n",
1714 // iColumn,columnLower2[iColumn],columnUpper2[iColumn],
1715 // newLower,newUpper);
1716 #if 1
1717 columnUpper2[iColumn] = newUpper;
1718 columnLower2[iColumn] = newLower;
1719 columnUpper_[whichColumn[iColumn]] = newUpper;
1720 columnLower_[whichColumn[iColumn]] = newLower;
1721 #endif
1722 // and adjust bounds on rows
1723 newUpper -= upper;
1724 newLower -= lower;
1725 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) {
1726 int iRow = row[j];
1727 double value = element[j];
1728 if (value > 0.0) {
1729 up[iRow] += newUpper * value;
1730 lo[iRow] += newLower * value;
1731 } else {
1732 lo[iRow] += newUpper * value;
1733 up[iRow] += newLower * value;
1734 }
1735 }
1736 } else {
1737 // infeasible
1738 //printf("%d bounds infeasible %g %g tightened to %g %g\n",
1739 // iColumn,columnLower2[iColumn],columnUpper2[iColumn],
1740 // newLower,newUpper);
1741 #if 1
1742 delete small;
1743 small = NULL;
1744 break;
1745 #endif
1746 }
1747 }
1748 }
1749 }
1750 }
1751 }
1752 }
1753 }
1754 }
1755 #if 0
1756 if (small) {
1757 static int which = 0;
1758 which++;
1759 char xxxx[20];
1760 sprintf(xxxx, "bad%d.mps", which);
1761 small->writeMps(xxxx, 0, 1);
1762 sprintf(xxxx, "largebad%d.mps", which);
1763 writeMps(xxxx, 0, 1);
1764 printf("bad%d %x old size %d %d new %d %d\n", which, small,
1765 numberRows_, numberColumns_, small->numberRows(), small->numberColumns());
1766 #if 0
1767 for (int i = 0; i < numberColumns_; i++)
1768 printf("Bound %d %g %g\n", i, columnLower_[i], columnUpper_[i]);
1769 for (int i = 0; i < numberRows_; i++)
1770 printf("Row bound %d %g %g\n", i, rowLower_[i], rowUpper_[i]);
1771 #endif
1772 }
1773 #endif
1774 #ifdef CHECK_STATUS
1775 {
1776 int n = 0;
1777 int i;
1778 for (i = 0; i < small->numberColumns(); i++)
1779 if (small->getColumnStatus(i) == ClpSimplex::basic)
1780 n++;
1781 for (i = 0; i < small->numberRows(); i++)
1782 if (small->getRowStatus(i) == ClpSimplex::basic)
1783 n++;
1784 assert(n == small->numberRows());
1785 }
1786 #endif
1787 return small;
1788 }
1789 /* After very cursory presolve.
1790 rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns.
1791 */
afterCrunch(const ClpSimplex & small,const int * whichRow,const int * whichColumn,int nBound)1792 void ClpSimplexOther::afterCrunch(const ClpSimplex &small,
1793 const int *whichRow,
1794 const int *whichColumn, int nBound)
1795 {
1796 #ifndef NDEBUG
1797 for (int i = 0; i < small.numberRows(); i++)
1798 assert(whichRow[i] >= 0 && whichRow[i] < numberRows_);
1799 for (int i = 0; i < small.numberColumns(); i++)
1800 assert(whichColumn[i] >= 0 && whichColumn[i] < numberColumns_);
1801 #endif
1802 getbackSolution(small, whichRow, whichColumn);
1803 // and deal with status for bounds
1804 const double *element = matrix_->getElements();
1805 const int *row = matrix_->getIndices();
1806 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
1807 const int *columnLength = matrix_->getVectorLengths();
1808 double tolerance = primalTolerance();
1809 double djTolerance = dualTolerance();
1810 for (int jRow = nBound; jRow < 2 * numberRows_; jRow++) {
1811 int iRow = whichRow[jRow];
1812 int iColumn = whichRow[jRow + numberRows_];
1813 if (getColumnStatus(iColumn) != ClpSimplex::basic) {
1814 double lower = columnLower_[iColumn];
1815 double upper = columnUpper_[iColumn];
1816 double value = columnActivity_[iColumn];
1817 double djValue = reducedCost_[iColumn];
1818 dual_[iRow] = 0.0;
1819 if (upper > lower) {
1820 if (value < lower + tolerance && djValue > -djTolerance) {
1821 setColumnStatus(iColumn, ClpSimplex::atLowerBound);
1822 setRowStatus(iRow, ClpSimplex::basic);
1823 } else if (value > upper - tolerance && djValue < djTolerance) {
1824 setColumnStatus(iColumn, ClpSimplex::atUpperBound);
1825 setRowStatus(iRow, ClpSimplex::basic);
1826 } else {
1827 // has to be basic
1828 setColumnStatus(iColumn, ClpSimplex::basic);
1829 reducedCost_[iColumn] = 0.0;
1830 double value = 0.0;
1831 for (CoinBigIndex j = columnStart[iColumn];
1832 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1833 if (iRow == row[j]) {
1834 value = element[j];
1835 break;
1836 }
1837 }
1838 dual_[iRow] = djValue / value;
1839 if (rowUpper_[iRow] > rowLower_[iRow]) {
1840 if (fabs(rowActivity_[iRow] - rowLower_[iRow]) < fabs(rowActivity_[iRow] - rowUpper_[iRow]))
1841 setRowStatus(iRow, ClpSimplex::atLowerBound);
1842 else
1843 setRowStatus(iRow, ClpSimplex::atUpperBound);
1844 } else {
1845 setRowStatus(iRow, ClpSimplex::isFixed);
1846 }
1847 }
1848 } else {
1849 // row can always be basic
1850 setRowStatus(iRow, ClpSimplex::basic);
1851 }
1852 } else {
1853 // row can always be basic
1854 setRowStatus(iRow, ClpSimplex::basic);
1855 }
1856 }
1857 //#ifndef NDEBUG
1858 #if 0
1859 if (small.status() == 0) {
1860 int n = 0;
1861 int i;
1862 for (i = 0; i < numberColumns; i++)
1863 if (getColumnStatus(i) == ClpSimplex::basic)
1864 n++;
1865 for (i = 0; i < numberRows; i++)
1866 if (getRowStatus(i) == ClpSimplex::basic)
1867 n++;
1868 assert (n == numberRows);
1869 }
1870 #endif
1871 }
1872 /* Tightens integer bounds - returns number tightened or -1 if infeasible
1873 */
tightenIntegerBounds(double * rhsSpace)1874 int ClpSimplexOther::tightenIntegerBounds(double *rhsSpace)
1875 {
1876 // See if we can tighten any bounds
1877 // use rhs for upper and small duals for lower
1878 double *up = rhsSpace;
1879 double *lo = dual_;
1880 const double *element = matrix_->getElements();
1881 const int *row = matrix_->getIndices();
1882 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
1883 const int *columnLength = matrix_->getVectorLengths();
1884 CoinZeroN(lo, numberRows_);
1885 CoinZeroN(up, numberRows_);
1886 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
1887 double upper = columnUpper_[iColumn];
1888 double lower = columnLower_[iColumn];
1889 //assert (columnLength[iColumn]==columnStart[iColumn+1]-columnStart[iColumn]);
1890 for (CoinBigIndex j = columnStart[iColumn];
1891 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1892 int iRow = row[j];
1893 double value = element[j];
1894 if (value > 0.0) {
1895 if (upper < 1.0e20)
1896 up[iRow] += upper * value;
1897 else
1898 up[iRow] = COIN_DBL_MAX;
1899 if (lower > -1.0e20)
1900 lo[iRow] += lower * value;
1901 else
1902 lo[iRow] = -COIN_DBL_MAX;
1903 } else {
1904 if (upper < 1.0e20)
1905 lo[iRow] += upper * value;
1906 else
1907 lo[iRow] = -COIN_DBL_MAX;
1908 if (lower > -1.0e20)
1909 up[iRow] += lower * value;
1910 else
1911 up[iRow] = COIN_DBL_MAX;
1912 }
1913 }
1914 }
1915 bool feasible = true;
1916 // make safer
1917 double tolerance = primalTolerance();
1918 for (int iRow = 0; iRow < numberRows_; iRow++) {
1919 double lower = lo[iRow];
1920 if (lower > rowUpper_[iRow] + tolerance) {
1921 feasible = false;
1922 break;
1923 } else {
1924 lo[iRow] = CoinMin(lower - rowUpper_[iRow], 0.0) - tolerance;
1925 }
1926 double upper = up[iRow];
1927 if (upper < rowLower_[iRow] - tolerance) {
1928 feasible = false;
1929 break;
1930 } else {
1931 up[iRow] = CoinMax(upper - rowLower_[iRow], 0.0) + tolerance;
1932 }
1933 }
1934 int numberTightened = 0;
1935 if (!feasible) {
1936 return -1;
1937 } else if (integerType_) {
1938 // and tighten
1939 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
1940 if (integerType_[iColumn]) {
1941 double upper = columnUpper_[iColumn];
1942 double lower = columnLower_[iColumn];
1943 double newUpper = upper;
1944 double newLower = lower;
1945 double difference = upper - lower;
1946 if (lower > -1000.0 && upper < 1000.0) {
1947 for (CoinBigIndex j = columnStart[iColumn];
1948 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1949 int iRow = row[j];
1950 double value = element[j];
1951 if (value > 0.0) {
1952 double upWithOut = up[iRow] - value * difference;
1953 if (upWithOut < 0.0) {
1954 newLower = CoinMax(newLower, lower - (upWithOut + tolerance) / value);
1955 }
1956 double lowWithOut = lo[iRow] + value * difference;
1957 if (lowWithOut > 0.0) {
1958 newUpper = CoinMin(newUpper, upper - (lowWithOut - tolerance) / value);
1959 }
1960 } else {
1961 double upWithOut = up[iRow] + value * difference;
1962 if (upWithOut < 0.0) {
1963 newUpper = CoinMin(newUpper, upper - (upWithOut + tolerance) / value);
1964 }
1965 double lowWithOut = lo[iRow] - value * difference;
1966 if (lowWithOut > 0.0) {
1967 newLower = CoinMax(newLower, lower - (lowWithOut - tolerance) / value);
1968 }
1969 }
1970 }
1971 if (newLower > lower || newUpper < upper) {
1972 if (fabs(newUpper - floor(newUpper + 0.5)) > 1.0e-6)
1973 newUpper = floor(newUpper);
1974 else
1975 newUpper = floor(newUpper + 0.5);
1976 if (fabs(newLower - ceil(newLower - 0.5)) > 1.0e-6)
1977 newLower = ceil(newLower);
1978 else
1979 newLower = ceil(newLower - 0.5);
1980 // change may be too small - check
1981 if (newLower > lower || newUpper < upper) {
1982 if (newUpper >= newLower) {
1983 numberTightened++;
1984 //printf("%d bounds %g %g tightened to %g %g\n",
1985 // iColumn,columnLower_[iColumn],columnUpper_[iColumn],
1986 // newLower,newUpper);
1987 columnUpper_[iColumn] = newUpper;
1988 columnLower_[iColumn] = newLower;
1989 // and adjust bounds on rows
1990 newUpper -= upper;
1991 newLower -= lower;
1992 for (CoinBigIndex j = columnStart[iColumn];
1993 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1994 int iRow = row[j];
1995 double value = element[j];
1996 if (value > 0.0) {
1997 up[iRow] += newUpper * value;
1998 lo[iRow] += newLower * value;
1999 } else {
2000 lo[iRow] += newUpper * value;
2001 up[iRow] += newLower * value;
2002 }
2003 }
2004 } else {
2005 // infeasible
2006 //printf("%d bounds infeasible %g %g tightened to %g %g\n",
2007 // iColumn,columnLower_[iColumn],columnUpper_[iColumn],
2008 // newLower,newUpper);
2009 return -1;
2010 }
2011 }
2012 }
2013 }
2014 }
2015 }
2016 }
2017 return numberTightened;
2018 }
2019 /* Parametrics
2020 This is an initial slow version.
2021 The code uses current bounds + theta * change (if change array not NULL)
2022 and similarly for objective.
2023 It starts at startingTheta and returns ending theta in endingTheta.
2024 If reportIncrement 0.0 it will report on any movement
2025 If reportIncrement >0.0 it will report at startingTheta+k*reportIncrement.
2026 If it can not reach input endingTheta return code will be 1 for infeasible,
2027 2 for unbounded, if error on ranges -1, otherwise 0.
2028 Normal report is just theta and objective but
2029 if event handler exists it may do more
2030 On exit endingTheta is maximum reached (can be used for next startingTheta)
2031 */
parametrics(double startingTheta,double & endingTheta,double reportIncrement,const double * lowerChangeBound,const double * upperChangeBound,const double * lowerChangeRhs,const double * upperChangeRhs,const double * changeObjective)2032 int ClpSimplexOther::parametrics(double startingTheta, double &endingTheta, double reportIncrement,
2033 const double *lowerChangeBound, const double *upperChangeBound,
2034 const double *lowerChangeRhs, const double *upperChangeRhs,
2035 const double *changeObjective)
2036 {
2037 bool needToDoSomething = true;
2038 bool canTryQuick = (reportIncrement) ? true : false;
2039 // Save copy of model
2040 ClpSimplex copyModel = *this;
2041 int savePerturbation = perturbation_;
2042 perturbation_ = 102; // switch off
2043 while (needToDoSomething) {
2044 needToDoSomething = false;
2045 algorithm_ = -1;
2046
2047 // save data
2048 ClpDataSave data = saveData();
2049 // Dantzig
2050 ClpDualRowPivot *savePivot = dualRowPivot_;
2051 dualRowPivot_ = new ClpDualRowDantzig();
2052 dualRowPivot_->setModel(this);
2053 int returnCode = reinterpret_cast< ClpSimplexDual * >(this)->startupSolve(0, NULL, 0);
2054 int iRow, iColumn;
2055 double *chgUpper = NULL;
2056 double *chgLower = NULL;
2057 double *chgObjective = NULL;
2058
2059 if (!returnCode) {
2060 // Find theta when bounds will cross over and create arrays
2061 int numberTotal = numberRows_ + numberColumns_;
2062 chgLower = new double[numberTotal];
2063 memset(chgLower, 0, numberTotal * sizeof(double));
2064 chgUpper = new double[numberTotal];
2065 memset(chgUpper, 0, numberTotal * sizeof(double));
2066 chgObjective = new double[numberTotal];
2067 memset(chgObjective, 0, numberTotal * sizeof(double));
2068 assert(!rowScale_);
2069 double maxTheta = 1.0e50;
2070 if (lowerChangeRhs || upperChangeRhs) {
2071 for (iRow = 0; iRow < numberRows_; iRow++) {
2072 double lower = rowLower_[iRow];
2073 double upper = rowUpper_[iRow];
2074 if (lower > upper) {
2075 maxTheta = -1.0;
2076 break;
2077 }
2078 double lowerChange = (lowerChangeRhs) ? lowerChangeRhs[iRow] : 0.0;
2079 double upperChange = (upperChangeRhs) ? upperChangeRhs[iRow] : 0.0;
2080 if (lower > -1.0e20 && upper < 1.0e20) {
2081 if (lower + maxTheta * lowerChange > upper + maxTheta * upperChange) {
2082 maxTheta = (upper - lower) / (lowerChange - upperChange);
2083 }
2084 }
2085 if (lower > -1.0e20) {
2086 lower_[numberColumns_ + iRow] += startingTheta * lowerChange;
2087 chgLower[numberColumns_ + iRow] = lowerChange;
2088 }
2089 if (upper < 1.0e20) {
2090 upper_[numberColumns_ + iRow] += startingTheta * upperChange;
2091 chgUpper[numberColumns_ + iRow] = upperChange;
2092 }
2093 }
2094 }
2095 if (maxTheta > 0.0) {
2096 if (lowerChangeBound || upperChangeBound) {
2097 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2098 double lower = columnLower_[iColumn];
2099 double upper = columnUpper_[iColumn];
2100 if (lower > upper) {
2101 maxTheta = -1.0;
2102 break;
2103 }
2104 double lowerChange = (lowerChangeBound) ? lowerChangeBound[iColumn] : 0.0;
2105 double upperChange = (upperChangeBound) ? upperChangeBound[iColumn] : 0.0;
2106 if (lower > -1.0e20 && upper < 1.0e20) {
2107 if (lower + maxTheta * lowerChange > upper + maxTheta * upperChange) {
2108 maxTheta = (upper - lower) / (lowerChange - upperChange);
2109 }
2110 }
2111 if (lower > -1.0e20) {
2112 lower_[iColumn] += startingTheta * lowerChange;
2113 chgLower[iColumn] = lowerChange;
2114 }
2115 if (upper < 1.0e20) {
2116 upper_[iColumn] += startingTheta * upperChange;
2117 chgUpper[iColumn] = upperChange;
2118 }
2119 }
2120 }
2121 if (maxTheta == 1.0e50)
2122 maxTheta = COIN_DBL_MAX;
2123 }
2124 if (maxTheta < 0.0) {
2125 // bad ranges or initial
2126 returnCode = -1;
2127 }
2128 if (maxTheta < endingTheta) {
2129 char line[100];
2130 sprintf(line, "Crossover considerations reduce ending theta from %g to %g\n",
2131 endingTheta, maxTheta);
2132 handler_->message(CLP_GENERAL, messages_)
2133 << line << CoinMessageEol;
2134 endingTheta = maxTheta;
2135 }
2136 if (endingTheta < startingTheta) {
2137 // bad initial
2138 returnCode = -2;
2139 }
2140 }
2141 double saveEndingTheta = endingTheta;
2142 if (!returnCode) {
2143 if (changeObjective) {
2144 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2145 chgObjective[iColumn] = changeObjective[iColumn];
2146 cost_[iColumn] += startingTheta * changeObjective[iColumn];
2147 }
2148 }
2149 double *saveDuals = NULL;
2150 reinterpret_cast< ClpSimplexDual * >(this)->gutsOfDual(0, saveDuals, -1, data);
2151 assert(!problemStatus_);
2152 for (int i = 0; i < numberRows_ + numberColumns_; i++)
2153 setFakeBound(i, noFake);
2154 // Now do parametrics
2155 handler_->message(CLP_PARAMETRICS_STATS, messages_)
2156 << startingTheta << objectiveValue() << CoinMessageEol;
2157 while (!returnCode) {
2158 //assert (reportIncrement);
2159 parametricsData paramData;
2160 paramData.startingTheta = startingTheta;
2161 paramData.endingTheta = endingTheta;
2162 paramData.maxTheta = COIN_DBL_MAX;
2163 paramData.lowerChange = chgLower;
2164 paramData.upperChange = chgUpper;
2165 returnCode = parametricsLoop(paramData, reportIncrement,
2166 chgLower, chgUpper, chgObjective, data,
2167 canTryQuick);
2168 startingTheta = paramData.startingTheta;
2169 endingTheta = paramData.endingTheta;
2170 if (!returnCode) {
2171 //double change = endingTheta-startingTheta;
2172 startingTheta = endingTheta;
2173 endingTheta = saveEndingTheta;
2174 //for (int i=0;i<numberTotal;i++) {
2175 //lower_[i] += change*chgLower[i];
2176 //upper_[i] += change*chgUpper[i];
2177 //cost_[i] += change*chgObjective[i];
2178 //}
2179 handler_->message(CLP_PARAMETRICS_STATS, messages_)
2180 << startingTheta << objectiveValue() << CoinMessageEol;
2181 if (startingTheta >= endingTheta)
2182 break;
2183 } else if (returnCode == -1) {
2184 // trouble - do external solve
2185 needToDoSomething = true;
2186 } else if (problemStatus_ == 1) {
2187 // can't move any further
2188 if (!canTryQuick) {
2189 handler_->message(CLP_PARAMETRICS_STATS, messages_)
2190 << endingTheta << objectiveValue() << CoinMessageEol;
2191 problemStatus_ = 0;
2192 }
2193 } else {
2194 abort();
2195 }
2196 }
2197 }
2198 reinterpret_cast< ClpSimplexDual * >(this)->finishSolve(0);
2199
2200 delete dualRowPivot_;
2201 dualRowPivot_ = savePivot;
2202 // Restore any saved stuff
2203 restoreData(data);
2204 if (needToDoSomething) {
2205 double saveStartingTheta = startingTheta; // known to be feasible
2206 int cleanedUp = 1;
2207 while (cleanedUp) {
2208 // tweak
2209 if (cleanedUp == 1) {
2210 if (!reportIncrement)
2211 startingTheta = CoinMin(startingTheta + 1.0e-5, saveEndingTheta);
2212 else
2213 startingTheta = CoinMin(startingTheta + reportIncrement, saveEndingTheta);
2214 } else {
2215 // restoring to go slowly
2216 startingTheta = saveStartingTheta;
2217 }
2218 // only works if not scaled
2219 int i;
2220 const double *obj1 = objective();
2221 double *obj2 = copyModel.objective();
2222 const double *lower1 = columnLower_;
2223 double *lower2 = copyModel.columnLower();
2224 const double *upper1 = columnUpper_;
2225 double *upper2 = copyModel.columnUpper();
2226 for (i = 0; i < numberColumns_; i++) {
2227 obj2[i] = obj1[i] + startingTheta * chgObjective[i];
2228 lower2[i] = lower1[i] + startingTheta * chgLower[i];
2229 upper2[i] = upper1[i] + startingTheta * chgUpper[i];
2230 }
2231 lower1 = rowLower_;
2232 lower2 = copyModel.rowLower();
2233 upper1 = rowUpper_;
2234 upper2 = copyModel.rowUpper();
2235 for (i = 0; i < numberRows_; i++) {
2236 lower2[i] = lower1[i] + startingTheta * chgLower[i + numberColumns_];
2237 upper2[i] = upper1[i] + startingTheta * chgUpper[i + numberColumns_];
2238 }
2239 copyModel.dual();
2240 if (copyModel.problemStatus()) {
2241 char line[100];
2242 sprintf(line, "Can not get to theta of %g\n", startingTheta);
2243 handler_->message(CLP_GENERAL, messages_)
2244 << line << CoinMessageEol;
2245 canTryQuick = false; // do slowly to get exact amount
2246 // back to last known good
2247 if (cleanedUp == 1)
2248 cleanedUp = 2;
2249 else
2250 abort();
2251 } else {
2252 // and move stuff back
2253 int numberTotal = numberRows_ + numberColumns_;
2254 CoinMemcpyN(copyModel.statusArray(), numberTotal, status_);
2255 CoinMemcpyN(copyModel.primalColumnSolution(), numberColumns_, columnActivity_);
2256 CoinMemcpyN(copyModel.primalRowSolution(), numberRows_, rowActivity_);
2257 cleanedUp = 0;
2258 }
2259 }
2260 }
2261 delete[] chgLower;
2262 delete[] chgUpper;
2263 delete[] chgObjective;
2264 }
2265 perturbation_ = savePerturbation;
2266 char line[100];
2267 sprintf(line, "Ending theta %g\n", endingTheta);
2268 handler_->message(CLP_GENERAL, messages_)
2269 << line << CoinMessageEol;
2270 return problemStatus_;
2271 }
2272 /* Version of parametrics which reads from file
2273 See CbcClpParam.cpp for details of format
2274 Returns -2 if unable to open file */
parametrics(const char * dataFile)2275 int ClpSimplexOther::parametrics(const char *dataFile)
2276 {
2277 int returnCode = -2;
2278 FILE *fp = fopen(dataFile, "r");
2279 char line[200];
2280 if (!fp) {
2281 handler_->message(CLP_UNABLE_OPEN, messages_)
2282 << dataFile << CoinMessageEol;
2283 return -2;
2284 }
2285
2286 if (!fgets(line, 200, fp)) {
2287 sprintf(line, "Empty parametrics file %s?", dataFile);
2288 handler_->message(CLP_GENERAL, messages_)
2289 << line << CoinMessageEol;
2290 fclose(fp);
2291 return -2;
2292 }
2293 char *pos = line;
2294 char *put = line;
2295 while (*pos >= ' ' && *pos != '\n') {
2296 if (*pos != ' ' && *pos != '\t') {
2297 *put = static_cast< char >(tolower(*pos));
2298 put++;
2299 }
2300 pos++;
2301 }
2302 *put = '\0';
2303 pos = line;
2304 double startTheta = 0.0;
2305 double endTheta = 0.0;
2306 double intervalTheta = COIN_DBL_MAX;
2307 int detail = 0;
2308 bool good = true;
2309 while (good) {
2310 good = false;
2311 // check ROWS
2312 char *comma = strchr(pos, ',');
2313 if (!comma)
2314 break;
2315 *comma = '\0';
2316 if (strcmp(pos, "rows"))
2317 break;
2318 *comma = ',';
2319 pos = comma + 1;
2320 // check lower theta
2321 comma = strchr(pos, ',');
2322 if (!comma)
2323 break;
2324 *comma = '\0';
2325 startTheta = atof(pos);
2326 *comma = ',';
2327 pos = comma + 1;
2328 // check upper theta
2329 comma = strchr(pos, ',');
2330 good = true;
2331 if (comma)
2332 *comma = '\0';
2333 endTheta = atof(pos);
2334 if (comma) {
2335 *comma = ',';
2336 pos = comma + 1;
2337 comma = strchr(pos, ',');
2338 if (comma)
2339 *comma = '\0';
2340 intervalTheta = atof(pos);
2341 if (comma) {
2342 *comma = ',';
2343 pos = comma + 1;
2344 comma = strchr(pos, ',');
2345 if (comma)
2346 *comma = '\0';
2347 detail = atoi(pos);
2348 if (comma)
2349 *comma = ',';
2350 }
2351 }
2352 break;
2353 }
2354 if (good) {
2355 if (startTheta < 0.0 || startTheta > endTheta || intervalTheta < 0.0)
2356 good = false;
2357 if (detail < 0 || detail > 1)
2358 good = false;
2359 }
2360 if (intervalTheta >= endTheta)
2361 intervalTheta = 0.0;
2362 if (!good) {
2363 sprintf(line, "Odd first line %s on file %s?", line, dataFile);
2364 handler_->message(CLP_GENERAL, messages_)
2365 << line << CoinMessageEol;
2366 fclose(fp);
2367 return -2;
2368 }
2369 if (!fgets(line, 200, fp)) {
2370 sprintf(line, "Not enough records on parametrics file %s?", dataFile);
2371 handler_->message(CLP_GENERAL, messages_)
2372 << line << CoinMessageEol;
2373 fclose(fp);
2374 return -2;
2375 }
2376 double *lowerRowMove = NULL;
2377 double *upperRowMove = NULL;
2378 double *lowerColumnMove = NULL;
2379 double *upperColumnMove = NULL;
2380 double *objectiveMove = NULL;
2381 char saveLine[200];
2382 saveLine[0] = '\0';
2383 std::string headingsRow[] = { "name", "number", "lower", "upper", "rhs" };
2384 int gotRow[] = { -1, -1, -1, -1, -1 };
2385 int orderRow[5];
2386 assert(sizeof(gotRow) == sizeof(orderRow));
2387 int nAcross = 0;
2388 pos = line;
2389 put = line;
2390 while (*pos >= ' ' && *pos != '\n') {
2391 if (*pos != ' ' && *pos != '\t') {
2392 *put = static_cast< char >(tolower(*pos));
2393 put++;
2394 }
2395 pos++;
2396 }
2397 *put = '\0';
2398 pos = line;
2399 int i;
2400 good = true;
2401 if (strncmp(line, "column", 6)) {
2402 while (pos) {
2403 char *comma = strchr(pos, ',');
2404 if (comma)
2405 *comma = '\0';
2406 for (i = 0; i < static_cast< int >(sizeof(gotRow) / sizeof(int)); i++) {
2407 if (headingsRow[i] == pos) {
2408 if (gotRow[i] < 0) {
2409 orderRow[nAcross] = i;
2410 gotRow[i] = nAcross++;
2411 } else {
2412 // duplicate
2413 good = false;
2414 }
2415 break;
2416 }
2417 }
2418 if (i == static_cast< int >(sizeof(gotRow) / sizeof(int)))
2419 good = false;
2420 if (comma) {
2421 *comma = ',';
2422 pos = comma + 1;
2423 } else {
2424 break;
2425 }
2426 }
2427 if (gotRow[0] < 0 && gotRow[1] < 0)
2428 good = false;
2429 if (gotRow[0] >= 0 && gotRow[1] >= 0)
2430 good = false;
2431 if (gotRow[0] >= 0 && !lengthNames())
2432 good = false;
2433 if (gotRow[4] < 0) {
2434 if (gotRow[2] < 0 && gotRow[3] >= 0)
2435 good = false;
2436 else if (gotRow[3] < 0 && gotRow[2] >= 0)
2437 good = false;
2438 } else if (gotRow[2] >= 0 || gotRow[3] >= 0) {
2439 good = false;
2440 }
2441 if (good) {
2442 char **rowNames = new char *[numberRows_];
2443 int iRow;
2444 for (iRow = 0; iRow < numberRows_; iRow++) {
2445 rowNames[iRow] = CoinStrdup(rowName(iRow).c_str());
2446 }
2447 lowerRowMove = new double[numberRows_];
2448 memset(lowerRowMove, 0, numberRows_ * sizeof(double));
2449 upperRowMove = new double[numberRows_];
2450 memset(upperRowMove, 0, numberRows_ * sizeof(double));
2451 int nLine = 0;
2452 int nBadLine = 0;
2453 int nBadName = 0;
2454 while (fgets(line, 200, fp)) {
2455 if (!strncmp(line, "ENDATA", 6) || !strncmp(line, "COLUMN", 6))
2456 break;
2457 nLine++;
2458 iRow = -1;
2459 double upper = 0.0;
2460 double lower = 0.0;
2461 char *pos = line;
2462 char *put = line;
2463 while (*pos >= ' ' && *pos != '\n') {
2464 if (*pos != ' ' && *pos != '\t') {
2465 *put = *pos;
2466 put++;
2467 }
2468 pos++;
2469 }
2470 *put = '\0';
2471 pos = line;
2472 for (int i = 0; i < nAcross; i++) {
2473 char *comma = strchr(pos, ',');
2474 if (comma) {
2475 *comma = '\0';
2476 } else if (i < nAcross - 1) {
2477 nBadLine++;
2478 break;
2479 }
2480 switch (orderRow[i]) {
2481 // name
2482 case 0:
2483 // For large problems this could be slow
2484 for (iRow = 0; iRow < numberRows_; iRow++) {
2485 if (!strcmp(rowNames[iRow], pos))
2486 break;
2487 }
2488 if (iRow == numberRows_)
2489 iRow = -1;
2490 break;
2491 // number
2492 case 1:
2493 iRow = atoi(pos);
2494 if (iRow < 0 || iRow >= numberRows_)
2495 iRow = -1;
2496 break;
2497 // lower
2498 case 2:
2499 upper = atof(pos);
2500 break;
2501 // upper
2502 case 3:
2503 lower = atof(pos);
2504 break;
2505 // rhs
2506 case 4:
2507 lower = atof(pos);
2508 upper = lower;
2509 break;
2510 }
2511 if (comma) {
2512 *comma = ',';
2513 pos = comma + 1;
2514 }
2515 }
2516 if (iRow >= 0) {
2517 if (rowLower_[iRow] > -1.0e20)
2518 lowerRowMove[iRow] = lower;
2519 else
2520 lowerRowMove[iRow] = 0.0;
2521 if (rowUpper_[iRow] < 1.0e20)
2522 upperRowMove[iRow] = upper;
2523 else
2524 upperRowMove[iRow] = lower;
2525 } else {
2526 nBadName++;
2527 if (saveLine[0] == '\0')
2528 strcpy(saveLine, line);
2529 }
2530 }
2531 sprintf(line, "%d Row fields and %d records", nAcross, nLine);
2532 handler_->message(CLP_GENERAL, messages_)
2533 << line << CoinMessageEol;
2534 if (nBadName) {
2535 sprintf(line, " ** %d records did not match on name/sequence, first bad %s", nBadName, saveLine);
2536 handler_->message(CLP_GENERAL, messages_)
2537 << line << CoinMessageEol;
2538 returnCode = -1;
2539 good = false;
2540 }
2541 for (iRow = 0; iRow < numberRows_; iRow++) {
2542 free(rowNames[iRow]);
2543 }
2544 delete[] rowNames;
2545 } else {
2546 sprintf(line, "Duplicate or unknown keyword - or name/number fields wrong");
2547 handler_->message(CLP_GENERAL, messages_)
2548 << line << CoinMessageEol;
2549 returnCode = -1;
2550 good = false;
2551 }
2552 }
2553 if (good && (!strncmp(line, "COLUMN", 6) || !strncmp(line, "column", 6))) {
2554 if (!fgets(line, 200, fp)) {
2555 sprintf(line, "Not enough records on parametrics file %s after COLUMNS?", dataFile);
2556 handler_->message(CLP_GENERAL, messages_)
2557 << line << CoinMessageEol;
2558 fclose(fp);
2559 return -2;
2560 }
2561 std::string headingsColumn[] = { "name", "number", "lower", "upper", "objective" };
2562 saveLine[0] = '\0';
2563 int gotColumn[] = { -1, -1, -1, -1, -1 };
2564 int orderColumn[5];
2565 assert(sizeof(gotColumn) == sizeof(orderColumn));
2566 nAcross = 0;
2567 pos = line;
2568 put = line;
2569 while (*pos >= ' ' && *pos != '\n') {
2570 if (*pos != ' ' && *pos != '\t') {
2571 *put = static_cast< char >(tolower(*pos));
2572 put++;
2573 }
2574 pos++;
2575 }
2576 *put = '\0';
2577 pos = line;
2578 int i;
2579 if (strncmp(line, "endata", 6) && good) {
2580 while (pos) {
2581 char *comma = strchr(pos, ',');
2582 if (comma)
2583 *comma = '\0';
2584 for (i = 0; i < static_cast< int >(sizeof(gotColumn) / sizeof(int)); i++) {
2585 if (headingsColumn[i] == pos) {
2586 if (gotColumn[i] < 0) {
2587 orderColumn[nAcross] = i;
2588 gotColumn[i] = nAcross++;
2589 } else {
2590 // duplicate
2591 good = false;
2592 }
2593 break;
2594 }
2595 }
2596 if (i == static_cast< int >(sizeof(gotColumn) / sizeof(int)))
2597 good = false;
2598 if (comma) {
2599 *comma = ',';
2600 pos = comma + 1;
2601 } else {
2602 break;
2603 }
2604 }
2605 if (gotColumn[0] < 0 && gotColumn[1] < 0)
2606 good = false;
2607 if (gotColumn[0] >= 0 && gotColumn[1] >= 0)
2608 good = false;
2609 if (gotColumn[0] >= 0 && !lengthNames())
2610 good = false;
2611 if (good) {
2612 char **columnNames = new char *[numberColumns_];
2613 int iColumn;
2614 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2615 columnNames[iColumn] = CoinStrdup(columnName(iColumn).c_str());
2616 }
2617 lowerColumnMove = new double[numberColumns_];
2618 memset(lowerColumnMove, 0, numberColumns_ * sizeof(double));
2619 upperColumnMove = new double[numberColumns_];
2620 memset(upperColumnMove, 0, numberColumns_ * sizeof(double));
2621 objectiveMove = new double[numberColumns_];
2622 memset(objectiveMove, 0, numberColumns_ * sizeof(double));
2623 int nLine = 0;
2624 int nBadLine = 0;
2625 int nBadName = 0;
2626 while (fgets(line, 200, fp)) {
2627 if (!strncmp(line, "ENDATA", 6))
2628 break;
2629 nLine++;
2630 iColumn = -1;
2631 double upper = 0.0;
2632 double lower = 0.0;
2633 double obj = 0.0;
2634 char *pos = line;
2635 char *put = line;
2636 while (*pos >= ' ' && *pos != '\n') {
2637 if (*pos != ' ' && *pos != '\t') {
2638 *put = *pos;
2639 put++;
2640 }
2641 pos++;
2642 }
2643 *put = '\0';
2644 pos = line;
2645 for (int i = 0; i < nAcross; i++) {
2646 char *comma = strchr(pos, ',');
2647 if (comma) {
2648 *comma = '\0';
2649 } else if (i < nAcross - 1) {
2650 nBadLine++;
2651 break;
2652 }
2653 switch (orderColumn[i]) {
2654 // name
2655 case 0:
2656 // For large problems this could be slow
2657 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2658 if (!strcmp(columnNames[iColumn], pos))
2659 break;
2660 }
2661 if (iColumn == numberColumns_)
2662 iColumn = -1;
2663 break;
2664 // number
2665 case 1:
2666 iColumn = atoi(pos);
2667 if (iColumn < 0 || iColumn >= numberColumns_)
2668 iColumn = -1;
2669 break;
2670 // lower
2671 case 2:
2672 upper = atof(pos);
2673 break;
2674 // upper
2675 case 3:
2676 lower = atof(pos);
2677 break;
2678 // objective
2679 case 4:
2680 obj = atof(pos);
2681 upper = lower;
2682 break;
2683 }
2684 if (comma) {
2685 *comma = ',';
2686 pos = comma + 1;
2687 }
2688 }
2689 if (iColumn >= 0) {
2690 if (columnLower_[iColumn] > -1.0e20)
2691 lowerColumnMove[iColumn] = lower;
2692 else
2693 lowerColumnMove[iColumn] = 0.0;
2694 if (columnUpper_[iColumn] < 1.0e20)
2695 upperColumnMove[iColumn] = upper;
2696 else
2697 upperColumnMove[iColumn] = lower;
2698 objectiveMove[iColumn] = obj;
2699 } else {
2700 nBadName++;
2701 if (saveLine[0] == '\0')
2702 strcpy(saveLine, line);
2703 }
2704 }
2705 sprintf(line, "%d Column fields and %d records", nAcross, nLine);
2706 handler_->message(CLP_GENERAL, messages_)
2707 << line << CoinMessageEol;
2708 if (nBadName) {
2709 sprintf(line, " ** %d records did not match on name/sequence, first bad %s", nBadName, saveLine);
2710 handler_->message(CLP_GENERAL, messages_)
2711 << line << CoinMessageEol;
2712 returnCode = -1;
2713 good = false;
2714 }
2715 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2716 free(columnNames[iColumn]);
2717 }
2718 delete[] columnNames;
2719 } else {
2720 sprintf(line, "Duplicate or unknown keyword - or name/number fields wrong");
2721 handler_->message(CLP_GENERAL, messages_)
2722 << line << CoinMessageEol;
2723 returnCode = -1;
2724 good = false;
2725 }
2726 }
2727 }
2728 returnCode = -1;
2729 if (good) {
2730 // clean arrays
2731 if (lowerRowMove) {
2732 bool empty = true;
2733 for (int i = 0; i < numberRows_; i++) {
2734 if (lowerRowMove[i]) {
2735 empty = false;
2736 break;
2737 }
2738 }
2739 if (empty) {
2740 delete[] lowerRowMove;
2741 lowerRowMove = NULL;
2742 }
2743 }
2744 if (upperRowMove) {
2745 bool empty = true;
2746 for (int i = 0; i < numberRows_; i++) {
2747 if (upperRowMove[i]) {
2748 empty = false;
2749 break;
2750 }
2751 }
2752 if (empty) {
2753 delete[] upperRowMove;
2754 upperRowMove = NULL;
2755 }
2756 }
2757 if (lowerColumnMove) {
2758 bool empty = true;
2759 for (int i = 0; i < numberColumns_; i++) {
2760 if (lowerColumnMove[i]) {
2761 empty = false;
2762 break;
2763 }
2764 }
2765 if (empty) {
2766 delete[] lowerColumnMove;
2767 lowerColumnMove = NULL;
2768 }
2769 }
2770 if (upperColumnMove) {
2771 bool empty = true;
2772 for (int i = 0; i < numberColumns_; i++) {
2773 if (upperColumnMove[i]) {
2774 empty = false;
2775 break;
2776 }
2777 }
2778 if (empty) {
2779 delete[] upperColumnMove;
2780 upperColumnMove = NULL;
2781 }
2782 }
2783 if (objectiveMove) {
2784 bool empty = true;
2785 for (int i = 0; i < numberColumns_; i++) {
2786 if (objectiveMove[i]) {
2787 empty = false;
2788 break;
2789 }
2790 }
2791 if (empty) {
2792 delete[] objectiveMove;
2793 objectiveMove = NULL;
2794 }
2795 }
2796 int saveScaling = scalingFlag_;
2797 scalingFlag_ = 0;
2798 int saveLogLevel = handler_->logLevel();
2799 if (detail > 0 && !intervalTheta)
2800 handler_->setLogLevel(3);
2801 else
2802 handler_->setLogLevel(1);
2803 returnCode = parametrics(startTheta, endTheta, intervalTheta,
2804 lowerColumnMove, upperColumnMove,
2805 lowerRowMove, upperRowMove,
2806 objectiveMove);
2807 scalingFlag_ = saveScaling;
2808 handler_->setLogLevel(saveLogLevel);
2809 }
2810 delete[] lowerRowMove;
2811 delete[] upperRowMove;
2812 delete[] lowerColumnMove;
2813 delete[] upperColumnMove;
2814 delete[] objectiveMove;
2815 fclose(fp);
2816 return returnCode;
2817 }
parametricsLoop(parametricsData & paramData,double reportIncrement,const double * lowerChange,const double * upperChange,const double * changeObjective,ClpDataSave & data,bool canTryQuick)2818 int ClpSimplexOther::parametricsLoop(parametricsData ¶mData, double reportIncrement,
2819 const double *lowerChange, const double *upperChange,
2820 const double *changeObjective, ClpDataSave &data,
2821 bool canTryQuick)
2822 {
2823 double startingTheta = paramData.startingTheta;
2824 double &endingTheta = paramData.endingTheta;
2825 // stuff is already at starting
2826 // For this crude version just try and go to end
2827 double change = 0.0;
2828 if (reportIncrement && canTryQuick) {
2829 endingTheta = CoinMin(endingTheta, startingTheta + reportIncrement);
2830 change = endingTheta - startingTheta;
2831 }
2832 int numberTotal = numberRows_ + numberColumns_;
2833 int i;
2834 for (i = 0; i < numberTotal; i++) {
2835 lower_[i] += change * lowerChange[i];
2836 upper_[i] += change * upperChange[i];
2837 switch (getStatus(i)) {
2838
2839 case basic:
2840 case isFree:
2841 case superBasic:
2842 break;
2843 case isFixed:
2844 case atUpperBound:
2845 solution_[i] = upper_[i];
2846 break;
2847 case atLowerBound:
2848 solution_[i] = lower_[i];
2849 break;
2850 }
2851 cost_[i] += change * changeObjective[i];
2852 }
2853 problemStatus_ = -1;
2854
2855 // This says whether to restore things etc
2856 // startup will have factorized so can skip
2857 int factorType = 0;
2858 // Start check for cycles
2859 progress_.startCheck();
2860 // Say change made on first iteration
2861 changeMade_ = 1;
2862 /*
2863 Status of problem:
2864 0 - optimal
2865 1 - infeasible
2866 2 - unbounded
2867 -1 - iterating
2868 -2 - factorization wanted
2869 -3 - redo checking without factorization
2870 -4 - looks infeasible
2871 */
2872 while (problemStatus_ < 0) {
2873 int iRow, iColumn;
2874 // clear
2875 for (iRow = 0; iRow < 4; iRow++) {
2876 rowArray_[iRow]->clear();
2877 }
2878
2879 for (iColumn = 0; iColumn < SHORT_REGION; iColumn++) {
2880 columnArray_[iColumn]->clear();
2881 }
2882
2883 // give matrix (and model costs and bounds a chance to be
2884 // refreshed (normally null)
2885 matrix_->refresh(this);
2886 // may factorize, checks if problem finished
2887 statusOfProblemInParametrics(factorType, data);
2888 // Say good factorization
2889 factorType = 1;
2890 if (data.sparseThreshold_) {
2891 // use default at present
2892 factorization_->sparseThreshold(0);
2893 factorization_->goSparse();
2894 }
2895
2896 // exit if victory declared
2897 if (problemStatus_ >= 0 && (canTryQuick || startingTheta >= endingTheta - 1.0e-7))
2898 break;
2899
2900 // test for maximum iterations
2901 if (hitMaximumIterations()) {
2902 problemStatus_ = 3;
2903 break;
2904 }
2905 // Check event
2906 {
2907 int status = eventHandler_->event(ClpEventHandler::endOfFactorization);
2908 if (status >= 0) {
2909 problemStatus_ = 5;
2910 secondaryStatus_ = ClpEventHandler::endOfFactorization;
2911 break;
2912 }
2913 }
2914 // Do iterations
2915 problemStatus_ = -1;
2916 if (canTryQuick) {
2917 double *saveDuals = NULL;
2918 reinterpret_cast< ClpSimplexDual * >(this)->whileIterating(saveDuals, 0);
2919 } else {
2920 whileIterating(paramData, reportIncrement,
2921 changeObjective);
2922 startingTheta = endingTheta;
2923 }
2924 }
2925 if (!problemStatus_) {
2926 theta_ = change + startingTheta;
2927 eventHandler_->event(ClpEventHandler::theta);
2928 return 0;
2929 } else if (problemStatus_ == 10) {
2930 return -1;
2931 } else {
2932 return problemStatus_;
2933 }
2934 }
2935 /* Parametrics
2936 The code uses current bounds + theta * change (if change array not NULL)
2937 It starts at startingTheta and returns ending theta in endingTheta.
2938 If it can not reach input endingTheta return code will be 1 for infeasible,
2939 2 for unbounded, if error on ranges -1, otherwise 0.
2940 Event handler may do more
2941 On exit endingTheta is maximum reached (can be used for next startingTheta)
2942 */
parametrics(double startingTheta,double & endingTheta,const double * lowerChangeBound,const double * upperChangeBound,const double * lowerChangeRhs,const double * upperChangeRhs)2943 int ClpSimplexOther::parametrics(double startingTheta, double &endingTheta,
2944 const double *lowerChangeBound, const double *upperChangeBound,
2945 const double *lowerChangeRhs, const double *upperChangeRhs)
2946 {
2947 int savePerturbation = perturbation_;
2948 perturbation_ = 102; // switch off
2949 algorithm_ = -1;
2950 // extra region
2951 int maximumPivots = factorization_->maximumPivots();
2952 int numberDense = factorization_->numberDense();
2953 int length = numberRows_ + numberDense + maximumPivots;
2954 assert(!rowArray_[4]);
2955 rowArray_[4] = new CoinIndexedVector(length);
2956 assert(!rowArray_[5]);
2957 rowArray_[5] = new CoinIndexedVector(length);
2958
2959 // save data
2960 ClpDataSave data = saveData();
2961 int numberTotal = numberRows_ + numberColumns_;
2962 int ratio = static_cast< int >((2 * sizeof(int)) / sizeof(double));
2963 assert(ratio == 1 || ratio == 2);
2964 // allow for unscaled - even if not needed
2965 int lengthArrays = 4 * numberTotal + (3 * numberTotal + 2) * ratio + 2 * numberRows_ + 1;
2966 int unscaledChangesOffset = lengthArrays; // need extra copy of change
2967 lengthArrays += numberTotal;
2968
2969 /*
2970 Save information and modify
2971 */
2972 double *saveLower = new double[lengthArrays];
2973 double *saveUpper = new double[lengthArrays];
2974 double *lowerCopy = saveLower + 2 * numberTotal;
2975 double *upperCopy = saveUpper + 2 * numberTotal;
2976 double *lowerChange = saveLower + numberTotal;
2977 double *upperChange = saveUpper + numberTotal;
2978 double *lowerGap = saveLower + 4 * numberTotal;
2979 double *lowerCoefficient = lowerGap + numberRows_;
2980 double *upperGap = saveUpper + 4 * numberTotal;
2981 double *upperCoefficient = upperGap + numberRows_;
2982 int *lowerList = (reinterpret_cast< int * >(saveLower + 4 * numberTotal + 2 * numberRows_)) + 2;
2983 int *upperList = (reinterpret_cast< int * >(saveUpper + 4 * numberTotal + 2 * numberRows_)) + 2;
2984 int *lowerActive = lowerList + numberTotal + 1;
2985 int *upperActive = upperList + numberTotal + 1;
2986 // To mark as odd
2987 char *markDone = reinterpret_cast< char * >(lowerActive + numberTotal);
2988 //memset(markDone,0,numberTotal);
2989 int *backwardBasic = upperActive + numberTotal;
2990 parametricsData paramData;
2991 paramData.lowerChange = lowerChange;
2992 paramData.lowerList = lowerList;
2993 paramData.upperChange = upperChange;
2994 paramData.upperList = upperList;
2995 paramData.markDone = markDone;
2996 paramData.backwardBasic = backwardBasic;
2997 paramData.lowerActive = lowerActive;
2998 paramData.lowerGap = lowerGap;
2999 paramData.lowerCoefficient = lowerCoefficient;
3000 paramData.upperActive = upperActive;
3001 paramData.upperGap = upperGap;
3002 paramData.upperCoefficient = upperCoefficient;
3003 paramData.unscaledChangesOffset = unscaledChangesOffset - numberTotal;
3004 paramData.firstIteration = true;
3005 // Find theta when bounds will cross over and create arrays
3006 memset(lowerChange, 0, numberTotal * sizeof(double));
3007 memset(upperChange, 0, numberTotal * sizeof(double));
3008 if (lowerChangeBound)
3009 memcpy(lowerChange, lowerChangeBound, numberColumns_ * sizeof(double));
3010 if (upperChangeBound)
3011 memcpy(upperChange, upperChangeBound, numberColumns_ * sizeof(double));
3012 if (lowerChangeRhs)
3013 memcpy(lowerChange + numberColumns_,
3014 lowerChangeRhs, numberRows_ * sizeof(double));
3015 if (upperChangeRhs)
3016 memcpy(upperChange + numberColumns_,
3017 upperChangeRhs, numberRows_ * sizeof(double));
3018 // clean
3019 for (int iRow = 0; iRow < numberRows_; iRow++) {
3020 double lower = rowLower_[iRow];
3021 double upper = rowUpper_[iRow];
3022 if (lower < -1.0e30)
3023 lowerChange[numberColumns_ + iRow] = 0.0;
3024 if (upper > 1.0e30)
3025 upperChange[numberColumns_ + iRow] = 0.0;
3026 }
3027 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
3028 double lower = columnLower_[iColumn];
3029 double upper = columnUpper_[iColumn];
3030 if (lower < -1.0e30)
3031 lowerChange[iColumn] = 0.0;
3032 if (upper > 1.0e30)
3033 upperChange[iColumn] = 0.0;
3034 }
3035 // save unscaled version of changes
3036 memcpy(saveLower + unscaledChangesOffset, lowerChange, numberTotal * sizeof(double));
3037 memcpy(saveUpper + unscaledChangesOffset, upperChange, numberTotal * sizeof(double));
3038 int nLowerChange = 0;
3039 int nUpperChange = 0;
3040 for (int i = 0; i < numberColumns_; i++) {
3041 if (lowerChange[i]) {
3042 lowerList[nLowerChange++] = i;
3043 }
3044 if (upperChange[i]) {
3045 upperList[nUpperChange++] = i;
3046 }
3047 }
3048 lowerList[-2] = nLowerChange;
3049 upperList[-2] = nUpperChange;
3050 for (int i = numberColumns_; i < numberTotal; i++) {
3051 if (lowerChange[i]) {
3052 lowerList[nLowerChange++] = i;
3053 }
3054 if (upperChange[i]) {
3055 upperList[nUpperChange++] = i;
3056 }
3057 }
3058 lowerList[-1] = nLowerChange;
3059 upperList[-1] = nUpperChange;
3060 memcpy(lowerCopy, columnLower_, numberColumns_ * sizeof(double));
3061 memcpy(upperCopy, columnUpper_, numberColumns_ * sizeof(double));
3062 memcpy(lowerCopy + numberColumns_,
3063 rowLower_, numberRows_ * sizeof(double));
3064 memcpy(upperCopy + numberColumns_,
3065 rowUpper_, numberRows_ * sizeof(double));
3066 {
3067 // extra for unscaled
3068 double *unscaledCopy;
3069 unscaledCopy = lowerCopy + numberTotal;
3070 memcpy(unscaledCopy, columnLower_, numberColumns_ * sizeof(double));
3071 memcpy(unscaledCopy + numberColumns_,
3072 rowLower_, numberRows_ * sizeof(double));
3073 unscaledCopy = upperCopy + numberTotal;
3074 memcpy(unscaledCopy, columnUpper_, numberColumns_ * sizeof(double));
3075 memcpy(unscaledCopy + numberColumns_,
3076 rowUpper_, numberRows_ * sizeof(double));
3077 }
3078 int returnCode = 0;
3079 paramData.startingTheta = startingTheta;
3080 paramData.endingTheta = endingTheta;
3081 paramData.maxTheta = endingTheta;
3082 computeRhsEtc(paramData);
3083 bool swapped = false;
3084 // Dantzig
3085 #define ALL_DANTZIG
3086 #ifdef ALL_DANTZIG
3087 ClpDualRowPivot *savePivot = dualRowPivot_;
3088 dualRowPivot_ = new ClpDualRowDantzig();
3089 dualRowPivot_->setModel(this);
3090 #else
3091 ClpDualRowPivot *savePivot = NULL;
3092 #endif
3093 if (!returnCode) {
3094 assert(objective_->type() == 1);
3095 objective_->setType(2); // in case matrix empty
3096 returnCode = reinterpret_cast< ClpSimplexDual * >(this)->startupSolve(0, NULL, 0);
3097 objective_->setType(1);
3098 if (!returnCode) {
3099 double saveDualBound = dualBound_;
3100 dualBound_ = CoinMax(dualBound_, 1.0e15);
3101 swapped = true;
3102 double *temp;
3103 memcpy(saveLower, lower_, numberTotal * sizeof(double));
3104 temp = saveLower;
3105 saveLower = lower_;
3106 lower_ = temp;
3107 //columnLowerWork_ = lower_;
3108 //rowLowerWork_ = lower_ + numberColumns_;
3109 memcpy(saveUpper, upper_, numberTotal * sizeof(double));
3110 temp = saveUpper;
3111 saveUpper = upper_;
3112 upper_ = temp;
3113 //columnUpperWork_ = upper_;
3114 //rowUpperWork_ = upper_ + numberColumns_;
3115 if (rowScale_) {
3116 // scale saved and change arrays
3117 double *lowerChange = lower_ + numberTotal;
3118 double *upperChange = upper_ + numberTotal;
3119 double *lowerSave = lowerChange + numberTotal;
3120 double *upperSave = upperChange + numberTotal;
3121 for (int i = 0; i < numberColumns_; i++) {
3122 double multiplier = inverseColumnScale_[i];
3123 if (lowerSave[i] > -1.0e20)
3124 lowerSave[i] *= multiplier;
3125 if (upperSave[i] < 1.0e20)
3126 upperSave[i] *= multiplier;
3127 lowerChange[i] *= multiplier;
3128 upperChange[i] *= multiplier;
3129 }
3130 lowerChange += numberColumns_;
3131 upperChange += numberColumns_;
3132 lowerSave += numberColumns_;
3133 upperSave += numberColumns_;
3134 for (int i = 0; i < numberRows_; i++) {
3135 double multiplier = rowScale_[i];
3136 if (lowerSave[i] > -1.0e20)
3137 lowerSave[i] *= multiplier;
3138 if (upperSave[i] < 1.0e20)
3139 upperSave[i] *= multiplier;
3140 lowerChange[i] *= multiplier;
3141 upperChange[i] *= multiplier;
3142 }
3143 }
3144 //double saveEndingTheta = endingTheta;
3145 double *saveDuals = NULL;
3146 reinterpret_cast< ClpSimplexDual * >(this)->gutsOfDual(0, saveDuals, -1, data);
3147 if (numberPrimalInfeasibilities_ && sumPrimalInfeasibilities_ < 1.0e-4) {
3148 // probably can get rid of this if we adjust every change in theta
3149 //printf("INFEAS_A %d %g\n",numberPrimalInfeasibilities_,
3150 // sumPrimalInfeasibilities_);
3151 int pass = 100;
3152 while (sumPrimalInfeasibilities_) {
3153 pass--;
3154 if (!pass)
3155 break;
3156 problemStatus_ = -1;
3157 for (int iSequence = numberColumns_; iSequence < numberTotal; iSequence++) {
3158 double value = solution_[iSequence];
3159 // remember scaling
3160 if (value < lower_[iSequence] - 1.0e-9) {
3161 lowerCopy[iSequence] += value - lower_[iSequence];
3162 lower_[iSequence] = value;
3163 } else if (value > upper_[iSequence] + 1.0e-9) {
3164 upperCopy[iSequence] += value - upper_[iSequence];
3165 upper_[iSequence] = value;
3166 }
3167 }
3168 reinterpret_cast< ClpSimplexDual * >(this)->gutsOfDual(1, saveDuals, -1, data);
3169 }
3170 }
3171 if (!problemStatus_) {
3172 if (nLowerChange || nUpperChange) {
3173 #ifndef ALL_DANTZIG
3174 // Dantzig
3175 savePivot = dualRowPivot_;
3176 dualRowPivot_ = new ClpDualRowDantzig();
3177 dualRowPivot_->setModel(this);
3178 #endif
3179 //for (int i=0;i<numberRows_+numberColumns_;i++)
3180 //setFakeBound(i, noFake);
3181 // Now do parametrics
3182 handler_->message(CLP_PARAMETRICS_STATS, messages_)
3183 << startingTheta << objectiveValue() << CoinMessageEol;
3184 bool canSkipFactorization = true;
3185 while (!returnCode) {
3186 paramData.startingTheta = startingTheta;
3187 paramData.endingTheta = endingTheta;
3188 returnCode = parametricsLoop(paramData,
3189 data, canSkipFactorization);
3190 startingTheta = paramData.startingTheta;
3191 endingTheta = paramData.endingTheta;
3192 canSkipFactorization = false;
3193 if (!returnCode) {
3194 //startingTheta = endingTheta;
3195 //endingTheta = saveEndingTheta;
3196 handler_->message(CLP_PARAMETRICS_STATS, messages_)
3197 << startingTheta << objectiveValue() << CoinMessageEol;
3198 if (startingTheta >= endingTheta - primalTolerance_
3199 || problemStatus_ == 2)
3200 break;
3201 } else if (returnCode == -1) {
3202 // trouble - do external solve
3203 abort(); //needToDoSomething = true;
3204 } else if (problemStatus_ == 1) {
3205 // can't move any further
3206 handler_->message(CLP_PARAMETRICS_STATS, messages_)
3207 << endingTheta << objectiveValue() << CoinMessageEol;
3208 problemStatus_ = 0;
3209 }
3210 }
3211 }
3212 dualBound_ = saveDualBound;
3213 //reinterpret_cast<ClpSimplexDual *> (this)->gutsOfDual(0, saveDuals, -1, data);
3214 } else {
3215 // check if empty
3216 //if (!numberRows_||!matrix_->getNumElements()) {
3217 // success
3218 #ifdef CLP_USER_DRIVEN
3219 //theta_ = endingTheta;
3220 //eventHandler_->event(ClpEventHandler::theta);
3221 #endif
3222 //}
3223 }
3224 }
3225 if (problemStatus_ == 2) {
3226 delete[] ray_;
3227 ray_ = new double[numberColumns_];
3228 }
3229 if (swapped && lower_) {
3230 double *temp = saveLower;
3231 saveLower = lower_;
3232 lower_ = temp;
3233 temp = saveUpper;
3234 saveUpper = upper_;
3235 upper_ = temp;
3236 }
3237 reinterpret_cast< ClpSimplexDual * >(this)->finishSolve(0);
3238 }
3239 if (!scalingFlag_) {
3240 memcpy(columnLower_, lowerCopy, numberColumns_ * sizeof(double));
3241 memcpy(columnUpper_, upperCopy, numberColumns_ * sizeof(double));
3242 memcpy(rowLower_, lowerCopy + numberColumns_,
3243 numberRows_ * sizeof(double));
3244 memcpy(rowUpper_, upperCopy + numberColumns_,
3245 numberRows_ * sizeof(double));
3246 } else {
3247 // extra for unscaled
3248 double *unscaledCopy;
3249 unscaledCopy = lowerCopy + numberTotal;
3250 memcpy(columnLower_, unscaledCopy, numberColumns_ * sizeof(double));
3251 memcpy(rowLower_, unscaledCopy + numberColumns_,
3252 numberRows_ * sizeof(double));
3253 unscaledCopy = upperCopy + numberTotal;
3254 memcpy(columnUpper_, unscaledCopy, numberColumns_ * sizeof(double));
3255 memcpy(rowUpper_, unscaledCopy + numberColumns_,
3256 numberRows_ * sizeof(double));
3257 }
3258 delete[] saveLower;
3259 delete[] saveUpper;
3260 #ifdef ALL_DANTZIG
3261 if (savePivot) {
3262 #endif
3263 delete dualRowPivot_;
3264 dualRowPivot_ = savePivot;
3265 #ifdef ALL_DANTZIG
3266 }
3267 #endif
3268 // Restore any saved stuff
3269 restoreData(data);
3270 perturbation_ = savePerturbation;
3271 delete rowArray_[4];
3272 rowArray_[4] = NULL;
3273 delete rowArray_[5];
3274 rowArray_[5] = NULL;
3275 char line[100];
3276 sprintf(line, "Ending theta %g\n", endingTheta);
3277 handler_->message(CLP_GENERAL, messages_)
3278 << line << CoinMessageEol;
3279 return problemStatus_;
3280 }
parametricsLoop(parametricsData & paramData,ClpDataSave & data,bool canSkipFactorization)3281 int ClpSimplexOther::parametricsLoop(parametricsData ¶mData,
3282 ClpDataSave &data, bool canSkipFactorization)
3283 {
3284 double &startingTheta = paramData.startingTheta;
3285 double &endingTheta = paramData.endingTheta;
3286 int numberTotal = numberRows_ + numberColumns_;
3287 // stuff is already at starting
3288 const int *lowerList = paramData.lowerList;
3289 const int *upperList = paramData.upperList;
3290 problemStatus_ = -1;
3291 //double saveEndingTheta=endingTheta;
3292
3293 // This says whether to restore things etc
3294 // startup will have factorized so can skip
3295 int factorType = 0;
3296 // Start check for cycles
3297 progress_.startCheck();
3298 // Say change made on first iteration
3299 changeMade_ = 1;
3300 /*
3301 Status of problem:
3302 0 - optimal
3303 1 - infeasible
3304 2 - unbounded
3305 -1 - iterating
3306 -2 - factorization wanted
3307 -3 - redo checking without factorization
3308 -4 - looks infeasible
3309 */
3310 while (problemStatus_ < 0) {
3311 int iRow, iColumn;
3312 // clear
3313 for (iRow = 0; iRow < 6; iRow++) {
3314 rowArray_[iRow]->clear();
3315 }
3316
3317 for (iColumn = 0; iColumn < SHORT_REGION; iColumn++) {
3318 columnArray_[iColumn]->clear();
3319 }
3320
3321 // give matrix (and model costs and bounds a chance to be
3322 // refreshed (normally null)
3323 matrix_->refresh(this);
3324 // may factorize, checks if problem finished
3325 if (!canSkipFactorization)
3326 statusOfProblemInParametrics(factorType, data);
3327 canSkipFactorization = false;
3328 if (numberPrimalInfeasibilities_) {
3329 if (largestPrimalError_ > 1.0e3 && startingTheta > 1.0e10) {
3330 // treat as success
3331 problemStatus_ = 0;
3332 endingTheta = startingTheta;
3333 break;
3334 }
3335 // probably can get rid of this if we adjust every change in theta
3336 //printf("INFEAS %d %g\n",numberPrimalInfeasibilities_,
3337 // sumPrimalInfeasibilities_);
3338 const double *lowerChange = lower_ + numberTotal;
3339 const double *upperChange = upper_ + numberTotal;
3340 const double *startLower = lowerChange + numberTotal;
3341 const double *startUpper = upperChange + numberTotal;
3342 //startingTheta -= 1.0e-7;
3343 int nLowerChange = lowerList[-1];
3344 for (int i = 0; i < nLowerChange; i++) {
3345 int iSequence = lowerList[i];
3346 lower_[iSequence] = startLower[iSequence] + startingTheta * lowerChange[iSequence];
3347 }
3348 int nUpperChange = upperList[-1];
3349 for (int i = 0; i < nUpperChange; i++) {
3350 int iSequence = upperList[i];
3351 upper_[iSequence] = startUpper[iSequence] + startingTheta * upperChange[iSequence];
3352 }
3353 // adjust rhs in case dual uses
3354 memcpy(columnLower_, lower_, numberColumns_ * sizeof(double));
3355 memcpy(rowLower_, lower_ + numberColumns_, numberRows_ * sizeof(double));
3356 memcpy(columnUpper_, upper_, numberColumns_ * sizeof(double));
3357 memcpy(rowUpper_, upper_ + numberColumns_, numberRows_ * sizeof(double));
3358 if (rowScale_) {
3359 for (int i = 0; i < numberColumns_; i++) {
3360 double multiplier = columnScale_[i];
3361 if (columnLower_[i] > -1.0e20)
3362 columnLower_[i] *= multiplier;
3363 if (columnUpper_[i] < 1.0e20)
3364 columnUpper_[i] *= multiplier;
3365 }
3366 for (int i = 0; i < numberRows_; i++) {
3367 double multiplier = inverseRowScale_[i];
3368 if (rowLower_[i] > -1.0e20)
3369 rowLower_[i] *= multiplier;
3370 if (rowUpper_[i] < 1.0e20)
3371 rowUpper_[i] *= multiplier;
3372 }
3373 }
3374 double *saveDuals = NULL;
3375 problemStatus_ = -1;
3376 ClpObjective *saveObjective = objective_;
3377 reinterpret_cast< ClpSimplexDual * >(this)->gutsOfDual(0, saveDuals, -1, data);
3378 if (saveObjective != objective_) {
3379 delete objective_;
3380 objective_ = saveObjective;
3381 }
3382 int pass = 100;
3383 double moved = 0.0;
3384 while (sumPrimalInfeasibilities_) {
3385 //printf("INFEAS pass %d %d %g\n",100-pass,numberPrimalInfeasibilities_,
3386 // sumPrimalInfeasibilities_);
3387 pass--;
3388 if (!pass)
3389 break;
3390 problemStatus_ = -1;
3391 for (int iSequence = numberColumns_; iSequence < numberTotal; iSequence++) {
3392 double value = solution_[iSequence];
3393 if (value < lower_[iSequence] - 1.0e-9) {
3394 moved += lower_[iSequence] - value;
3395 lower_[iSequence] = value;
3396 } else if (value > upper_[iSequence] + 1.0e-9) {
3397 moved += upper_[iSequence] - value;
3398 upper_[iSequence] = value;
3399 }
3400 }
3401 if (!moved) {
3402 for (int iSequence = 0; iSequence < numberColumns_; iSequence++) {
3403 double value = solution_[iSequence];
3404 if (value < lower_[iSequence] - 1.0e-9) {
3405 moved += lower_[iSequence] - value;
3406 lower_[iSequence] = value;
3407 } else if (value > upper_[iSequence] + 1.0e-9) {
3408 moved += upper_[iSequence] - value;
3409 upper_[iSequence] = value;
3410 }
3411 }
3412 }
3413 assert(moved);
3414 reinterpret_cast< ClpSimplexDual * >(this)->gutsOfDual(1, saveDuals, -1, data);
3415 }
3416 // adjust
3417 //printf("Should adjust - moved %g\n",moved);
3418 }
3419 // Say good factorization
3420 factorType = 1;
3421 if (data.sparseThreshold_) {
3422 // use default at present
3423 factorization_->sparseThreshold(0);
3424 factorization_->goSparse();
3425 }
3426
3427 // exit if victory declared
3428 if (problemStatus_ >= 0 && startingTheta >= endingTheta - 1.0e-7)
3429 break;
3430
3431 // test for maximum iterations
3432 if (hitMaximumIterations()) {
3433 problemStatus_ = 3;
3434 break;
3435 }
3436 #ifdef CLP_USER_DRIVEN
3437 // Check event
3438 {
3439 int status = eventHandler_->event(ClpEventHandler::endOfFactorization);
3440 if (status >= 0) {
3441 problemStatus_ = 5;
3442 secondaryStatus_ = ClpEventHandler::endOfFactorization;
3443 break;
3444 }
3445 }
3446 #endif
3447 // Do iterations
3448 problemStatus_ = -1;
3449 whileIterating(paramData, 0.0,
3450 NULL);
3451 //startingTheta = endingTheta;
3452 //endingTheta = saveEndingTheta;
3453 }
3454 if (!problemStatus_ /*||problemStatus_==2*/) {
3455 theta_ = endingTheta;
3456 #ifdef CLP_USER_DRIVEN
3457 {
3458 double saveTheta = theta_;
3459 theta_ = endingTheta;
3460 int status = eventHandler_->event(ClpEventHandler::theta);
3461 if (status >= 0 && status < 10) {
3462 endingTheta = theta_;
3463 theta_ = saveTheta;
3464 problemStatus_ = -1;
3465 } else {
3466 if (status >= 10) {
3467 problemStatus_ = status - 10;
3468 startingTheta = endingTheta;
3469 }
3470 theta_ = saveTheta;
3471 }
3472 }
3473 #endif
3474 return 0;
3475 } else if (problemStatus_ == 10) {
3476 return -1;
3477 } else {
3478 return problemStatus_;
3479 }
3480 }
3481 /* Checks if finished. Updates status */
statusOfProblemInParametrics(int type,ClpDataSave & saveData)3482 void ClpSimplexOther::statusOfProblemInParametrics(int type, ClpDataSave &saveData)
3483 {
3484 if (type == 2) {
3485 // trouble - go to recovery
3486 problemStatus_ = 10;
3487 return;
3488 }
3489 if (problemStatus_ > -3 || factorization_->pivots()) {
3490 // factorize
3491 // later on we will need to recover from singularities
3492 // also we could skip if first time
3493 if (type) {
3494 // is factorization okay?
3495 if (internalFactorize(1)) {
3496 // trouble - go to recovery
3497 problemStatus_ = 10;
3498 return;
3499 }
3500 }
3501 if (problemStatus_ != -4 || factorization_->pivots() > 10)
3502 problemStatus_ = -3;
3503 }
3504 // at this stage status is -3 or -4 if looks infeasible
3505 // get primal and dual solutions
3506 gutsOfSolution(NULL, NULL);
3507 double realDualInfeasibilities = sumDualInfeasibilities_;
3508 // If bad accuracy treat as singular
3509 if ((largestPrimalError_ > 1.0e15 || largestDualError_ > 1.0e15) && numberIterations_) {
3510 // trouble - go to recovery
3511 problemStatus_ = 10;
3512 return;
3513 } else if (largestPrimalError_ < 1.0e-7 && largestDualError_ < 1.0e-7) {
3514 // Can reduce tolerance
3515 double newTolerance = CoinMax(0.99 * factorization_->pivotTolerance(), saveData.pivotTolerance_);
3516 factorization_->pivotTolerance(newTolerance);
3517 }
3518 // Check if looping
3519 int loop;
3520 if (type != 2)
3521 loop = progress_.looping();
3522 else
3523 loop = -1;
3524 if (loop >= 0) {
3525 problemStatus_ = loop; //exit if in loop
3526 if (!problemStatus_) {
3527 // declaring victory
3528 numberPrimalInfeasibilities_ = 0;
3529 sumPrimalInfeasibilities_ = 0.0;
3530 } else {
3531 problemStatus_ = 10; // instead - try other algorithm
3532 }
3533 return;
3534 } else if (loop < -1) {
3535 // something may have changed
3536 gutsOfSolution(NULL, NULL);
3537 }
3538 progressFlag_ = 0; //reset progress flag
3539 if (handler_->detail(CLP_SIMPLEX_STATUS, messages_) < 100) {
3540 handler_->message(CLP_SIMPLEX_STATUS, messages_)
3541 << numberIterations_ << objectiveValue();
3542 handler_->printing(sumPrimalInfeasibilities_ > 0.0)
3543 << sumPrimalInfeasibilities_ << numberPrimalInfeasibilities_;
3544 handler_->printing(sumDualInfeasibilities_ > 0.0)
3545 << sumDualInfeasibilities_ << numberDualInfeasibilities_;
3546 handler_->printing(numberDualInfeasibilitiesWithoutFree_
3547 < numberDualInfeasibilities_)
3548 << numberDualInfeasibilitiesWithoutFree_;
3549 handler_->message() << CoinMessageEol;
3550 }
3551 #ifdef CLP_USER_DRIVEN
3552 if (sumPrimalInfeasibilities_ && sumPrimalInfeasibilities_ < 1.0e-7) {
3553 int status = eventHandler_->event(ClpEventHandler::slightlyInfeasible);
3554 if (status >= 0) {
3555 // fix up
3556 for (int iSequence = 0; iSequence < numberRows_ + numberColumns_; iSequence++) {
3557 double value = solution_[iSequence];
3558 if (value <= lower_[iSequence] - primalTolerance_) {
3559 lower_[iSequence] = value;
3560 } else if (value >= upper_[iSequence] + primalTolerance_) {
3561 upper_[iSequence] = value;
3562 }
3563 }
3564 numberPrimalInfeasibilities_ = 0;
3565 sumPrimalInfeasibilities_ = 0.0;
3566 }
3567 }
3568 #endif
3569 /* If we are primal feasible and any dual infeasibilities are on
3570 free variables then it is better to go to primal */
3571 if (!numberPrimalInfeasibilities_ && !numberDualInfeasibilitiesWithoutFree_ && numberDualInfeasibilities_) {
3572 problemStatus_ = 10;
3573 return;
3574 }
3575
3576 // check optimal
3577 // give code benefit of doubt
3578 if (sumOfRelaxedDualInfeasibilities_ == 0.0 && sumOfRelaxedPrimalInfeasibilities_ == 0.0) {
3579 // say optimal (with these bounds etc)
3580 numberDualInfeasibilities_ = 0;
3581 sumDualInfeasibilities_ = 0.0;
3582 numberPrimalInfeasibilities_ = 0;
3583 sumPrimalInfeasibilities_ = 0.0;
3584 }
3585 if (dualFeasible() || problemStatus_ == -4) {
3586 progress_.modifyObjective(objectiveValue_
3587 - sumDualInfeasibilities_ * dualBound_);
3588 }
3589 if (numberPrimalInfeasibilities_) {
3590 if (problemStatus_ == -4 || problemStatus_ == -5) {
3591 problemStatus_ = 1; // infeasible
3592 }
3593 } else if (numberDualInfeasibilities_) {
3594 // clean up
3595 problemStatus_ = 10;
3596 } else {
3597 problemStatus_ = 0;
3598 }
3599 lastGoodIteration_ = numberIterations_;
3600 if (problemStatus_ < 0) {
3601 sumDualInfeasibilities_ = realDualInfeasibilities; // back to say be careful
3602 if (sumDualInfeasibilities_)
3603 numberDualInfeasibilities_ = 1;
3604 }
3605 // Allow matrices to be sorted etc
3606 int fake = -999; // signal sort
3607 matrix_->correctSequence(this, fake, fake);
3608 }
3609 //static double lastThetaX=0.0;
3610 /* This has the flow between re-factorizations
3611 Reasons to come out:
3612 -1 iterations etc
3613 -2 inaccuracy
3614 -3 slight inaccuracy (and done iterations)
3615 +0 looks optimal (might be unbounded - but we will investigate)
3616 +1 looks infeasible
3617 +3 max iterations
3618 +4 accuracy problems
3619 */
whileIterating(parametricsData & paramData,double,const double *)3620 int ClpSimplexOther::whileIterating(parametricsData ¶mData, double /*reportIncrement*/,
3621 const double * /*changeObjective*/)
3622 {
3623 double &startingTheta = paramData.startingTheta;
3624 double &endingTheta = paramData.endingTheta;
3625 const double *lowerChange = paramData.lowerChange;
3626 const double *upperChange = paramData.upperChange;
3627 int numberTotal = numberColumns_ + numberRows_;
3628 const int *lowerList = paramData.lowerList;
3629 const int *upperList = paramData.upperList;
3630 //#define CLP_PARAMETRIC_DENSE_ARRAYS 2
3631 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
3632 double *lowerGap = paramData.lowerGap;
3633 double *upperGap = paramData.upperGap;
3634 double *lowerCoefficient = paramData.lowerCoefficient;
3635 double *upperCoefficient = paramData.upperCoefficient;
3636 #endif
3637 // do basic pointers
3638 int *backwardBasic = paramData.backwardBasic;
3639 for (int i = 0; i < numberTotal; i++)
3640 backwardBasic[i] = -1;
3641 for (int i = 0; i < numberRows_; i++) {
3642 int iPivot = pivotVariable_[i];
3643 backwardBasic[iPivot] = i;
3644 }
3645 {
3646 int i;
3647 for (i = 0; i < 4; i++) {
3648 rowArray_[i]->clear();
3649 }
3650 for (i = 0; i < 2; i++) {
3651 columnArray_[i]->clear();
3652 }
3653 }
3654 // if can't trust much and long way from optimal then relax
3655 if (largestPrimalError_ > 10.0)
3656 factorization_->relaxAccuracyCheck(CoinMin(1.0e2, largestPrimalError_ / 10.0));
3657 else
3658 factorization_->relaxAccuracyCheck(1.0);
3659 // status stays at -1 while iterating, >=0 finished, -2 to invert
3660 // status -3 to go to top without an invert
3661 int returnCode = -1;
3662 double lastTheta = startingTheta;
3663 double useTheta = startingTheta;
3664 while (problemStatus_ == -1) {
3665 double increaseTheta = CoinMin(endingTheta - lastTheta, 1.0e50);
3666 // Get theta for bounds - we know can't crossover
3667 int pivotType = nextTheta(1, increaseTheta, paramData,
3668 NULL);
3669 useTheta += theta_;
3670 double change = useTheta - lastTheta;
3671 if (paramData.firstIteration) {
3672 // redo rhs etc to make as accurate as possible
3673 paramData.firstIteration = false;
3674 if (change > 1.0e-14) {
3675 startingTheta = useTheta;
3676 lastTheta = startingTheta;
3677 change = 0.0;
3678 // restore rhs
3679 const double *saveLower = paramData.lowerChange + 2 * numberTotal;
3680 memcpy(columnLower_, saveLower, numberColumns_ * sizeof(double));
3681 memcpy(rowLower_, saveLower + numberColumns_, numberRows_ * sizeof(double));
3682 const double *saveUpper = paramData.upperChange + 2 * numberTotal;
3683 memcpy(columnUpper_, saveUpper, numberColumns_ * sizeof(double));
3684 memcpy(rowUpper_, saveUpper + numberColumns_, numberRows_ * sizeof(double));
3685 paramData.startingTheta = startingTheta;
3686 computeRhsEtc(paramData);
3687 redoInternalArrays();
3688 // Update solution
3689 rowArray_[4]->clear();
3690 for (int i = 0; i < numberTotal; i++) {
3691 if (getStatus(i) == atLowerBound || getStatus(i) == isFixed)
3692 solution_[i] = lower_[i];
3693 else if (getStatus(i) == atUpperBound)
3694 solution_[i] = upper_[i];
3695 }
3696 gutsOfSolution(NULL, NULL);
3697 }
3698 }
3699 if (change > 1.0e-14) {
3700 int n;
3701 n = lowerList[-1];
3702 for (int i = 0; i < n; i++) {
3703 int iSequence = lowerList[i];
3704 double thisChange = change * lowerChange[iSequence];
3705 double newValue = lower_[iSequence] + thisChange;
3706 lower_[iSequence] = newValue;
3707 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
3708 if (getStatus(iSequence) == basic) {
3709 int iRow = backwardBasic[iSequence];
3710 lowerGap[iRow] -= thisChange;
3711 } else if (getStatus(iSequence) == atLowerBound) {
3712 solution_[iSequence] = newValue;
3713 }
3714 #else
3715 if (getStatus(iSequence) == atLowerBound) {
3716 solution_[iSequence] = newValue;
3717 }
3718 #endif
3719 #if 0
3720 // may have to adjust other bound
3721 double otherValue = upper_[iSequence];
3722 if (otherValue-newValue<dualBound_) {
3723 //originalBound(iSequence,useTheta,lowerChange,upperChange);
3724 //reinterpret_cast<ClpSimplexDual *> ( this)->changeBound(iSequence);
3725 //ClpTraceDebug (fabs(lower_[iSequence]-newValue)<1.0e-5);
3726 }
3727 #endif
3728 }
3729 n = upperList[-1];
3730 for (int i = 0; i < n; i++) {
3731 int iSequence = upperList[i];
3732 double thisChange = change * upperChange[iSequence];
3733 double newValue = upper_[iSequence] + thisChange;
3734 upper_[iSequence] = newValue;
3735 if (getStatus(iSequence) == atUpperBound || getStatus(iSequence) == isFixed) {
3736 solution_[iSequence] = newValue;
3737 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
3738 } else if (getStatus(iSequence) == basic) {
3739 int iRow = backwardBasic[iSequence];
3740 upperGap[iRow] += thisChange;
3741 #endif
3742 }
3743 // may have to adjust other bound
3744 double otherValue = lower_[iSequence];
3745 if (newValue - otherValue < dualBound_) {
3746 //originalBound(iSequence,useTheta,lowerChange,upperChange);
3747 //reinterpret_cast<ClpSimplexDual *> ( this)->changeBound(iSequence);
3748 //ClpTraceDebug (fabs(upper_[iSequence]-newValue)<1.0e-5);
3749 }
3750 }
3751 }
3752 sequenceIn_ = -1;
3753 if (pivotType) {
3754 if (useTheta > lastTheta + 1.0e-9) {
3755 handler_->message(CLP_PARAMETRICS_STATS, messages_)
3756 << useTheta << objectiveValue() << CoinMessageEol;
3757 lastTheta = useTheta;
3758 }
3759 problemStatus_ = -2;
3760 if (!factorization_->pivots() && pivotRow_ < 0)
3761 problemStatus_ = 2;
3762 #ifdef CLP_USER_DRIVEN
3763 {
3764 double saveTheta = theta_;
3765 theta_ = endingTheta;
3766 if (problemStatus_ == 2 && theta_ > paramData.acceptableMaxTheta)
3767 theta_ = COIN_DBL_MAX; // we have finished
3768 int status = eventHandler_->event(ClpEventHandler::theta);
3769 if (status >= 0 && status < 10) {
3770 endingTheta = theta_;
3771 problemStatus_ = -1;
3772 continue;
3773 } else {
3774 if (status >= 10)
3775 problemStatus_ = status - 10;
3776 if (status < 0)
3777 startingTheta = useTheta;
3778 }
3779 theta_ = saveTheta;
3780 }
3781 #else
3782 startingTheta = useTheta;
3783 #endif
3784 return 4;
3785 }
3786 // choose row to go out
3787 //reinterpret_cast<ClpSimplexDual *> ( this)->dualRow(-1);
3788 if (pivotRow_ >= 0) {
3789 // we found a pivot row
3790 if (handler_->detail(CLP_SIMPLEX_PIVOTROW, messages_) < 100) {
3791 handler_->message(CLP_SIMPLEX_PIVOTROW, messages_)
3792 << pivotRow_
3793 << CoinMessageEol;
3794 }
3795 // check accuracy of weights
3796 dualRowPivot_->checkAccuracy();
3797 // do ratio test for normal iteration
3798 double bestPossiblePivot = bestPivot();
3799 if (sequenceIn_ >= 0) {
3800 // normal iteration
3801 // update the incoming column
3802 double btranAlpha = -alpha_ * directionOut_; // for check
3803 #ifndef COIN_FAC_NEW
3804 unpackPacked(rowArray_[1]);
3805 #else
3806 unpack(rowArray_[1]);
3807 #endif
3808 // and update dual weights (can do in parallel - with extra array)
3809 rowArray_[2]->clear();
3810 alpha_ = dualRowPivot_->updateWeights(rowArray_[0],
3811 rowArray_[2],
3812 rowArray_[3],
3813 rowArray_[1]);
3814 // see if update stable
3815 #ifdef CLP_DEBUG
3816 if ((handler_->logLevel() & 32))
3817 printf("btran alpha %g, ftran alpha %g\n", btranAlpha, alpha_);
3818 #endif
3819 double checkValue = 1.0e-7;
3820 // if can't trust much and long way from optimal then relax
3821 if (largestPrimalError_ > 10.0)
3822 checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_);
3823 if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > checkValue * (1.0 + fabs(alpha_))) {
3824 handler_->message(CLP_DUAL_CHECK, messages_)
3825 << btranAlpha
3826 << alpha_
3827 << CoinMessageEol;
3828 // clear arrays
3829 rowArray_[4]->clear();
3830 if (factorization_->pivots()) {
3831 dualRowPivot_->unrollWeights();
3832 problemStatus_ = -2; // factorize now
3833 rowArray_[0]->clear();
3834 rowArray_[1]->clear();
3835 columnArray_[0]->clear();
3836 returnCode = -2;
3837 break;
3838 } else {
3839 // take on more relaxed criterion
3840 double test;
3841 if (fabs(btranAlpha) < 1.0e-8 || fabs(alpha_) < 1.0e-8)
3842 test = 1.0e-1 * fabs(alpha_);
3843 else
3844 test = 1.0e-4 * (1.0 + fabs(alpha_));
3845 if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > test) {
3846 dualRowPivot_->unrollWeights();
3847 // need to reject something
3848 char x = isColumn(sequenceOut_) ? 'C' : 'R';
3849 handler_->message(CLP_SIMPLEX_FLAG, messages_)
3850 << x << sequenceWithin(sequenceOut_)
3851 << CoinMessageEol;
3852 setFlagged(sequenceOut_);
3853 progress_.clearBadTimes();
3854 lastBadIteration_ = numberIterations_; // say be more cautious
3855 rowArray_[0]->clear();
3856 rowArray_[1]->clear();
3857 columnArray_[0]->clear();
3858 if (fabs(alpha_) < 1.0e-10 && fabs(btranAlpha) < 1.0e-8 && numberIterations_ > 100) {
3859 //printf("I think should declare infeasible\n");
3860 problemStatus_ = 1;
3861 returnCode = 1;
3862 break;
3863 }
3864 continue;
3865 }
3866 }
3867 }
3868 // update duals BEFORE replaceColumn so can do updateColumn
3869 double objectiveChange = 0.0;
3870 // do duals first as variables may flip bounds
3871 // rowArray_[0] and columnArray_[0] may have flips
3872 // so use rowArray_[3] for work array from here on
3873 int nswapped = 0;
3874 //rowArray_[0]->cleanAndPackSafe(1.0e-60);
3875 //columnArray_[0]->cleanAndPackSafe(1.0e-60);
3876 #if CLP_CAN_HAVE_ZERO_OBJ
3877 if ((specialOptions_ & 16777216) == 0) {
3878 #endif
3879 nswapped = reinterpret_cast< ClpSimplexDual * >(this)->updateDualsInDual(rowArray_[0], columnArray_[0],
3880 rowArray_[2], theta_,
3881 objectiveChange, false);
3882 assert(!nswapped);
3883 #if CLP_CAN_HAVE_ZERO_OBJ
3884 } else {
3885 rowArray_[0]->clear();
3886 rowArray_[2]->clear();
3887 columnArray_[0]->clear();
3888 }
3889 #endif
3890 // which will change basic solution
3891 if (nswapped) {
3892 abort(); //needs testing
3893 factorization_->updateColumn(rowArray_[3], rowArray_[2]);
3894 dualRowPivot_->updatePrimalSolution(rowArray_[2],
3895 1.0, objectiveChange);
3896 // recompute dualOut_
3897 valueOut_ = solution_[sequenceOut_];
3898 if (directionOut_ < 0) {
3899 dualOut_ = valueOut_ - upperOut_;
3900 } else {
3901 dualOut_ = lowerOut_ - valueOut_;
3902 }
3903 }
3904 // amount primal will move
3905 double movement = -dualOut_ * directionOut_ / alpha_;
3906 // so objective should increase by fabs(dj)*movement
3907 // but we already have objective change - so check will be good
3908 if (objectiveChange + fabs(movement * dualIn_) < -1.0e-5) {
3909 #ifdef CLP_DEBUG
3910 if (handler_->logLevel() & 32)
3911 printf("movement %g, swap change %g, rest %g * %g\n",
3912 objectiveChange + fabs(movement * dualIn_),
3913 objectiveChange, movement, dualIn_);
3914 #endif
3915 assert(objectiveChange + fabs(movement * dualIn_) >= -1.0e-5);
3916 if (factorization_->pivots()) {
3917 // going backwards - factorize
3918 dualRowPivot_->unrollWeights();
3919 problemStatus_ = -2; // factorize now
3920 returnCode = -2;
3921 break;
3922 }
3923 }
3924 CoinAssert(fabs(dualOut_) < 1.0e50);
3925 // if stable replace in basis
3926 int updateStatus = factorization_->replaceColumn(this,
3927 rowArray_[2],
3928 rowArray_[1],
3929 pivotRow_,
3930 alpha_);
3931 // if no pivots, bad update but reasonable alpha - take and invert
3932 if (updateStatus == 2 && !factorization_->pivots() && fabs(alpha_) > 1.0e-5)
3933 updateStatus = 4;
3934 if (updateStatus == 1 || updateStatus == 4) {
3935 // slight error
3936 if (factorization_->pivots() > 5 || updateStatus == 4) {
3937 problemStatus_ = -2; // factorize now
3938 returnCode = -3;
3939 }
3940 } else if (updateStatus == 2) {
3941 // major error
3942 dualRowPivot_->unrollWeights();
3943 // later we may need to unwind more e.g. fake bounds
3944 if (factorization_->pivots()) {
3945 problemStatus_ = -2; // factorize now
3946 returnCode = -2;
3947 break;
3948 } else {
3949 // need to reject something
3950 char x = isColumn(sequenceOut_) ? 'C' : 'R';
3951 handler_->message(CLP_SIMPLEX_FLAG, messages_)
3952 << x << sequenceWithin(sequenceOut_)
3953 << CoinMessageEol;
3954 setFlagged(sequenceOut_);
3955 progress_.clearBadTimes();
3956 lastBadIteration_ = numberIterations_; // say be more cautious
3957 rowArray_[0]->clear();
3958 rowArray_[1]->clear();
3959 columnArray_[0]->clear();
3960 // make sure dual feasible
3961 // look at all rows and columns
3962 double objectiveChange = 0.0;
3963 reinterpret_cast< ClpSimplexDual * >(this)->updateDualsInDual(rowArray_[0], columnArray_[0], rowArray_[1],
3964 0.0, objectiveChange, true);
3965 continue;
3966 }
3967 } else if (updateStatus == 3) {
3968 // out of memory
3969 // increase space if not many iterations
3970 if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200)
3971 factorization_->areaFactor(
3972 factorization_->areaFactor() * 1.1);
3973 problemStatus_ = -2; // factorize now
3974 } else if (updateStatus == 5) {
3975 problemStatus_ = -2; // factorize now
3976 }
3977 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
3978 int *lowerActive = paramData.lowerActive;
3979 int *upperActive = paramData.upperActive;
3980 #endif
3981 // update change vector
3982 {
3983 double *work = rowArray_[1]->denseVector();
3984 int number = rowArray_[1]->getNumElements();
3985 int *which = rowArray_[1]->getIndices();
3986 assert(!rowArray_[4]->packedMode());
3987 #ifndef COIN_FAC_NEW
3988 assert(rowArray_[1]->packedMode());
3989 #else
3990 assert(!rowArray_[1]->packedMode());
3991 #endif
3992 double pivotValue = rowArray_[4]->denseVector()[pivotRow_];
3993 double multiplier = -pivotValue / alpha_;
3994 double *array = rowArray_[4]->denseVector();
3995 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
3996 int lowerN = lowerActive[-1];
3997 int upperN = upperActive[-1];
3998 #endif
3999 if (multiplier) {
4000 for (int i = 0; i < number; i++) {
4001 int iRow = which[i];
4002 #ifndef COIN_FAC_NEW
4003 double alpha = multiplier * work[i];
4004 #else
4005 double alpha = multiplier * work[iRow];
4006 #endif
4007 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
4008 double alpha3 = alpha + array[iRow];
4009 int iSequence = pivotVariable_[iRow];
4010 double oldLower = lowerCoefficient[iRow];
4011 double oldUpper = upperCoefficient[iRow];
4012 if (lower_[iSequence] > -1.0e30) {
4013 //lowerGap[iRow]=value-lower_[iSequence];
4014 double alpha2 = alpha3 + lowerChange[iSequence];
4015 if (alpha2 > 1.0e-8) {
4016 lowerCoefficient[iRow] = alpha2;
4017 if (!oldLower)
4018 lowerActive[lowerN++] = iRow;
4019 } else {
4020 if (oldLower)
4021 lowerCoefficient[iRow] = COIN_DBL_MIN;
4022 }
4023 } else {
4024 if (oldLower)
4025 lowerCoefficient[iRow] = COIN_DBL_MIN;
4026 }
4027 if (upper_[iSequence] < 1.0e30) {
4028 //upperGap[iRow]=-(value-upper_[iSequence]);
4029 double alpha2 = -(alpha3 + upperChange[iSequence]);
4030 if (alpha2 > 1.0e-8) {
4031 upperCoefficient[iRow] = alpha2;
4032 if (!oldUpper)
4033 upperActive[upperN++] = iRow;
4034 } else {
4035 if (oldUpper)
4036 upperCoefficient[iRow] = COIN_DBL_MIN;
4037 }
4038 } else {
4039 if (oldUpper)
4040 upperCoefficient[iRow] = COIN_DBL_MIN;
4041 }
4042 #endif
4043 rowArray_[4]->quickAdd(iRow, alpha);
4044 }
4045 }
4046 pivotValue = array[pivotRow_];
4047 // we want pivot to be -multiplier
4048 rowArray_[4]->quickAdd(pivotRow_, -multiplier - pivotValue);
4049 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
4050 assert(lowerN >= 0 && lowerN <= numberRows_);
4051 lowerActive[-1] = lowerN;
4052 upperActive[-1] = upperN;
4053 #endif
4054 }
4055 // update primal solution
4056 #if CLP_CAN_HAVE_ZERO_OBJ
4057 if ((specialOptions_ & 16777216) != 0)
4058 theta_ = 0.0;
4059 #endif
4060 if (theta_ < 0.0) {
4061 #ifdef CLP_DEBUG
4062 if (handler_->logLevel() & 32)
4063 printf("negative theta %g\n", theta_);
4064 #endif
4065 theta_ = 0.0;
4066 }
4067 // do actual flips
4068 reinterpret_cast< ClpSimplexDual * >(this)->flipBounds(rowArray_[0], columnArray_[0]);
4069 //rowArray_[1]->expand();
4070 #ifndef CLP_PARAMETRIC_DENSE_ARRAYS
4071 dualRowPivot_->updatePrimalSolution(rowArray_[1],
4072 movement,
4073 objectiveChange);
4074 #else
4075 // do by hand
4076 {
4077 double *work = rowArray_[1]->denseVector();
4078 int number = rowArray_[1]->getNumElements();
4079 int *which = rowArray_[1]->getIndices();
4080 int i;
4081 if (rowArray_[1]->packedMode()) {
4082 for (i = 0; i < number; i++) {
4083 int iRow = which[i];
4084 int iSequence = pivotVariable_[iRow];
4085 double value = solution_[iSequence];
4086 double change = movement * work[i];
4087 value -= change;
4088 if (lower_[iSequence] > -1.0e30)
4089 lowerGap[iRow] = value - lower_[iSequence];
4090 if (upper_[iSequence] < 1.0e30)
4091 upperGap[iRow] = -(value - upper_[iSequence]);
4092 solution_[iSequence] = value;
4093 objectiveChange -= change * cost_[iSequence];
4094 work[i] = 0.0;
4095 }
4096 } else {
4097 for (i = 0; i < number; i++) {
4098 int iRow = which[i];
4099 int iSequence = pivotVariable_[iRow];
4100 double value = solution_[iSequence];
4101 double change = movement * work[iRow];
4102 value -= change;
4103 solution_[iSequence] = value;
4104 objectiveChange -= change * cost_[iSequence];
4105 work[iRow] = 0.0;
4106 }
4107 }
4108 rowArray_[1]->setNumElements(0);
4109 }
4110 #endif
4111 // modify dualout
4112 dualOut_ /= alpha_;
4113 dualOut_ *= -directionOut_;
4114 //setStatus(sequenceIn_,basic);
4115 dj_[sequenceIn_] = 0.0;
4116 //double oldValue = valueIn_;
4117 if (directionIn_ == -1) {
4118 // as if from upper bound
4119 valueIn_ = upperIn_ + dualOut_;
4120 } else {
4121 // as if from lower bound
4122 valueIn_ = lowerIn_ + dualOut_;
4123 }
4124 objectiveChange = 0.0;
4125 #if CLP_CAN_HAVE_ZERO_OBJ
4126 if ((specialOptions_ & 16777216) == 0) {
4127 #endif
4128 for (int i = 0; i < numberTotal; i++)
4129 objectiveChange += solution_[i] * cost_[i];
4130 objectiveChange -= objectiveValue_;
4131 #if CLP_CAN_HAVE_ZERO_OBJ
4132 }
4133 #endif
4134 // outgoing
4135 originalBound(sequenceOut_, useTheta, lowerChange, upperChange);
4136 lowerOut_ = lower_[sequenceOut_];
4137 upperOut_ = upper_[sequenceOut_];
4138 // set dj to zero unless values pass
4139 if (directionOut_ > 0) {
4140 valueOut_ = lowerOut_;
4141 dj_[sequenceOut_] = theta_;
4142 #if CLP_CAN_HAVE_ZERO_OBJ > 1
4143 #ifdef COIN_REUSE_RANDOM
4144 if ((specialOptions_ & 16777216) != 0) {
4145 dj_[sequenceOut_] = 1.0e-9 * (1.0 + CoinDrand48());
4146 ;
4147 }
4148 #endif
4149 #endif
4150 } else {
4151 valueOut_ = upperOut_;
4152 dj_[sequenceOut_] = -theta_;
4153 #if CLP_CAN_HAVE_ZERO_OBJ > 1
4154 #ifdef COIN_REUSE_RANDOM
4155 if ((specialOptions_ & 16777216) != 0) {
4156 dj_[sequenceOut_] = -1.0e-9 * (1.0 + CoinDrand48());
4157 ;
4158 }
4159 #endif
4160 #endif
4161 }
4162 solution_[sequenceOut_] = valueOut_;
4163 int whatNext = housekeeping(objectiveChange);
4164 reinterpret_cast< ClpSimplexDual * >(this)->originalBound(sequenceIn_);
4165 assert(backwardBasic[sequenceOut_] == pivotRow_);
4166 backwardBasic[sequenceOut_] = -1;
4167 backwardBasic[sequenceIn_] = pivotRow_;
4168 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
4169 double value = solution_[sequenceIn_];
4170 double alpha = rowArray_[4]->denseVector()[pivotRow_];
4171 double oldLower = lowerCoefficient[pivotRow_];
4172 double oldUpper = upperCoefficient[pivotRow_];
4173 if (lower_[sequenceIn_] > -1.0e30) {
4174 lowerGap[pivotRow_] = value - lower_[sequenceIn_];
4175 double alpha2 = alpha + lowerChange[sequenceIn_];
4176 if (alpha2 > 1.0e-8) {
4177 lowerCoefficient[pivotRow_] = alpha2;
4178 if (!oldLower) {
4179 int lowerN = lowerActive[-1];
4180 assert(lowerN >= 0 && lowerN < numberRows_);
4181 lowerActive[lowerN] = pivotRow_;
4182 lowerActive[-1] = lowerN + 1;
4183 }
4184 } else {
4185 if (oldLower)
4186 lowerCoefficient[pivotRow_] = COIN_DBL_MIN;
4187 }
4188 } else {
4189 if (oldLower)
4190 lowerCoefficient[pivotRow_] = COIN_DBL_MIN;
4191 }
4192 if (upper_[sequenceIn_] < 1.0e30) {
4193 upperGap[pivotRow_] = -(value - upper_[sequenceIn_]);
4194 double alpha2 = -(alpha + upperChange[sequenceIn_]);
4195 if (alpha2 > 1.0e-8) {
4196 upperCoefficient[pivotRow_] = alpha2;
4197 if (!oldUpper) {
4198 int upperN = upperActive[-1];
4199 assert(upperN >= 0 && upperN < numberRows_);
4200 upperActive[upperN] = pivotRow_;
4201 upperActive[-1] = upperN + 1;
4202 }
4203 } else {
4204 if (oldUpper)
4205 upperCoefficient[pivotRow_] = COIN_DBL_MIN;
4206 }
4207 } else {
4208 if (oldUpper)
4209 upperCoefficient[pivotRow_] = COIN_DBL_MIN;
4210 }
4211 #endif
4212 {
4213 char in[200], out[200];
4214 int iSequence = sequenceIn_;
4215 if (iSequence < numberColumns_) {
4216 if (lengthNames_)
4217 strcpy(in, columnNames_[iSequence].c_str());
4218 else
4219 sprintf(in, "C%7.7d", iSequence);
4220 } else {
4221 iSequence -= numberColumns_;
4222 if (lengthNames_)
4223 strcpy(in, rowNames_[iSequence].c_str());
4224 else
4225 sprintf(in, "R%7.7d", iSequence);
4226 }
4227 iSequence = sequenceOut_;
4228 if (iSequence < numberColumns_) {
4229 if (lengthNames_)
4230 strcpy(out, columnNames_[iSequence].c_str());
4231 else
4232 sprintf(out, "C%7.7d", iSequence);
4233 } else {
4234 iSequence -= numberColumns_;
4235 if (lengthNames_)
4236 strcpy(out, rowNames_[iSequence].c_str());
4237 else
4238 sprintf(out, "R%7.7d", iSequence);
4239 }
4240 handler_->message(CLP_PARAMETRICS_STATS2, messages_)
4241 << useTheta << objectiveValue()
4242 << in << out << CoinMessageEol;
4243 }
4244 if (useTheta > lastTheta + 1.0e-9) {
4245 handler_->message(CLP_PARAMETRICS_STATS, messages_)
4246 << useTheta << objectiveValue() << CoinMessageEol;
4247 lastTheta = useTheta;
4248 }
4249 // and set bounds correctly
4250 originalBound(sequenceIn_, useTheta, lowerChange, upperChange);
4251 reinterpret_cast< ClpSimplexDual * >(this)->changeBound(sequenceOut_);
4252 if (whatNext == 1) {
4253 problemStatus_ = -2; // refactorize
4254 } else if (whatNext == 2) {
4255 // maximum iterations or equivalent
4256 problemStatus_ = 3;
4257 returnCode = 3;
4258 break;
4259 }
4260 #ifdef CLP_USER_DRIVEN
4261 // Check event
4262 {
4263 int status = eventHandler_->event(ClpEventHandler::endOfIteration);
4264 if (status >= 0) {
4265 problemStatus_ = 5;
4266 secondaryStatus_ = ClpEventHandler::endOfIteration;
4267 returnCode = 4;
4268 break;
4269 }
4270 }
4271 #endif
4272 } else {
4273 // no incoming column is valid
4274 #ifdef CLP_USER_DRIVEN
4275 rowArray_[0]->clear();
4276 columnArray_[0]->clear();
4277 theta_ = useTheta;
4278 lastTheta = useTheta;
4279 int action = eventHandler_->event(ClpEventHandler::noTheta);
4280 if (action >= 0) {
4281 endingTheta = theta_;
4282 theta_ = 0.0;
4283 //adjust [4] from handler - but
4284 //rowArray_[4]->clear(); // temp
4285 if (action >= 0 && action < 10)
4286 problemStatus_ = -1; // carry on
4287 else if (action == 15)
4288 problemStatus_ = 5; // say stopped
4289 returnCode = 1;
4290 if (action == 0 || action >= 10)
4291 break;
4292 else
4293 continue;
4294 } else {
4295 theta_ = 0.0;
4296 }
4297 #endif
4298 pivotRow_ = -1;
4299 #ifdef CLP_DEBUG
4300 if (handler_->logLevel() & 32)
4301 printf("** no column pivot\n");
4302 #endif
4303 if (factorization_->pivots() < 10) {
4304 // If we have just factorized and infeasibility reasonable say infeas
4305 if (((specialOptions_ & 4096) != 0 || bestPossiblePivot < 1.0e-11) && dualBound_ > 1.0e8) {
4306 if (valueOut_ > upperOut_ + 1.0e-3 || valueOut_ < lowerOut_ - 1.0e-3
4307 || (specialOptions_ & 64) == 0) {
4308 // say infeasible
4309 problemStatus_ = 1;
4310 // unless primal feasible!!!!
4311 //printf("%d %g %d %g\n",numberPrimalInfeasibilities_,sumPrimalInfeasibilities_,
4312 // numberDualInfeasibilities_,sumDualInfeasibilities_);
4313 if (numberDualInfeasibilities_)
4314 problemStatus_ = 10;
4315 rowArray_[0]->clear();
4316 columnArray_[0]->clear();
4317 }
4318 }
4319 // If special option set - put off as long as possible
4320 if ((specialOptions_ & 64) == 0) {
4321 problemStatus_ = -4; //say looks infeasible
4322 } else {
4323 // flag
4324 char x = isColumn(sequenceOut_) ? 'C' : 'R';
4325 handler_->message(CLP_SIMPLEX_FLAG, messages_)
4326 << x << sequenceWithin(sequenceOut_)
4327 << CoinMessageEol;
4328 setFlagged(sequenceOut_);
4329 if (!factorization_->pivots()) {
4330 rowArray_[0]->clear();
4331 columnArray_[0]->clear();
4332 continue;
4333 }
4334 }
4335 }
4336 rowArray_[0]->clear();
4337 columnArray_[0]->clear();
4338 returnCode = 1;
4339 break;
4340 }
4341 } else {
4342 // no pivot row
4343 #ifdef CLP_USER_DRIVEN
4344 {
4345 double saveTheta = theta_;
4346 theta_ = endingTheta;
4347 int status = eventHandler_->event(ClpEventHandler::theta);
4348 if (status >= 0 && status < 10) {
4349 endingTheta = theta_;
4350 theta_ = saveTheta;
4351 continue;
4352 } else {
4353 theta_ = saveTheta;
4354 }
4355 }
4356 #endif
4357 #ifdef CLP_DEBUG
4358 if (handler_->logLevel() & 32)
4359 printf("** no row pivot\n");
4360 #endif
4361 int numberPivots = factorization_->pivots();
4362 bool specialCase;
4363 int useNumberFake;
4364 returnCode = 0;
4365 if (numberPivots < 20 && (specialOptions_ & 2048) != 0 && !numberChanged_ && perturbation_ >= 100
4366 && dualBound_ > 1.0e8) {
4367 specialCase = true;
4368 // as dual bound high - should be okay
4369 useNumberFake = 0;
4370 } else {
4371 specialCase = false;
4372 useNumberFake = numberFake_;
4373 }
4374 if (!numberPivots || specialCase) {
4375 // may have crept through - so may be optimal
4376 // check any flagged variables
4377 int iRow;
4378 for (iRow = 0; iRow < numberRows_; iRow++) {
4379 int iPivot = pivotVariable_[iRow];
4380 if (flagged(iPivot))
4381 break;
4382 }
4383 if (iRow < numberRows_ && numberPivots) {
4384 // try factorization
4385 returnCode = -2;
4386 }
4387
4388 if (useNumberFake || numberDualInfeasibilities_) {
4389 // may be dual infeasible
4390 problemStatus_ = -5;
4391 } else {
4392 if (iRow < numberRows_) {
4393 problemStatus_ = -5;
4394 } else {
4395 if (numberPivots) {
4396 // objective may be wrong
4397 objectiveValue_ = innerProduct(cost_,
4398 numberColumns_ + numberRows_,
4399 solution_);
4400 objectiveValue_ += objective_->nonlinearOffset();
4401 objectiveValue_ /= (objectiveScale_ * rhsScale_);
4402 if ((specialOptions_ & 16384) == 0) {
4403 // and dual_ may be wrong (i.e. for fixed or basic)
4404 CoinIndexedVector *arrayVector = rowArray_[1];
4405 arrayVector->clear();
4406 int iRow;
4407 double *array = arrayVector->denseVector();
4408 /* Use dual_ instead of array
4409 Even though dual_ is only numberRows_ long this is
4410 okay as gets permuted to longer rowArray_[2]
4411 */
4412 arrayVector->setDenseVector(dual_);
4413 int *index = arrayVector->getIndices();
4414 int number = 0;
4415 for (iRow = 0; iRow < numberRows_; iRow++) {
4416 int iPivot = pivotVariable_[iRow];
4417 double value = cost_[iPivot];
4418 dual_[iRow] = value;
4419 if (value) {
4420 index[number++] = iRow;
4421 }
4422 }
4423 arrayVector->setNumElements(number);
4424 // Extended duals before "updateTranspose"
4425 matrix_->dualExpanded(this, arrayVector, NULL, 0);
4426 // Btran basic costs
4427 rowArray_[2]->clear();
4428 factorization_->updateColumnTranspose(rowArray_[2], arrayVector);
4429 // and return vector
4430 arrayVector->setDenseVector(array);
4431 }
4432 }
4433 problemStatus_ = 0;
4434 sumPrimalInfeasibilities_ = 0.0;
4435 if ((specialOptions_ & (1024 + 16384)) != 0) {
4436 CoinIndexedVector *arrayVector = rowArray_[1];
4437 arrayVector->clear();
4438 double *rhs = arrayVector->denseVector();
4439 times(1.0, solution_, rhs);
4440 bool bad2 = false;
4441 int i;
4442 for (i = 0; i < numberRows_; i++) {
4443 if (rhs[i] < rowLowerWork_[i] - primalTolerance_ || rhs[i] > rowUpperWork_[i] + primalTolerance_) {
4444 bad2 = true;
4445 } else if (fabs(rhs[i] - rowActivityWork_[i]) > 1.0e-3) {
4446 }
4447 rhs[i] = 0.0;
4448 }
4449 for (i = 0; i < numberColumns_; i++) {
4450 if (solution_[i] < columnLowerWork_[i] - primalTolerance_ || solution_[i] > columnUpperWork_[i] + primalTolerance_) {
4451 bad2 = true;
4452 }
4453 }
4454 if (bad2) {
4455 problemStatus_ = -3;
4456 returnCode = -2;
4457 // Force to re-factorize early next time
4458 int numberPivots = factorization_->pivots();
4459 forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1);
4460 }
4461 }
4462 }
4463 }
4464 } else {
4465 problemStatus_ = -3;
4466 returnCode = -2;
4467 // Force to re-factorize early next time
4468 int numberPivots = factorization_->pivots();
4469 forceFactorization_ = CoinMin(forceFactorization_, (numberPivots + 1) >> 1);
4470 }
4471 break;
4472 }
4473 }
4474 startingTheta = lastTheta + theta_;
4475 return returnCode;
4476 }
4477 // Compute new rowLower_ etc (return negative if infeasible - otherwise largest change)
4478 double
computeRhsEtc(parametricsData & paramData)4479 ClpSimplexOther::computeRhsEtc(parametricsData ¶mData)
4480 {
4481 double maxTheta = COIN_DBL_MAX;
4482 double largestChange = 0.0;
4483 double startingTheta = paramData.startingTheta;
4484 const double *lowerChange = paramData.lowerChange + paramData.unscaledChangesOffset;
4485 const double *upperChange = paramData.upperChange + paramData.unscaledChangesOffset;
4486 for (int iRow = 0; iRow < numberRows_; iRow++) {
4487 double lower = rowLower_[iRow];
4488 double upper = rowUpper_[iRow];
4489 double chgLower = lowerChange[numberColumns_ + iRow];
4490 largestChange = CoinMax(largestChange, fabs(chgLower));
4491 double chgUpper = upperChange[numberColumns_ + iRow];
4492 largestChange = CoinMax(largestChange, fabs(chgUpper));
4493 if (lower > -1.0e30 && upper < 1.0e30) {
4494 if (lower + maxTheta * chgLower > upper + maxTheta * chgUpper) {
4495 maxTheta = (upper - lower) / (chgLower - chgUpper);
4496 }
4497 }
4498 lower += startingTheta * chgLower;
4499 upper += startingTheta * chgUpper;
4500 #ifndef CLP_USER_DRIVEN
4501 if (lower > upper) {
4502 maxTheta = -1.0;
4503 break;
4504 }
4505 #endif
4506 rowLower_[iRow] = lower;
4507 rowUpper_[iRow] = upper;
4508 }
4509 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
4510 double lower = columnLower_[iColumn];
4511 double upper = columnUpper_[iColumn];
4512 double chgLower = lowerChange[iColumn];
4513 largestChange = CoinMax(largestChange, fabs(chgLower));
4514 double chgUpper = upperChange[iColumn];
4515 largestChange = CoinMax(largestChange, fabs(chgUpper));
4516 if (lower > -1.0e30 && upper < 1.0e30) {
4517 if (lower + maxTheta * chgLower > upper + maxTheta * chgUpper) {
4518 maxTheta = (upper - lower) / (chgLower - chgUpper);
4519 }
4520 }
4521 lower += startingTheta * chgLower;
4522 upper += startingTheta * chgUpper;
4523 #ifndef CLP_USER_DRIVEN
4524 if (lower > upper) {
4525 maxTheta = -1.0;
4526 break;
4527 }
4528 #endif
4529 columnLower_[iColumn] = lower;
4530 columnUpper_[iColumn] = upper;
4531 }
4532 #ifndef CLP_USER_DRIVEN
4533 paramData.maxTheta = maxTheta;
4534 if (maxTheta < 0)
4535 largestChange = -1.0; // signal infeasible
4536 #else
4537 // maxTheta already set
4538 /* given largest change element choose acceptable end
4539 be safe and make sure difference < 0.1*tolerance */
4540 double acceptableDifference = 0.1 * primalTolerance_ / CoinMax(largestChange, 1.0);
4541 paramData.acceptableMaxTheta = maxTheta - acceptableDifference;
4542 #endif
4543 return largestChange;
4544 }
4545 // Redo lower_ from rowLower_ etc
redoInternalArrays()4546 void ClpSimplexOther::redoInternalArrays()
4547 {
4548 double *lowerSave = lower_;
4549 double *upperSave = upper_;
4550 memcpy(lowerSave, columnLower_, numberColumns_ * sizeof(double));
4551 memcpy(lowerSave + numberColumns_, rowLower_, numberRows_ * sizeof(double));
4552 memcpy(upperSave, columnUpper_, numberColumns_ * sizeof(double));
4553 memcpy(upperSave + numberColumns_, rowUpper_, numberRows_ * sizeof(double));
4554 if (rowScale_) {
4555 // scale arrays
4556 for (int i = 0; i < numberColumns_; i++) {
4557 double multiplier = inverseColumnScale_[i];
4558 if (lowerSave[i] > -1.0e20)
4559 lowerSave[i] *= multiplier;
4560 if (upperSave[i] < 1.0e20)
4561 upperSave[i] *= multiplier;
4562 }
4563 lowerSave += numberColumns_;
4564 upperSave += numberColumns_;
4565 for (int i = 0; i < numberRows_; i++) {
4566 double multiplier = rowScale_[i];
4567 if (lowerSave[i] > -1.0e20)
4568 lowerSave[i] *= multiplier;
4569 if (upperSave[i] < 1.0e20)
4570 upperSave[i] *= multiplier;
4571 }
4572 }
4573 }
4574 #if 0
4575 static int zzzzzz=0;
4576 int zzzzzzOther=0;
4577 #endif
4578 // Finds best possible pivot
4579 double
bestPivot(bool justColumns)4580 ClpSimplexOther::bestPivot(bool justColumns)
4581 {
4582 // Get good size for pivot
4583 // Allow first few iterations to take tiny
4584 double acceptablePivot = 1.0e-9;
4585 if (numberIterations_ > 100)
4586 acceptablePivot = 1.0e-8;
4587 if (factorization_->pivots() > 10 || (factorization_->pivots() && sumDualInfeasibilities_))
4588 acceptablePivot = 1.0e-5; // if we have iterated be more strict
4589 else if (factorization_->pivots() > 5)
4590 acceptablePivot = 1.0e-6; // if we have iterated be slightly more strict
4591 else if (factorization_->pivots())
4592 acceptablePivot = 1.0e-8; // relax
4593 double bestPossiblePivot = 1.0;
4594 // get sign for finding row of tableau
4595 // normal iteration
4596 // create as packed
4597 double direction = directionOut_;
4598 #ifndef COIN_FAC_NEW
4599 rowArray_[0]->createPacked(1, &pivotRow_, &direction);
4600 #else
4601 rowArray_[0]->createOneUnpackedElement(pivotRow_, direction);
4602 #endif
4603 factorization_->updateColumnTranspose(rowArray_[1], rowArray_[0]);
4604 // put row of tableau in rowArray[0] and columnArray[0]
4605 matrix_->transposeTimes(this, -1.0,
4606 rowArray_[0], rowArray_[3], columnArray_[0]);
4607 sequenceIn_ = -1;
4608 if (justColumns)
4609 rowArray_[0]->clear();
4610 // do ratio test for normal iteration
4611 bestPossiblePivot = reinterpret_cast< ClpSimplexDual * >(this)->dualColumn(rowArray_[0],
4612 columnArray_[0],
4613 #ifdef LONG_REGION_2
4614 rowArray_[2],
4615 #else
4616 columnArray_[1],
4617 #endif
4618 rowArray_[3], acceptablePivot, NULL);
4619 return bestPossiblePivot;
4620 }
4621 // Computes next theta and says if objective or bounds (0= bounds, 1 objective, -1 none)
nextTheta(int,double maxTheta,parametricsData & paramData,const double *)4622 int ClpSimplexOther::nextTheta(int /*type*/, double maxTheta, parametricsData ¶mData,
4623 const double * /*changeObjective*/)
4624 {
4625 const double *lowerChange = paramData.lowerChange;
4626 const double *upperChange = paramData.upperChange;
4627 const int *lowerList = paramData.lowerList;
4628 const int *upperList = paramData.upperList;
4629 int iSequence;
4630 bool toLower = false;
4631 //assert (type==1);
4632 // may need to decide based on model?
4633 bool needFullUpdate = rowArray_[4]->getNumElements() == 0;
4634 double *array = rowArray_[4]->denseVector();
4635 //rowArray_[4]->checkClean();
4636 const int *row = matrix_->getIndices();
4637 const int *columnLength = matrix_->getVectorLengths();
4638 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
4639 const double *elementByColumn = matrix_->getElements();
4640 #if 0
4641 double tempArray[5000];
4642 bool checkIt=false;
4643 if (factorization_->pivots()&&!needFullUpdate&&sequenceIn_<0) {
4644 memcpy(tempArray,array,numberRows_*sizeof(double));
4645 checkIt=true;
4646 needFullUpdate=true;
4647 }
4648 #endif
4649 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
4650 double *lowerGap = paramData.lowerGap;
4651 double *upperGap = paramData.upperGap;
4652 double *lowerCoefficient = paramData.lowerCoefficient;
4653 double *upperCoefficient = paramData.upperCoefficient;
4654 int *lowerActive = paramData.lowerActive;
4655 int *upperActive = paramData.upperActive;
4656 #endif
4657 if (!factorization_->pivots() || needFullUpdate) {
4658 //zzzzzz=0;
4659 rowArray_[4]->clear();
4660 // get change
4661 if (!rowScale_) {
4662 int n;
4663 n = lowerList[-2];
4664 int i;
4665 for (i = 0; i < n; i++) {
4666 int iSequence = lowerList[i];
4667 assert(iSequence < numberColumns_);
4668 if (getColumnStatus(iSequence) == atLowerBound) {
4669 double value = lowerChange[iSequence];
4670 for (CoinBigIndex j = columnStart[iSequence];
4671 j < columnStart[iSequence] + columnLength[iSequence]; j++) {
4672 rowArray_[4]->quickAdd(row[j], elementByColumn[j] * value);
4673 }
4674 }
4675 }
4676 n = lowerList[-1];
4677 const double *change = lowerChange + numberColumns_;
4678 for (; i < n; i++) {
4679 int iSequence = lowerList[i] - numberColumns_;
4680 assert(iSequence >= 0);
4681 if (getRowStatus(iSequence) == atLowerBound) {
4682 double value = change[iSequence];
4683 rowArray_[4]->quickAdd(iSequence, -value);
4684 }
4685 }
4686 n = upperList[-2];
4687 for (i = 0; i < n; i++) {
4688 int iSequence = upperList[i];
4689 assert(iSequence < numberColumns_);
4690 if (getColumnStatus(iSequence) == atUpperBound) {
4691 double value = upperChange[iSequence];
4692 for (CoinBigIndex j = columnStart[iSequence];
4693 j < columnStart[iSequence] + columnLength[iSequence]; j++) {
4694 rowArray_[4]->quickAdd(row[j], elementByColumn[j] * value);
4695 }
4696 }
4697 }
4698 n = upperList[-1];
4699 change = upperChange + numberColumns_;
4700 for (; i < n; i++) {
4701 int iSequence = upperList[i] - numberColumns_;
4702 assert(iSequence >= 0);
4703 if (getRowStatus(iSequence) == atUpperBound) {
4704 double value = change[iSequence];
4705 rowArray_[4]->quickAdd(iSequence, -value);
4706 }
4707 }
4708 } else {
4709 int n;
4710 n = lowerList[-2];
4711 int i;
4712 for (i = 0; i < n; i++) {
4713 int iSequence = lowerList[i];
4714 assert(iSequence < numberColumns_);
4715 if (getColumnStatus(iSequence) == atLowerBound) {
4716 double value = lowerChange[iSequence];
4717 // apply scaling
4718 double scale = columnScale_[iSequence];
4719 for (CoinBigIndex j = columnStart[iSequence];
4720 j < columnStart[iSequence] + columnLength[iSequence]; j++) {
4721 int iRow = row[j];
4722 rowArray_[4]->quickAdd(iRow, elementByColumn[j] * scale * rowScale_[iRow] * value);
4723 }
4724 }
4725 }
4726 n = lowerList[-1];
4727 const double *change = lowerChange + numberColumns_;
4728 for (; i < n; i++) {
4729 int iSequence = lowerList[i] - numberColumns_;
4730 assert(iSequence >= 0);
4731 if (getRowStatus(iSequence) == atLowerBound) {
4732 double value = change[iSequence];
4733 rowArray_[4]->quickAdd(iSequence, -value);
4734 }
4735 }
4736 n = upperList[-2];
4737 for (i = 0; i < n; i++) {
4738 int iSequence = upperList[i];
4739 assert(iSequence < numberColumns_);
4740 if (getColumnStatus(iSequence) == atUpperBound) {
4741 double value = upperChange[iSequence];
4742 // apply scaling
4743 double scale = columnScale_[iSequence];
4744 for (CoinBigIndex j = columnStart[iSequence];
4745 j < columnStart[iSequence] + columnLength[iSequence]; j++) {
4746 int iRow = row[j];
4747 rowArray_[4]->quickAdd(iRow, elementByColumn[j] * scale * rowScale_[iRow] * value);
4748 }
4749 }
4750 }
4751 n = upperList[-1];
4752 change = upperChange + numberColumns_;
4753 for (; i < n; i++) {
4754 int iSequence = upperList[i] - numberColumns_;
4755 assert(iSequence >= 0);
4756 if (getRowStatus(iSequence) == atUpperBound) {
4757 double value = change[iSequence];
4758 rowArray_[4]->quickAdd(iSequence, -value);
4759 }
4760 }
4761 }
4762 // ftran it
4763 factorization_->updateColumn(rowArray_[0], rowArray_[4]);
4764 #if 0
4765 if (checkIt) {
4766 for (int i=0;i<numberRows_;i++) {
4767 assert (fabs(tempArray[i]-array[i])<1.0e-8);
4768 }
4769 }
4770 #endif
4771 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
4772 /* later for sparse - keep like CoinIndexedvector
4773 and just redo here */
4774 int lowerN = 0;
4775 int upperN = 0;
4776 memset(lowerCoefficient, 0, numberRows_ * sizeof(double));
4777 memset(upperCoefficient, 0, numberRows_ * sizeof(double));
4778 for (int iRow = 0; iRow < numberRows_; iRow++) {
4779 iSequence = pivotVariable_[iRow];
4780 double currentSolution = solution_[iSequence];
4781 double alpha = array[iRow];
4782 double thetaCoefficientLower = lowerChange[iSequence] + alpha;
4783 double thetaCoefficientUpper = upperChange[iSequence] + alpha;
4784 if (thetaCoefficientLower > 1.0e-8 && lower_[iSequence] > -1.0e30) {
4785 double currentLower = lower_[iSequence];
4786 ClpTraceDebug(currentSolution >= currentLower - 100.0 * primalTolerance_);
4787 double gap = currentSolution - currentLower;
4788 lowerGap[iRow] = gap;
4789 lowerCoefficient[iRow] = thetaCoefficientLower;
4790 lowerActive[lowerN++] = iRow;
4791 //} else {
4792 //lowerCoefficient[iRow]=0.0;
4793 }
4794 if (thetaCoefficientUpper < -1.0e-8 && upper_[iSequence] < 1.0e30) {
4795 double currentUpper = upper_[iSequence];
4796 ClpTraceDebug(currentSolution <= currentUpper + 100.0 * primalTolerance_);
4797 double gap2 = -(currentSolution - currentUpper); //positive
4798 upperGap[iRow] = gap2;
4799 upperCoefficient[iRow] = -thetaCoefficientUpper;
4800 upperActive[upperN++] = iRow;
4801 }
4802 }
4803 assert(lowerN >= 0 && lowerN <= numberRows_);
4804 lowerActive[-1] = lowerN;
4805 upperActive[-1] = upperN;
4806 #endif
4807 } else if (sequenceIn_ >= 0) {
4808 //assert (sequenceIn_>=0);
4809 assert(sequenceOut_ >= 0);
4810 assert(sequenceIn_ != sequenceOut_);
4811 double change = (directionIn_ > 0) ? -lowerChange[sequenceIn_] : -upperChange[sequenceIn_];
4812 int needed = 0;
4813 assert(!rowArray_[5]->getNumElements());
4814 if (change) {
4815 if (sequenceIn_ < numberColumns_) {
4816 if (!rowScale_) {
4817 for (CoinBigIndex i = columnStart[sequenceIn_];
4818 i < columnStart[sequenceIn_] + columnLength[sequenceIn_]; i++) {
4819 rowArray_[5]->quickAdd(row[i], elementByColumn[i] * change);
4820 }
4821 } else {
4822 // apply scaling
4823 double scale = columnScale_[sequenceIn_];
4824 for (CoinBigIndex i = columnStart[sequenceIn_];
4825 i < columnStart[sequenceIn_] + columnLength[sequenceIn_]; i++) {
4826 int iRow = row[i];
4827 rowArray_[5]->quickAdd(iRow, elementByColumn[i] * scale * rowScale_[iRow] * change);
4828 }
4829 }
4830 } else {
4831 rowArray_[5]->insert(sequenceIn_ - numberColumns_, -change);
4832 }
4833 needed++;
4834 }
4835 if (getStatus(sequenceOut_) == atLowerBound)
4836 change = lowerChange[sequenceOut_];
4837 else
4838 change = upperChange[sequenceOut_];
4839 if (change) {
4840 if (sequenceOut_ < numberColumns_) {
4841 if (!rowScale_) {
4842 for (CoinBigIndex i = columnStart[sequenceOut_];
4843 i < columnStart[sequenceOut_] + columnLength[sequenceOut_]; i++) {
4844 rowArray_[5]->quickAdd(row[i], elementByColumn[i] * change);
4845 }
4846 } else {
4847 // apply scaling
4848 double scale = columnScale_[sequenceOut_];
4849 for (CoinBigIndex i = columnStart[sequenceOut_];
4850 i < columnStart[sequenceOut_] + columnLength[sequenceOut_]; i++) {
4851 int iRow = row[i];
4852 rowArray_[5]->quickAdd(iRow, elementByColumn[i] * scale * rowScale_[iRow] * change);
4853 }
4854 }
4855 } else {
4856 rowArray_[5]->quickAdd(sequenceOut_ - numberColumns_, -change);
4857 }
4858 needed++;
4859 }
4860 //printf("seqin %d seqout %d needed %d\n",
4861 // sequenceIn_,sequenceOut_,needed);
4862 if (needed) {
4863 // ftran it
4864 factorization_->updateColumn(rowArray_[0], rowArray_[5]);
4865 // add
4866 double *array5 = rowArray_[5]->denseVector();
4867 int *index5 = rowArray_[5]->getIndices();
4868 int number5 = rowArray_[5]->getNumElements();
4869 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
4870 int lowerN = lowerActive[-1];
4871 int upperN = upperActive[-1];
4872 int nIn4 = rowArray_[4]->getNumElements();
4873 int *index4 = rowArray_[4]->getIndices();
4874 #endif
4875 for (int i = 0; i < number5; i++) {
4876 int iPivot = index5[i];
4877 #ifndef CLP_PARAMETRIC_DENSE_ARRAYS
4878 rowArray_[4]->quickAdd(iPivot, array5[iPivot]);
4879 #else
4880 /* later for sparse - modify here */
4881 int iSequence = pivotVariable_[iPivot];
4882 double currentSolution = solution_[iSequence];
4883 double currentAlpha = array[iPivot];
4884 double alpha5 = array5[iPivot];
4885 double alpha = currentAlpha + alpha5;
4886 if (currentAlpha) {
4887 if (alpha) {
4888 array[iPivot] = alpha;
4889 } else {
4890 array[iPivot] = COIN_DBL_MIN;
4891 }
4892 } else {
4893 index4[nIn4++] = iPivot;
4894 array[iPivot] = alpha;
4895 }
4896 double thetaCoefficientLower = lowerChange[iSequence] + alpha;
4897 double thetaCoefficientUpper = upperChange[iSequence] + alpha;
4898 double oldLower = lowerCoefficient[iPivot];
4899 double oldUpper = upperCoefficient[iPivot];
4900 if (thetaCoefficientLower > 1.0e-8 && lower_[iSequence] > -1.0e30) {
4901 double currentLower = lower_[iSequence];
4902 ClpTraceDebug(currentSolution >= currentLower - 100.0 * primalTolerance_);
4903 double gap = currentSolution - currentLower;
4904 lowerGap[iPivot] = gap;
4905 lowerCoefficient[iPivot] = thetaCoefficientLower;
4906 if (!oldLower)
4907 lowerActive[lowerN++] = iPivot;
4908 } else {
4909 if (oldLower)
4910 lowerCoefficient[iPivot] = COIN_DBL_MIN;
4911 }
4912 if (thetaCoefficientUpper < -1.0e-8 && upper_[iSequence] < 1.0e30) {
4913 double currentUpper = upper_[iSequence];
4914 ClpTraceDebug(currentSolution <= currentUpper + 100.0 * primalTolerance_);
4915 double gap2 = -(currentSolution - currentUpper); //positive
4916 upperGap[iPivot] = gap2;
4917 upperCoefficient[iPivot] = -thetaCoefficientUpper;
4918 if (!oldUpper)
4919 upperActive[upperN++] = iPivot;
4920 } else {
4921 if (oldUpper)
4922 upperCoefficient[iPivot] = COIN_DBL_MIN;
4923 }
4924 #endif
4925 array5[iPivot] = 0.0;
4926 }
4927 rowArray_[5]->setNumElements(0);
4928 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
4929 rowArray_[4]->setNumElements(nIn4);
4930 assert(lowerN >= 0 && lowerN <= numberRows_);
4931 lowerActive[-1] = lowerN;
4932 upperActive[-1] = upperN;
4933 #endif
4934 }
4935 }
4936 const int *index = rowArray_[4]->getIndices();
4937 int number = rowArray_[4]->getNumElements();
4938 #define TESTXX 0
4939 #ifndef CLP_PARAMETRIC_DENSE_ARRAYS //TESTXX
4940 int *markDone = reinterpret_cast< int * >(paramData.markDone);
4941 int nToZero = (numberRows_ + numberColumns_ + COIN_ANY_BITS_PER_INT - 1) >> COIN_ANY_SHIFT_PER_INT;
4942 memset(markDone, 0, nToZero * sizeof(int));
4943 const int *backwardBasic = paramData.backwardBasic;
4944 #endif
4945 // first ones with alpha
4946 double theta1 = maxTheta;
4947 int pivotRow1 = -1;
4948 #ifndef CLP_PARAMETRIC_DENSE_ARRAYS //TESTXX
4949 int pivotRow2 = -1;
4950 double theta2 = maxTheta;
4951 #endif
4952 #ifndef CLP_PARAMETRIC_DENSE_ARRAYS //TESTXX
4953 for (int i = 0; i < number; i++) {
4954 int iPivot = index[i];
4955 iSequence = pivotVariable_[iPivot];
4956 //assert(!markDone[iSequence]);
4957 int word = iSequence >> COIN_ANY_SHIFT_PER_INT;
4958 int bit = iSequence & COIN_ANY_MASK_PER_INT;
4959 markDone[word] |= (1 << bit);
4960 // solution value will be sol - theta*alpha
4961 // bounds will be bounds + change *theta
4962 double currentSolution = solution_[iSequence];
4963 double alpha = array[iPivot];
4964 double thetaCoefficientLower = lowerChange[iSequence] + alpha;
4965 double thetaCoefficientUpper = upperChange[iSequence] + alpha;
4966 if (thetaCoefficientLower > 1.0e-8) {
4967 double currentLower = lower_[iSequence];
4968 ClpTraceDebug(currentSolution >= currentLower - 100.0 * primalTolerance_);
4969 assert(currentSolution >= currentLower - 100.0 * primalTolerance_);
4970 double gap = currentSolution - currentLower;
4971 if (thetaCoefficientLower * theta1 > gap) {
4972 theta1 = gap / thetaCoefficientLower;
4973 //toLower=true;
4974 pivotRow1 = iPivot;
4975 }
4976 }
4977 if (thetaCoefficientUpper < -1.0e-8) {
4978 double currentUpper = upper_[iSequence];
4979 ClpTraceDebug(currentSolution <= currentUpper + 100.0 * primalTolerance_);
4980 assert(currentSolution <= currentUpper + 100.0 * primalTolerance_);
4981 double gap2 = currentSolution - currentUpper; //negative
4982 if (thetaCoefficientUpper * theta2 < gap2) {
4983 theta2 = gap2 / thetaCoefficientUpper;
4984 //toLower=false;
4985 pivotRow2 = iPivot;
4986 }
4987 }
4988 }
4989 // now others
4990 int nLook = lowerList[-1];
4991 for (int i = 0; i < nLook; i++) {
4992 int iSequence = lowerList[i];
4993 int word = iSequence >> COIN_ANY_SHIFT_PER_INT;
4994 int bit = iSequence & COIN_ANY_MASK_PER_INT;
4995 if (getColumnStatus(iSequence) == basic && (markDone[word] & (1 << bit)) == 0) {
4996 double currentSolution = solution_[iSequence];
4997 double currentLower = lower_[iSequence];
4998 ClpTraceDebug(currentSolution >= currentLower - 100.0 * primalTolerance_);
4999 double thetaCoefficient = lowerChange[iSequence];
5000 if (thetaCoefficient > 0.0) {
5001 double gap = currentSolution - currentLower;
5002 if (thetaCoefficient * theta1 > gap) {
5003 theta1 = gap / thetaCoefficient;
5004 //toLower=true;
5005 pivotRow1 = backwardBasic[iSequence];
5006 }
5007 }
5008 }
5009 }
5010 nLook = upperList[-1];
5011 for (int i = 0; i < nLook; i++) {
5012 int iSequence = upperList[i];
5013 int word = iSequence >> COIN_ANY_SHIFT_PER_INT;
5014 int bit = iSequence & COIN_ANY_MASK_PER_INT;
5015 if (getColumnStatus(iSequence) == basic && (markDone[word] & (1 << bit)) == 0) {
5016 double currentSolution = solution_[iSequence];
5017 double currentUpper = upper_[iSequence];
5018 ClpTraceDebug(currentSolution <= currentUpper + 100.0 * primalTolerance_);
5019 double thetaCoefficient = upperChange[iSequence];
5020 if (thetaCoefficient < 0) {
5021 double gap = currentSolution - currentUpper; //negative
5022 if (thetaCoefficient * theta2 < gap) {
5023 theta2 = gap / thetaCoefficient;
5024 //toLower=false;
5025 pivotRow2 = backwardBasic[iSequence];
5026 }
5027 }
5028 }
5029 }
5030 if (theta2 < theta1) {
5031 theta_ = theta2;
5032 toLower = false;
5033 pivotRow_ = pivotRow2;
5034 } else {
5035 theta_ = theta1;
5036 toLower = true;
5037 pivotRow_ = pivotRow1;
5038 }
5039 #if 0 //TESTXX
5040 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
5041 {
5042 double * checkArray = new double[numberRows_];
5043 memcpy(checkArray,lowerCoefficient,numberRows_*sizeof(double));
5044 int lowerN=lowerActive[-1];
5045 for (int i=0;i<lowerN;i++) {
5046 int iRow=lowerActive[i];
5047 int iSequence = pivotVariable_[iRow];
5048 double alpha = array[iRow];
5049 double thetaCoefficient = lowerChange[iSequence] + alpha;
5050 if (thetaCoefficient > 1.0e-8&&lower_[iSequence]>-1.0e30) {
5051 assert(fabs(checkArray[iRow]-thetaCoefficient)<1.0e-5);
5052 if(fabs(checkArray[iRow]-thetaCoefficient)>1.0e-5) {
5053 abort();
5054 }
5055 } else {
5056 assert (fabs(checkArray[iRow])<1.0e-12);
5057 if (fabs(checkArray[iRow])>1.0e-12) {
5058 abort();
5059 }
5060 }
5061 checkArray[iRow]=0.0;
5062 }
5063 for (int i=0;i<numberRows_;i++) {
5064 assert (!checkArray[i]);
5065 if (checkArray[i])
5066 abort();
5067 }
5068 memcpy(checkArray,upperCoefficient,numberRows_*sizeof(double));
5069 int upperN=upperActive[-1];
5070 for (int i=0;i<upperN;i++) {
5071 int iRow=upperActive[i];
5072 int iSequence = pivotVariable_[iRow];
5073 double alpha = array[iRow];
5074 double thetaCoefficient = -(upperChange[iSequence] + alpha);
5075 if (thetaCoefficient > 1.0e-8&&upper_[iSequence]<1.0e30) {
5076 assert(fabs(checkArray[iRow]-thetaCoefficient)<1.0e-5);
5077 if(fabs(checkArray[iRow]-thetaCoefficient)>1.0e-5) {
5078 abort();
5079 }
5080 } else {
5081 assert (fabs(checkArray[iRow])<1.0e-12);
5082 if (fabs(checkArray[iRow])>1.0e-12) {
5083 abort();
5084 }
5085 }
5086 checkArray[iRow]=0.0;
5087 }
5088 for (int i=0;i<numberRows_;i++) {
5089 assert (!checkArray[i]);
5090 if (checkArray[i])
5091 abort();
5092 }
5093 delete [] checkArray;
5094 }
5095 double theta3=maxTheta;
5096 int pivotRow3=-1;
5097 int lowerN=lowerActive[-1];
5098 for (int i=0;i<lowerN;i++) {
5099 int iRow=lowerActive[i];
5100 double lowerC = lowerCoefficient[iRow];
5101 double gap=lowerGap[iRow];
5102 if (toLower&&iRow==pivotRow_) {
5103 assert (lowerC*theta3>gap-1.0e-8);
5104 if (lowerC*theta3<gap-1.0e-8)
5105 abort();
5106 }
5107 if (lowerC*theta3>gap&&lowerC!=COIN_DBL_MIN) {
5108 theta3 = gap/lowerC;
5109 pivotRow3=iRow;
5110 }
5111 }
5112 int pivotRow4=pivotRow3;
5113 double theta4=theta3;
5114 int upperN=upperActive[-1];
5115 for (int i=0;i<upperN;i++) {
5116 int iRow=upperActive[i];
5117 double upperC = upperCoefficient[iRow];
5118 double gap=upperGap[iRow];
5119 if (!toLower&&iRow==pivotRow_) {
5120 assert (upperC*theta3>gap-1.0e-8);
5121 if (upperC*theta3<gap-1.0e-8)
5122 abort();
5123 }
5124 if (upperC*theta4>gap&&upperC!=COIN_DBL_MIN) {
5125 theta4 = gap/upperC;
5126 pivotRow4=iRow;
5127 }
5128 }
5129 bool toLower3;
5130 if (theta4<theta3) {
5131 theta3=theta4;
5132 toLower3=false;
5133 pivotRow3=pivotRow4;
5134 } else {
5135 toLower3=true;
5136 }
5137 if (fabs(theta3-theta_)>1.0e-8)
5138 abort();
5139 if (toLower!=toLower3||pivotRow_!=pivotRow3) {
5140 printf("bad piv - good %d %g %s, bad %d %g %s\n",pivotRow_,theta_,toLower ? "toLower" : "toUpper",
5141 pivotRow3,theta3,toLower3 ? "toLower" : "toUpper");
5142 //zzzzzz++;
5143 if (true/*zzzzzz>zzzzzzOther*/) {
5144 printf("Swapping\n");
5145 pivotRow_=pivotRow3;
5146 theta_=theta3;
5147 toLower=toLower3;
5148 }
5149 }
5150 #endif
5151 #endif
5152 #else
5153 #if 0 //CLP_PARAMETRIC_DENSE_ARRAYS==2
5154 {
5155 double * checkArray = new double[numberRows_];
5156 memcpy(checkArray,lowerCoefficient,numberRows_*sizeof(double));
5157 int lowerN=lowerActive[-1];
5158 for (int i=0;i<lowerN;i++) {
5159 int iRow=lowerActive[i];
5160 checkArray[iRow]=0.0;
5161 }
5162 for (int i=0;i<numberRows_;i++) {
5163 assert (!checkArray[i]);
5164 if (checkArray[i])
5165 abort();
5166 }
5167 memcpy(checkArray,upperCoefficient,numberRows_*sizeof(double));
5168 int upperN=upperActive[-1];
5169 for (int i=0;i<upperN;i++) {
5170 int iRow=upperActive[i];
5171 checkArray[iRow]=0.0;
5172 }
5173 for (int i=0;i<numberRows_;i++) {
5174 assert (!checkArray[i]);
5175 if (checkArray[i])
5176 abort();
5177 }
5178 delete [] checkArray;
5179 }
5180 #endif
5181 int lowerN = lowerActive[-1];
5182 for (int i = 0; i < lowerN; i++) {
5183 int iRow = lowerActive[i];
5184 double lowerC = lowerCoefficient[iRow];
5185 double gap = lowerGap[iRow];
5186 if (lowerC * theta1 > gap && lowerC != COIN_DBL_MIN) {
5187 theta1 = gap / lowerC;
5188 pivotRow1 = iRow;
5189 }
5190 }
5191 pivotRow_ = pivotRow1;
5192 theta_ = theta1;
5193 int upperN = upperActive[-1];
5194 for (int i = 0; i < upperN; i++) {
5195 int iRow = upperActive[i];
5196 double upperC = upperCoefficient[iRow];
5197 double gap = upperGap[iRow];
5198 if (upperC * theta1 > gap && upperC != COIN_DBL_MIN) {
5199 theta1 = gap / upperC;
5200 pivotRow1 = iRow;
5201 }
5202 }
5203 if (theta1 < theta_) {
5204 theta_ = theta1;
5205 toLower = false;
5206 pivotRow_ = pivotRow1;
5207 } else {
5208 toLower = true;
5209 }
5210 #endif
5211 theta_ = CoinMax(theta_, 0.0);
5212 if (theta_ > 1.0e-15) {
5213 // update solution
5214 for (int iRow = 0; iRow < number; iRow++) {
5215 int iPivot = index[iRow];
5216 iSequence = pivotVariable_[iPivot];
5217 // solution value will be sol - theta*alpha
5218 double alpha = array[iPivot];
5219 double currentSolution = solution_[iSequence] - theta_ * alpha;
5220 solution_[iSequence] = currentSolution;
5221 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
5222 if (lower_[iSequence] > -1.0e30)
5223 lowerGap[iPivot] = currentSolution - lower_[iSequence];
5224 if (upper_[iSequence] < 1.0e30)
5225 upperGap[iPivot] = -(currentSolution - upper_[iSequence]);
5226 #endif
5227 }
5228 }
5229 #ifdef CLP_PARAMETRIC_DENSE_ARRAYS
5230 if (pivotRow_ >= 0 && false) {
5231 double oldValue = upperCoefficient[pivotRow_];
5232 double value = array[pivotRow_];
5233 if (value) {
5234 if (!oldValue) {
5235 int upperN = upperActive[-1];
5236 assert(upperN >= 0 && upperN < numberRows_);
5237 upperActive[upperN] = pivotRow_;
5238 upperActive[-1] = upperN + 1;
5239 }
5240 } else {
5241 if (oldValue)
5242 upperCoefficient[pivotRow_] = COIN_DBL_MIN;
5243 }
5244 }
5245 #endif
5246 #if 0
5247 for (int i=0;i<numberTotal;i++)
5248 assert(!markDone[i]);
5249 #endif
5250 if (pivotRow_ >= 0) {
5251 sequenceOut_ = pivotVariable_[pivotRow_];
5252 valueOut_ = solution_[sequenceOut_];
5253 lowerOut_ = lower_[sequenceOut_] + theta_ * lowerChange[sequenceOut_];
5254 upperOut_ = upper_[sequenceOut_] + theta_ * upperChange[sequenceOut_];
5255 if (!toLower) {
5256 directionOut_ = -1;
5257 dualOut_ = valueOut_ - upperOut_;
5258 } else {
5259 directionOut_ = 1;
5260 dualOut_ = lowerOut_ - valueOut_;
5261 }
5262 return 0;
5263 } else {
5264 //theta_=0.0;
5265 return -1;
5266 }
5267 }
5268 // Restores bound to original bound
originalBound(int iSequence,double theta,const double * lowerChange,const double * upperChange)5269 void ClpSimplexOther::originalBound(int iSequence, double theta,
5270 const double *lowerChange,
5271 const double *upperChange)
5272 {
5273 if (getFakeBound(iSequence) != noFake) {
5274 numberFake_--;
5275 setFakeBound(iSequence, noFake);
5276 if (iSequence >= numberColumns_) {
5277 // rows
5278 int iRow = iSequence - numberColumns_;
5279 rowLowerWork_[iRow] = rowLower_[iRow] + theta * lowerChange[iSequence];
5280 rowUpperWork_[iRow] = rowUpper_[iRow] + theta * upperChange[iSequence];
5281 if (rowScale_) {
5282 if (rowLowerWork_[iRow] > -1.0e50)
5283 rowLowerWork_[iRow] *= rowScale_[iRow] * rhsScale_;
5284 if (rowUpperWork_[iRow] < 1.0e50)
5285 rowUpperWork_[iRow] *= rowScale_[iRow] * rhsScale_;
5286 } else if (rhsScale_ != 1.0) {
5287 if (rowLowerWork_[iRow] > -1.0e50)
5288 rowLowerWork_[iRow] *= rhsScale_;
5289 if (rowUpperWork_[iRow] < 1.0e50)
5290 rowUpperWork_[iRow] *= rhsScale_;
5291 }
5292 } else {
5293 // columns
5294 columnLowerWork_[iSequence] = columnLower_[iSequence] + theta * lowerChange[iSequence];
5295 columnUpperWork_[iSequence] = columnUpper_[iSequence] + theta * upperChange[iSequence];
5296 if (rowScale_) {
5297 double multiplier = 1.0 * inverseColumnScale_[iSequence];
5298 if (columnLowerWork_[iSequence] > -1.0e50)
5299 columnLowerWork_[iSequence] *= multiplier * rhsScale_;
5300 if (columnUpperWork_[iSequence] < 1.0e50)
5301 columnUpperWork_[iSequence] *= multiplier * rhsScale_;
5302 } else if (rhsScale_ != 1.0) {
5303 if (columnLowerWork_[iSequence] > -1.0e50)
5304 columnLowerWork_[iSequence] *= rhsScale_;
5305 if (columnUpperWork_[iSequence] < 1.0e50)
5306 columnUpperWork_[iSequence] *= rhsScale_;
5307 }
5308 }
5309 }
5310 }
5311 /* Expands out all possible combinations for a knapsack
5312 If buildObj NULL then just computes space needed - returns number elements
5313 On entry numberOutput is maximum allowed, on exit it is number needed or
5314 -1 (as will be number elements) if maximum exceeded. numberOutput will have at
5315 least space to return values which reconstruct input.
5316 Rows returned will be original rows but no entries will be returned for
5317 any rows all of whose entries are in knapsack. So up to user to allow for this.
5318 If reConstruct >=0 then returns number of entrie which make up item "reConstruct"
5319 in expanded knapsack. Values in buildRow and buildElement;
5320 */
expandKnapsack(int knapsackRow,int & numberOutput,double * buildObj,CoinBigIndex * buildStart,int * buildRow,double * buildElement,int reConstruct) const5321 int ClpSimplexOther::expandKnapsack(int knapsackRow, int &numberOutput,
5322 double *buildObj, CoinBigIndex *buildStart,
5323 int *buildRow, double *buildElement, int reConstruct) const
5324 {
5325 int iRow;
5326 int iColumn;
5327 // Get column copy
5328 CoinPackedMatrix *columnCopy = matrix();
5329 // Get a row copy in standard format
5330 CoinPackedMatrix matrixByRow;
5331 matrixByRow.reverseOrderedCopyOf(*columnCopy);
5332 const double *elementByRow = matrixByRow.getElements();
5333 const int *column = matrixByRow.getIndices();
5334 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
5335 const int *rowLength = matrixByRow.getVectorLengths();
5336 CoinBigIndex j;
5337 int *whichColumn = new int[numberColumns_];
5338 int *whichRow = new int[numberRows_];
5339 int numJ = 0;
5340 // Get what other columns can compensate for
5341 double *lo = new double[numberRows_];
5342 double *high = new double[numberRows_];
5343 {
5344 // Use to get tight column bounds
5345 ClpSimplex tempModel(*this);
5346 tempModel.tightenPrimalBounds(0.0, 0, true);
5347 // Now another model without knapsacks
5348 int nCol = 0;
5349 for (iRow = 0; iRow < numberRows_; iRow++) {
5350 whichRow[iRow] = iRow;
5351 }
5352 for (iColumn = 0; iColumn < numberColumns_; iColumn++)
5353 whichColumn[iColumn] = -1;
5354 for (j = rowStart[knapsackRow]; j < rowStart[knapsackRow] + rowLength[knapsackRow]; j++) {
5355 int iColumn = column[j];
5356 if (columnUpper_[iColumn] > columnLower_[iColumn]) {
5357 whichColumn[iColumn] = 0;
5358 } else {
5359 assert(!columnLower_[iColumn]); // fix later
5360 }
5361 }
5362 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
5363 if (whichColumn[iColumn] < 0)
5364 whichColumn[nCol++] = iColumn;
5365 }
5366 ClpSimplex tempModel2(&tempModel, numberRows_, whichRow, nCol, whichColumn, false, false, false);
5367 // Row copy
5368 CoinPackedMatrix matrixByRow;
5369 matrixByRow.reverseOrderedCopyOf(*tempModel2.matrix());
5370 const double *elementByRow = matrixByRow.getElements();
5371 const int *column = matrixByRow.getIndices();
5372 const CoinBigIndex *rowStart = matrixByRow.getVectorStarts();
5373 const int *rowLength = matrixByRow.getVectorLengths();
5374 const double *columnLower = tempModel2.getColLower();
5375 const double *columnUpper = tempModel2.getColUpper();
5376 for (iRow = 0; iRow < numberRows_; iRow++) {
5377 lo[iRow] = -COIN_DBL_MAX;
5378 high[iRow] = COIN_DBL_MAX;
5379 if (rowLower_[iRow] > -1.0e20 || rowUpper_[iRow] < 1.0e20) {
5380
5381 // possible row
5382 int infiniteUpper = 0;
5383 int infiniteLower = 0;
5384 double maximumUp = 0.0;
5385 double maximumDown = 0.0;
5386 CoinBigIndex rStart = rowStart[iRow];
5387 CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow];
5388 CoinBigIndex j;
5389 // Compute possible lower and upper ranges
5390
5391 for (j = rStart; j < rEnd; ++j) {
5392 double value = elementByRow[j];
5393 iColumn = column[j];
5394 if (value > 0.0) {
5395 if (columnUpper[iColumn] >= 1.0e20) {
5396 ++infiniteUpper;
5397 } else {
5398 maximumUp += columnUpper[iColumn] * value;
5399 }
5400 if (columnLower[iColumn] <= -1.0e20) {
5401 ++infiniteLower;
5402 } else {
5403 maximumDown += columnLower[iColumn] * value;
5404 }
5405 } else if (value < 0.0) {
5406 if (columnUpper[iColumn] >= 1.0e20) {
5407 ++infiniteLower;
5408 } else {
5409 maximumDown += columnUpper[iColumn] * value;
5410 }
5411 if (columnLower[iColumn] <= -1.0e20) {
5412 ++infiniteUpper;
5413 } else {
5414 maximumUp += columnLower[iColumn] * value;
5415 }
5416 }
5417 }
5418 // Build in a margin of error
5419 maximumUp += 1.0e-8 * fabs(maximumUp) + 1.0e-7;
5420 maximumDown -= 1.0e-8 * fabs(maximumDown) + 1.0e-7;
5421 // we want to save effective rhs
5422 double up = (infiniteUpper) ? COIN_DBL_MAX : maximumUp;
5423 double down = (infiniteLower) ? -COIN_DBL_MAX : maximumDown;
5424 if (up == COIN_DBL_MAX || rowLower_[iRow] == -COIN_DBL_MAX) {
5425 // However low we go it doesn't matter
5426 lo[iRow] = -COIN_DBL_MAX;
5427 } else {
5428 // If we go below this then can not be feasible
5429 lo[iRow] = rowLower_[iRow] - up;
5430 }
5431 if (down == -COIN_DBL_MAX || rowUpper_[iRow] == COIN_DBL_MAX) {
5432 // However high we go it doesn't matter
5433 high[iRow] = COIN_DBL_MAX;
5434 } else {
5435 // If we go above this then can not be feasible
5436 high[iRow] = rowUpper_[iRow] - down;
5437 }
5438 }
5439 }
5440 }
5441 numJ = 0;
5442 for (iColumn = 0; iColumn < numberColumns_; iColumn++)
5443 whichColumn[iColumn] = -1;
5444 int *markRow = new int[numberRows_];
5445 for (iRow = 0; iRow < numberRows_; iRow++)
5446 markRow[iRow] = 1;
5447 for (j = rowStart[knapsackRow]; j < rowStart[knapsackRow] + rowLength[knapsackRow]; j++) {
5448 int iColumn = column[j];
5449 if (columnUpper_[iColumn] > columnLower_[iColumn]) {
5450 whichColumn[iColumn] = numJ;
5451 numJ++;
5452 }
5453 }
5454 /* mark rows
5455 -n in knapsack and n other variables
5456 1 no entries
5457 n+1000 not involved in knapsack but n entries
5458 0 only in knapsack
5459 */
5460 for (iRow = 0; iRow < numberRows_; iRow++) {
5461 int type = 1;
5462 for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
5463 int iColumn = column[j];
5464 if (whichColumn[iColumn] >= 0) {
5465 if (type == 1) {
5466 type = 0;
5467 } else if (type > 0) {
5468 assert(type > 1000);
5469 type = -(type - 1000);
5470 }
5471 } else if (type == 1) {
5472 type = 1001;
5473 } else if (type < 0) {
5474 type--;
5475 } else if (type == 0) {
5476 type = -1;
5477 } else {
5478 assert(type > 1000);
5479 type++;
5480 }
5481 }
5482 markRow[iRow] = type;
5483 if (type < 0 && type > -30 && false)
5484 printf("markrow on row %d is %d\n", iRow, markRow[iRow]);
5485 }
5486 int *bound = new int[numberColumns_ + 1];
5487 int *stack = new int[numberColumns_ + 1];
5488 int *flip = new int[numberColumns_ + 1];
5489 double *offset = new double[numberColumns_ + 1];
5490 double *size = new double[numberColumns_ + 1];
5491 double *rhsOffset = new double[numberRows_];
5492 int *build = new int[numberColumns_];
5493 int maxNumber = numberOutput;
5494 numJ = 0;
5495 double minSize = rowLower_[knapsackRow];
5496 double maxSize = rowUpper_[knapsackRow];
5497 double knapsackOffset = 0.0;
5498 for (j = rowStart[knapsackRow]; j < rowStart[knapsackRow] + rowLength[knapsackRow]; j++) {
5499 int iColumn = column[j];
5500 double lowerColumn = columnLower_[iColumn];
5501 double upperColumn = columnUpper_[iColumn];
5502 if (lowerColumn == upperColumn)
5503 continue;
5504 double gap = upperColumn - lowerColumn;
5505 if (gap > 1.0e8)
5506 gap = 1.0e8;
5507 assert(fabs(floor(gap + 0.5) - gap) < 1.0e-5);
5508 whichColumn[numJ] = iColumn;
5509 bound[numJ] = static_cast< int >(gap);
5510 if (elementByRow[j] > 0.0) {
5511 flip[numJ] = 1;
5512 offset[numJ] = lowerColumn;
5513 size[numJ++] = elementByRow[j];
5514 } else {
5515 flip[numJ] = -1;
5516 offset[numJ] = upperColumn;
5517 size[numJ++] = -elementByRow[j];
5518 lowerColumn = upperColumn;
5519 }
5520 knapsackOffset += elementByRow[j] * lowerColumn;
5521 }
5522 int jRow;
5523 for (iRow = 0; iRow < numberRows_; iRow++)
5524 whichRow[iRow] = iRow;
5525 ClpSimplex smallModel(this, numberRows_, whichRow, numJ, whichColumn, true, true, true);
5526 // modify rhs to allow for nonzero lower bounds
5527 //double * rowLower = smallModel.rowLower();
5528 //double * rowUpper = smallModel.rowUpper();
5529 //const double * columnLower = smallModel.columnLower();
5530 //const double * columnUpper = smallModel.columnUpper();
5531 const CoinPackedMatrix *matrix = smallModel.matrix();
5532 const double *element = matrix->getElements();
5533 const int *row = matrix->getIndices();
5534 const CoinBigIndex *columnStart = matrix->getVectorStarts();
5535 const int *columnLength = matrix->getVectorLengths();
5536 const double *objective = smallModel.objective();
5537 //double objectiveOffset=0.0;
5538 // would use for fixed?
5539 CoinZeroN(rhsOffset, numberRows_);
5540 double *rowActivity = smallModel.primalRowSolution();
5541 CoinZeroN(rowActivity, numberRows_);
5542 maxSize -= knapsackOffset;
5543 minSize -= knapsackOffset;
5544 // now generate
5545 int i;
5546 int iStack = numJ;
5547 for (i = 0; i < numJ; i++) {
5548 stack[i] = 0;
5549 }
5550 double tooMuch = 10.0 * maxSize + 10000;
5551 stack[numJ] = 1;
5552 size[numJ] = tooMuch;
5553 bound[numJ] = 0;
5554 double sum = tooMuch;
5555 // allow for all zero being OK
5556 stack[numJ - 1] = -1;
5557 sum -= size[numJ - 1];
5558 numberOutput = 0;
5559 int nelCreate = 0;
5560 /* typeRun is - 0 for initial sizes
5561 1 for build
5562 2 for reconstruct
5563 */
5564 int typeRun = buildObj ? 1 : 0;
5565 if (reConstruct >= 0) {
5566 assert(buildRow && buildElement);
5567 typeRun = 2;
5568 }
5569 if (typeRun == 1)
5570 buildStart[0] = 0;
5571 while (iStack >= 0) {
5572 if (sum >= minSize && sum <= maxSize) {
5573 double checkSize = 0.0;
5574 bool good = true;
5575 int nRow = 0;
5576 double obj = 0.0;
5577 CoinZeroN(rowActivity, numberRows_);
5578 for (iColumn = 0; iColumn < numJ; iColumn++) {
5579 int iValue = stack[iColumn];
5580 if (iValue > bound[iColumn]) {
5581 good = false;
5582 break;
5583 } else {
5584 double realValue = offset[iColumn] + flip[iColumn] * iValue;
5585 if (realValue) {
5586 obj += objective[iColumn] * realValue;
5587 for (CoinBigIndex j = columnStart[iColumn];
5588 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
5589 double value = element[j] * realValue;
5590 int kRow = row[j];
5591 if (rowActivity[kRow]) {
5592 rowActivity[kRow] += value;
5593 if (!rowActivity[kRow])
5594 rowActivity[kRow] = 1.0e-100;
5595 } else {
5596 build[nRow++] = kRow;
5597 rowActivity[kRow] = value;
5598 }
5599 }
5600 }
5601 }
5602 }
5603 if (good) {
5604 for (jRow = 0; jRow < nRow; jRow++) {
5605 int kRow = build[jRow];
5606 double value = rowActivity[kRow];
5607 if (value > high[kRow] || value < lo[kRow]) {
5608 good = false;
5609 break;
5610 }
5611 }
5612 }
5613 if (good) {
5614 if (typeRun == 1) {
5615 buildObj[numberOutput] = obj;
5616 for (jRow = 0; jRow < nRow; jRow++) {
5617 int kRow = build[jRow];
5618 double value = rowActivity[kRow];
5619 if (markRow[kRow] < 0 && fabs(value) > 1.0e-13) {
5620 buildElement[nelCreate] = value;
5621 buildRow[nelCreate++] = kRow;
5622 }
5623 }
5624 buildStart[numberOutput + 1] = nelCreate;
5625 } else if (!typeRun) {
5626 for (jRow = 0; jRow < nRow; jRow++) {
5627 int kRow = build[jRow];
5628 double value = rowActivity[kRow];
5629 if (markRow[kRow] < 0 && fabs(value) > 1.0e-13) {
5630 nelCreate++;
5631 }
5632 }
5633 }
5634 if (typeRun == 2 && reConstruct == numberOutput) {
5635 // build and exit
5636 nelCreate = 0;
5637 for (iColumn = 0; iColumn < numJ; iColumn++) {
5638 int iValue = stack[iColumn];
5639 double realValue = offset[iColumn] + flip[iColumn] * iValue;
5640 if (realValue) {
5641 buildRow[nelCreate] = whichColumn[iColumn];
5642 buildElement[nelCreate++] = realValue;
5643 }
5644 }
5645 numberOutput = 1;
5646 for (i = 0; i < numJ; i++) {
5647 bound[i] = 0;
5648 }
5649 break;
5650 }
5651 numberOutput++;
5652 if (numberOutput > maxNumber) {
5653 nelCreate = -numberOutput;
5654 numberOutput = -1;
5655 for (i = 0; i < numJ; i++) {
5656 bound[i] = 0;
5657 }
5658 break;
5659 } else if (typeRun == 1 && numberOutput == maxNumber) {
5660 // On second run
5661 for (i = 0; i < numJ; i++) {
5662 bound[i] = 0;
5663 }
5664 break;
5665 }
5666 for (int j = 0; j < numJ; j++) {
5667 checkSize += stack[j] * size[j];
5668 }
5669 assert(fabs(sum - checkSize) < 1.0e-3);
5670 }
5671 for (jRow = 0; jRow < nRow; jRow++) {
5672 int kRow = build[jRow];
5673 rowActivity[kRow] = 0.0;
5674 }
5675 }
5676 if (sum > maxSize || stack[iStack] > bound[iStack]) {
5677 sum -= size[iStack] * stack[iStack];
5678 stack[iStack--] = 0;
5679 if (iStack >= 0) {
5680 stack[iStack]++;
5681 sum += size[iStack];
5682 }
5683 } else {
5684 // must be less
5685 // add to last possible
5686 iStack = numJ - 1;
5687 sum += size[iStack];
5688 stack[iStack]++;
5689 }
5690 }
5691 //printf("%d will be created\n",numberOutput);
5692 delete[] whichColumn;
5693 delete[] whichRow;
5694 delete[] bound;
5695 delete[] stack;
5696 delete[] flip;
5697 delete[] size;
5698 delete[] offset;
5699 delete[] rhsOffset;
5700 delete[] build;
5701 delete[] markRow;
5702 delete[] lo;
5703 delete[] high;
5704 return nelCreate;
5705 }
5706 // Quick try at cleaning up duals if postsolve gets wrong
cleanupAfterPostsolve()5707 void ClpSimplexOther::cleanupAfterPostsolve()
5708 {
5709 // First mark singleton equality rows
5710 char *mark = new char[numberRows_];
5711 memset(mark, 0, numberRows_);
5712 const int *row = matrix_->getIndices();
5713 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
5714 const int *columnLength = matrix_->getVectorLengths();
5715 const double *element = matrix_->getElements();
5716 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
5717 for (CoinBigIndex j = columnStart[iColumn];
5718 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
5719 int iRow = row[j];
5720 if (mark[iRow])
5721 mark[iRow] = 2;
5722 else
5723 mark[iRow] = 1;
5724 }
5725 }
5726 // for now just == rows
5727 for (int iRow = 0; iRow < numberRows_; iRow++) {
5728 if (rowUpper_[iRow] > rowLower_[iRow])
5729 mark[iRow] = 3;
5730 }
5731 double dualTolerance = dblParam_[ClpDualTolerance];
5732 double primalTolerance = dblParam_[ClpPrimalTolerance];
5733 int numberCleaned = 0;
5734 double maxmin = optimizationDirection_;
5735 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
5736 double dualValue = reducedCost_[iColumn] * maxmin;
5737 double primalValue = columnActivity_[iColumn];
5738 double lower = columnLower_[iColumn];
5739 double upper = columnUpper_[iColumn];
5740 int way = 0;
5741 switch (getColumnStatus(iColumn)) {
5742
5743 case basic:
5744 // dual should be zero
5745 if (dualValue > dualTolerance) {
5746 way = -1;
5747 } else if (dualValue < -dualTolerance) {
5748 way = 1;
5749 }
5750 break;
5751 case ClpSimplex::isFixed:
5752 break;
5753 case atUpperBound:
5754 // dual should not be positive
5755 if (dualValue > dualTolerance) {
5756 way = -1;
5757 }
5758 break;
5759 case atLowerBound:
5760 // dual should not be negative
5761 if (dualValue < -dualTolerance) {
5762 way = 1;
5763 }
5764 break;
5765 case superBasic:
5766 case isFree:
5767 if (primalValue < upper - primalTolerance) {
5768 // dual should not be negative
5769 if (dualValue < -dualTolerance) {
5770 way = 1;
5771 }
5772 }
5773 if (primalValue > lower + primalTolerance) {
5774 // dual should not be positive
5775 if (dualValue > dualTolerance) {
5776 way = -1;
5777 }
5778 }
5779 break;
5780 }
5781 if (way) {
5782 // see if can find singleton row
5783 for (CoinBigIndex j = columnStart[iColumn];
5784 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
5785 int iRow = row[j];
5786 if (mark[iRow] == 1) {
5787 double value = element[j];
5788 // dj - addDual*value == 0.0
5789 double addDual = dualValue / value;
5790 dual_[iRow] += addDual;
5791 reducedCost_[iColumn] = 0.0;
5792 numberCleaned++;
5793 break;
5794 }
5795 }
5796 }
5797 }
5798 delete[] mark;
5799 #ifdef CLP_INVESTIGATE
5800 printf("cleanupAfterPostsolve cleaned up %d columns\n", numberCleaned);
5801 #endif
5802 // Redo
5803 memcpy(reducedCost_, this->objective(), numberColumns_ * sizeof(double));
5804 matrix_->transposeTimes(-1.0, dual_, reducedCost_);
5805 checkSolutionInternal();
5806 }
5807 // Returns gub version of model or NULL
5808 ClpSimplex *
gubVersion(int * whichRows,int * whichColumns,int neededGub,int factorizationFrequency)5809 ClpSimplexOther::gubVersion(int *whichRows, int *whichColumns,
5810 int neededGub,
5811 int factorizationFrequency)
5812 {
5813 // find gub
5814 int numberRows = this->numberRows();
5815 int numberColumns = this->numberColumns();
5816 int iRow, iColumn;
5817 int *columnIsGub = new int[numberColumns];
5818 const double *columnLower = this->columnLower();
5819 const double *columnUpper = this->columnUpper();
5820 int numberFixed = 0;
5821 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5822 if (columnUpper[iColumn] == columnLower[iColumn]) {
5823 columnIsGub[iColumn] = -2;
5824 numberFixed++;
5825 } else if (columnLower[iColumn] >= 0) {
5826 columnIsGub[iColumn] = -1;
5827 } else {
5828 columnIsGub[iColumn] = -3;
5829 }
5830 }
5831 CoinPackedMatrix *matrix = this->matrix();
5832 // get row copy
5833 CoinPackedMatrix rowCopy = *matrix;
5834 rowCopy.reverseOrdering();
5835 const int *column = rowCopy.getIndices();
5836 const int *rowLength = rowCopy.getVectorLengths();
5837 const CoinBigIndex *rowStart = rowCopy.getVectorStarts();
5838 const double *element = rowCopy.getElements();
5839 int numberNonGub = 0;
5840 int numberEmpty = numberRows;
5841 int *rowIsGub = new int[numberRows];
5842 int smallestGubRow = -1;
5843 int count = numberColumns + 1;
5844 double *rowLower = this->rowLower();
5845 double *rowUpper = this->rowUpper();
5846 // make sure we can get rid of upper bounds
5847 double *fixedRow = new double[numberRows];
5848 for (iRow = 0; iRow < numberRows; iRow++) {
5849 double sumFixed = 0.0;
5850 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
5851 int iColumn = column[j];
5852 double value = columnLower[iColumn];
5853 if (value)
5854 sumFixed += element[j] * value;
5855 }
5856 fixedRow[iRow] = rowUpper[iRow] - sumFixed;
5857 }
5858 for (iRow = numberRows - 1; iRow >= 0; iRow--) {
5859 bool gubRow = true;
5860 int numberInRow = 0;
5861 double sumFixed = 0.0;
5862 double gap = fixedRow[iRow] - 1.0e-12;
5863 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
5864 int iColumn = column[j];
5865 if (columnIsGub[iColumn] != -2) {
5866 if (element[j] != 1.0 || columnIsGub[iColumn] == -3 || columnUpper[iColumn] - columnLower[iColumn] < gap) {
5867 gubRow = false;
5868 break;
5869 } else {
5870 numberInRow++;
5871 if (columnIsGub[iColumn] >= 0) {
5872 gubRow = false;
5873 break;
5874 }
5875 }
5876 } else {
5877 sumFixed += columnLower[iColumn] * element[j];
5878 }
5879 }
5880 if (!gubRow) {
5881 whichRows[numberNonGub++] = iRow;
5882 rowIsGub[iRow] = -1;
5883 } else if (numberInRow) {
5884 if (numberInRow < count) {
5885 count = numberInRow;
5886 smallestGubRow = iRow;
5887 }
5888 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
5889 int iColumn = column[j];
5890 if (columnIsGub[iColumn] != -2)
5891 columnIsGub[iColumn] = iRow;
5892 }
5893 rowIsGub[iRow] = 0;
5894 } else {
5895 // empty row!
5896 whichRows[--numberEmpty] = iRow;
5897 rowIsGub[iRow] = -2;
5898 if (sumFixed > rowUpper[iRow] + 1.0e-4 || sumFixed < rowLower[iRow] - 1.0e-4) {
5899 fprintf(stderr, "******** No infeasible empty rows - please!\n");
5900 abort();
5901 }
5902 }
5903 }
5904 delete[] fixedRow;
5905 char message[100];
5906 int numberGub = numberEmpty - numberNonGub;
5907 if (numberGub >= neededGub) {
5908 sprintf(message, "%d gub rows", numberGub);
5909 handler_->message(CLP_GENERAL2, messages_)
5910 << message << CoinMessageEol;
5911 int numberNormal = 0;
5912 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5913 if (columnIsGub[iColumn] < 0 && columnIsGub[iColumn] != -2) {
5914 whichColumns[numberNormal++] = iColumn;
5915 }
5916 }
5917 if (!numberNormal) {
5918 sprintf(message, "Putting back one gub row to make non-empty");
5919 handler_->message(CLP_GENERAL2, messages_)
5920 << message << CoinMessageEol;
5921 rowIsGub[smallestGubRow] = -1;
5922 whichRows[numberNonGub++] = smallestGubRow;
5923 for (CoinBigIndex j = rowStart[smallestGubRow];
5924 j < rowStart[smallestGubRow] + rowLength[smallestGubRow]; j++) {
5925 int iColumn = column[j];
5926 if (columnIsGub[iColumn] >= 0) {
5927 columnIsGub[iColumn] = -4;
5928 whichColumns[numberNormal++] = iColumn;
5929 }
5930 }
5931 }
5932 std::sort(whichRows, whichRows + numberNonGub);
5933 std::sort(whichColumns, whichColumns + numberNormal);
5934 double *lower = CoinCopyOfArray(this->rowLower(), numberRows);
5935 double *upper = CoinCopyOfArray(this->rowUpper(), numberRows);
5936 // leave empty rows at end
5937 numberEmpty = numberRows - numberEmpty;
5938 const int *row = matrix->getIndices();
5939 const int *columnLength = matrix->getVectorLengths();
5940 const CoinBigIndex *columnStart = matrix->getVectorStarts();
5941 const double *elementByColumn = matrix->getElements();
5942 // Fixed at end
5943 int put2 = numberColumns - numberFixed;
5944 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
5945 if (columnIsGub[iColumn] == -2) {
5946 whichColumns[put2++] = iColumn;
5947 double value = columnLower[iColumn];
5948 for (CoinBigIndex j = columnStart[iColumn];
5949 j < columnStart[iColumn] + columnLength[iColumn]; j++) {
5950 int iRow = row[j];
5951 if (lower[iRow] > -1.0e20)
5952 lower[iRow] -= value * element[j];
5953 if (upper[iRow] < 1.0e20)
5954 upper[iRow] -= value * element[j];
5955 }
5956 }
5957 }
5958 int put = numberNormal;
5959 ClpSimplex *model2 = new ClpSimplex(this, numberNonGub, whichRows, numberNormal, whichColumns);
5960 // scale
5961 double *scaleArray = new double[numberRows];
5962 for (int i = 0; i < numberRows; i++) {
5963 scaleArray[i] = 1.0;
5964 if (rowIsGub[i] == -1) {
5965 double largest = 1.0e-30;
5966 double smallest = 1.0e30;
5967 for (CoinBigIndex j = rowStart[i]; j < rowStart[i] + rowLength[i]; j++) {
5968 int iColumn = column[j];
5969 if (columnIsGub[iColumn] != -2) {
5970 double value = fabs(element[j]);
5971 largest = CoinMax(value, largest);
5972 smallest = CoinMin(value, smallest);
5973 }
5974 }
5975 double scale = CoinMax(0.001, 1.0 / sqrt(largest * smallest));
5976 scaleArray[i] = scale;
5977 if (lower[i] > -1.0e30)
5978 lower[i] *= scale;
5979 if (upper[i] < 1.0e30)
5980 upper[i] *= scale;
5981 }
5982 }
5983 // scale partial matrix
5984 {
5985 CoinPackedMatrix *matrix = model2->matrix();
5986 const int *row = matrix->getIndices();
5987 const int *columnLength = matrix->getVectorLengths();
5988 const CoinBigIndex *columnStart = matrix->getVectorStarts();
5989 double *element = matrix->getMutableElements();
5990 for (int i = 0; i < numberNormal; i++) {
5991 for (CoinBigIndex j = columnStart[i];
5992 j < columnStart[i] + columnLength[i]; j++) {
5993 int iRow = row[j];
5994 iRow = whichRows[iRow];
5995 double scaleBy = scaleArray[iRow];
5996 element[j] *= scaleBy;
5997 }
5998 }
5999 }
6000 // adjust rhs
6001 double *rowLower = model2->rowLower();
6002 double *rowUpper = model2->rowUpper();
6003 for (int i = 0; i < numberNonGub; i++) {
6004 int iRow = whichRows[i];
6005 rowLower[i] = lower[iRow];
6006 rowUpper[i] = upper[iRow];
6007 }
6008 int numberGubColumns = numberColumns - put - numberFixed;
6009 CoinBigIndex numberElements = 0;
6010 int *temp1 = new int[numberRows + 1];
6011 // get counts
6012 memset(temp1, 0, numberRows * sizeof(int));
6013 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6014 int iGub = columnIsGub[iColumn];
6015 if (iGub >= 0) {
6016 numberElements += columnLength[iColumn] - 1;
6017 temp1[iGub]++;
6018 }
6019 }
6020 /* Optional but means can eventually simplify coding
6021 could even add in fixed slacks to deal with
6022 singularities - but should not be necessary */
6023 int numberSlacks = 0;
6024 for (int i = 0; i < numberRows; i++) {
6025 if (rowIsGub[i] >= 0) {
6026 if (lower[i] < upper[i]) {
6027 numberSlacks++;
6028 temp1[i]++;
6029 }
6030 }
6031 }
6032 int *gubStart = new int[numberGub + 1];
6033 numberGub = 0;
6034 gubStart[0] = 0;
6035 for (int i = 0; i < numberRows; i++) {
6036 if (rowIsGub[i] >= 0) {
6037 rowIsGub[i] = numberGub;
6038 gubStart[numberGub + 1] = gubStart[numberGub] + temp1[i];
6039 temp1[numberGub] = 0;
6040 lower[numberGub] = lower[i];
6041 upper[numberGub] = upper[i];
6042 whichRows[numberNonGub + numberGub] = i;
6043 numberGub++;
6044 }
6045 }
6046 int numberGubColumnsPlus = numberGubColumns + numberSlacks;
6047 double *lowerColumn2 = new double[numberGubColumnsPlus];
6048 CoinFillN(lowerColumn2, numberGubColumnsPlus, 0.0);
6049 double *upperColumn2 = new double[numberGubColumnsPlus];
6050 CoinFillN(upperColumn2, numberGubColumnsPlus, COIN_DBL_MAX);
6051 CoinBigIndex *start2 = new CoinBigIndex[numberGubColumnsPlus + 1];
6052 int *row2 = new int[numberElements];
6053 double *element2 = new double[numberElements];
6054 double *cost2 = new double[numberGubColumnsPlus];
6055 CoinFillN(cost2, numberGubColumnsPlus, 0.0);
6056 const double *cost = this->objective();
6057 put = numberNormal;
6058 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
6059 int iGub = columnIsGub[iColumn];
6060 if (iGub >= 0) {
6061 // TEMP
6062 //this->setColUpper(iColumn,COIN_DBL_MAX);
6063 iGub = rowIsGub[iGub];
6064 assert(iGub >= 0);
6065 int kPut = put + gubStart[iGub] + temp1[iGub];
6066 temp1[iGub]++;
6067 whichColumns[kPut] = iColumn;
6068 }
6069 }
6070 for (int i = 0; i < numberRows; i++) {
6071 if (rowIsGub[i] >= 0) {
6072 int iGub = rowIsGub[i];
6073 if (lower[iGub] < upper[iGub]) {
6074 int kPut = put + gubStart[iGub] + temp1[iGub];
6075 temp1[iGub]++;
6076 whichColumns[kPut] = iGub + numberColumns;
6077 }
6078 }
6079 }
6080 //this->primal(1); // TEMP
6081 // redo rowIsGub to give lookup
6082 for (int i = 0; i < numberRows; i++)
6083 rowIsGub[i] = -1;
6084 for (int i = 0; i < numberNonGub; i++)
6085 rowIsGub[whichRows[i]] = i;
6086 start2[0] = 0;
6087 numberElements = 0;
6088 for (int i = 0; i < numberGubColumnsPlus; i++) {
6089 int iColumn = whichColumns[put++];
6090 if (iColumn < numberColumns) {
6091 cost2[i] = cost[iColumn];
6092 lowerColumn2[i] = columnLower[iColumn];
6093 upperColumn2[i] = columnUpper[iColumn];
6094 upperColumn2[i] = COIN_DBL_MAX;
6095 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
6096 int iRow = row[j];
6097 double scaleBy = scaleArray[iRow];
6098 iRow = rowIsGub[iRow];
6099 if (iRow >= 0) {
6100 row2[numberElements] = iRow;
6101 element2[numberElements++] = elementByColumn[j] * scaleBy;
6102 }
6103 }
6104 } else {
6105 // slack
6106 int iGub = iColumn - numberColumns;
6107 double slack = upper[iGub] - lower[iGub];
6108 assert(upper[iGub] < 1.0e20);
6109 lower[iGub] = upper[iGub];
6110 cost2[i] = 0;
6111 lowerColumn2[i] = 0;
6112 upperColumn2[i] = slack;
6113 upperColumn2[i] = COIN_DBL_MAX;
6114 }
6115 start2[i + 1] = numberElements;
6116 }
6117 // clean up bounds on variables
6118 for (int iSet = 0; iSet < numberGub; iSet++) {
6119 double lowerValue = 0.0;
6120 for (int i = gubStart[iSet]; i < gubStart[iSet + 1]; i++) {
6121 lowerValue += lowerColumn2[i];
6122 }
6123 assert(lowerValue < upper[iSet] + 1.0e-6);
6124 double gap = CoinMax(0.0, upper[iSet] - lowerValue);
6125 for (int i = gubStart[iSet]; i < gubStart[iSet + 1]; i++) {
6126 if (upperColumn2[i] < 1.0e30) {
6127 upperColumn2[i] = CoinMin(upperColumn2[i],
6128 lowerColumn2[i] + gap);
6129 }
6130 }
6131 }
6132 sprintf(message, "** Before adding matrix there are %d rows and %d columns",
6133 model2->numberRows(), model2->numberColumns());
6134 handler_->message(CLP_GENERAL2, messages_)
6135 << message << CoinMessageEol;
6136 delete[] scaleArray;
6137 delete[] temp1;
6138 model2->setFactorizationFrequency(factorizationFrequency);
6139 ClpDynamicMatrix *newMatrix = new ClpDynamicMatrix(model2, numberGub,
6140 numberGubColumnsPlus, gubStart,
6141 lower, upper,
6142 start2, row2, element2, cost2,
6143 lowerColumn2, upperColumn2);
6144 delete[] gubStart;
6145 delete[] lowerColumn2;
6146 delete[] upperColumn2;
6147 delete[] start2;
6148 delete[] row2;
6149 delete[] element2;
6150 delete[] cost2;
6151 delete[] lower;
6152 delete[] upper;
6153 model2->replaceMatrix(newMatrix, true);
6154 #ifdef EVERY_ITERATION
6155 {
6156 ClpDynamicMatrix *gubMatrix = dynamic_cast< ClpDynamicMatrix * >(model2->clpMatrix());
6157 assert(gubMatrix);
6158 gubMatrix->writeMps("gub.mps");
6159 }
6160 #endif
6161 delete[] columnIsGub;
6162 delete[] rowIsGub;
6163 newMatrix->switchOffCheck();
6164 #ifdef EVERY_ITERATION
6165 newMatrix->setRefreshFrequency(1 /*000*/);
6166 #else
6167 newMatrix->setRefreshFrequency(1000);
6168 #endif
6169 sprintf(message,
6170 "** While after adding matrix there are %d rows and %d columns",
6171 model2->numberRows(), model2->numberColumns());
6172 handler_->message(CLP_GENERAL2, messages_)
6173 << message << CoinMessageEol;
6174 model2->setSpecialOptions(4); // exactly to bound
6175 // Scaling off (done by hand)
6176 model2->scaling(0);
6177 return model2;
6178 } else {
6179 delete[] columnIsGub;
6180 delete[] rowIsGub;
6181 return NULL;
6182 }
6183 }
6184 // Sets basis from original
setGubBasis(ClpSimplex & original,const int * whichRows,const int * whichColumns)6185 void ClpSimplexOther::setGubBasis(ClpSimplex &original, const int *whichRows,
6186 const int *whichColumns)
6187 {
6188 ClpDynamicMatrix *gubMatrix = dynamic_cast< ClpDynamicMatrix * >(clpMatrix());
6189 assert(gubMatrix);
6190 int numberGubColumns = gubMatrix->numberGubColumns();
6191 int numberNormal = gubMatrix->firstDynamic();
6192 //int lastOdd = gubMatrix->firstAvailable();
6193 //int numberTotalColumns = numberNormal + numberGubColumns;
6194 //assert (numberTotalColumns==numberColumns+numberSlacks);
6195 int numberRows = original.numberRows();
6196 int numberColumns = original.numberColumns();
6197 int *columnIsGub = new int[numberColumns];
6198 int numberNonGub = gubMatrix->numberStaticRows();
6199 //assert (firstOdd==numberNormal);
6200 double *solution = primalColumnSolution();
6201 double *originalSolution = original.primalColumnSolution();
6202 const double *upperSet = gubMatrix->upperSet();
6203 // Column copy of GUB part
6204 int numberSets = gubMatrix->numberSets();
6205 const int *startSet = gubMatrix->startSets();
6206 const CoinBigIndex *columnStart = gubMatrix->startColumn();
6207 const double *columnLower = gubMatrix->columnLower();
6208 #ifdef TRY_IMPROVE
6209 const double *columnUpper = gubMatrix->columnUpper();
6210 const double *lowerSet = gubMatrix->lowerSet();
6211 const double *element = gubMatrix->element();
6212 const int *row = gubMatrix->row();
6213 bool allPositive = true;
6214 double *rowActivity = new double[numberNonGub];
6215 memset(rowActivity, 0, numberNonGub * sizeof(double));
6216 {
6217 // Non gub contribution
6218 const double *element = matrix_->getElements();
6219 const int *row = matrix_->getIndices();
6220 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
6221 const int *columnLength = matrix_->getVectorLengths();
6222 for (int i = 0; i < numberNormal; i++) {
6223 int iColumn = whichColumns[i];
6224 double value = originalSolution[iColumn];
6225 if (value) {
6226 for (CoinBigIndex j = columnStart[i];
6227 j < columnStart[i] + columnLength[i]; j++) {
6228 int iRow = row[j];
6229 rowActivity[iRow] += value * element[j];
6230 }
6231 }
6232 }
6233 }
6234 double *newSolution = new double[numberGubColumns];
6235 int *slacks = new int[numberSets];
6236 for (int i = 0; i < numberSets; i++) {
6237 double sum = 0.0;
6238 int iSlack = -1;
6239 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6240 gubMatrix->setDynamicStatus(j, ClpDynamicMatrix::atLowerBound);
6241 int iColumn = whichColumns[j + numberNormal];
6242 if (iColumn < numberColumns) {
6243 columnIsGub[iColumn] = whichRows[numberNonGub + i];
6244 double value = originalSolution[iColumn];
6245 sum += value;
6246 newSolution[j] = value;
6247 for (CoinBigIndex k = columnStart[j]; k < columnStart[j + 1]; k++) {
6248 int iRow = row[k];
6249 rowActivity[iRow] += value * element[k];
6250 if (element[k] < 0.0)
6251 allPositive = false;
6252 }
6253 if (columnStart[j] == columnStart[j + 1])
6254 iSlack = j;
6255 } else {
6256 newSolution[j] = 0.0;
6257 iSlack = j;
6258 allPositive = false; // for now
6259 }
6260 }
6261 slacks[i] = iSlack;
6262 if (sum > upperSet[i] + 1.0e-8) {
6263 double gap = sum - upperSet[i];
6264 if (iSlack >= 0) {
6265 double value = newSolution[iSlack];
6266 if (value > 0.0) {
6267 double down = CoinMin(gap, value);
6268 gap -= down;
6269 sum -= down;
6270 newSolution[iSlack] = value - down;
6271 }
6272 }
6273 if (gap > 1.0e-8) {
6274 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6275 int iColumn = whichColumns[j + numberNormal];
6276 if (newSolution[j] > 0.0 && iColumn < numberColumns) {
6277 double value = newSolution[j];
6278 double down = CoinMin(gap, value);
6279 gap -= down;
6280 sum -= down;
6281 newSolution[iSlack] = value - down;
6282 for (CoinBigIndex k = columnStart[j]; k < columnStart[j + 1]; k++) {
6283 int iRow = row[k];
6284 rowActivity[iRow] -= down * element[k];
6285 }
6286 }
6287 }
6288 }
6289 assert(gap < 1.0e-8);
6290 } else if (sum < lowerSet[i] - 1.0e-8) {
6291 double gap = lowerSet[i] - sum;
6292 if (iSlack >= 0) {
6293 double value = newSolution[iSlack];
6294 if (value < columnUpper[iSlack]) {
6295 double up = CoinMin(gap, columnUpper[iSlack] - value);
6296 gap -= up;
6297 sum += up;
6298 newSolution[iSlack] = value + up;
6299 }
6300 }
6301 if (gap > 1.0e-8) {
6302 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6303 int iColumn = whichColumns[j + numberNormal];
6304 if (newSolution[j] < columnUpper[j] && iColumn < numberColumns) {
6305 double value = newSolution[j];
6306 double up = CoinMin(gap, columnUpper[j] - value);
6307 gap -= up;
6308 sum += up;
6309 newSolution[iSlack] = value + up;
6310 for (CoinBigIndex k = columnStart[j]; k < columnStart[j + 1]; k++) {
6311 int iRow = row[k];
6312 rowActivity[iRow] += up * element[k];
6313 }
6314 }
6315 }
6316 }
6317 assert(gap < 1.0e-8);
6318 }
6319 if (fabs(sum - upperSet[i]) > 1.0e-7)
6320 printf("Sum for set %d is %g - lower %g, upper %g\n", i,
6321 sum, lowerSet[i], upperSet[i]);
6322 }
6323 if (allPositive) {
6324 // See if we can improve solution
6325 // first reduce if over
6326 double *gaps = new double[numberNonGub];
6327 double direction = optimizationDirection_;
6328 const double *cost = gubMatrix->cost();
6329 bool over = false;
6330 for (int i = 0; i < numberNonGub; i++) {
6331 double activity = rowActivity[i];
6332 gaps[i] = 0.0;
6333 if (activity > rowUpper_[i] + 1.0e-6) {
6334 gaps[i] = activity - rowUpper_[i];
6335 over = true;
6336 }
6337 }
6338 double *weights = new double[numberGubColumns];
6339 int *which = new int[numberGubColumns];
6340 int *whichSet = new int[numberGubColumns];
6341 if (over) {
6342 int n = 0;
6343 for (int i = 0; i < numberSets; i++) {
6344 int iSlack = slacks[i];
6345 if (iSlack < 0 || newSolution[iSlack] > upperSet[i] - 1.0e-8)
6346 continue;
6347 double slackCost = cost[iSlack] * direction;
6348 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6349 whichSet[j] = i;
6350 double value = newSolution[j];
6351 double thisCost = cost[j] * direction;
6352 if (value > columnLower[j] && j != iSlack) {
6353 if (thisCost < slackCost) {
6354 double sum = 1.0e-30;
6355 for (CoinBigIndex k = columnStart[j];
6356 k < columnStart[j + 1]; k++) {
6357 int iRow = row[k];
6358 sum += gaps[iRow] * element[k];
6359 }
6360 which[n] = j;
6361 // big drop and small difference in cost better
6362 weights[n++] = (slackCost - thisCost) / sum;
6363 } else {
6364 // slack better anyway
6365 double move = value - columnLower[j];
6366 newSolution[iSlack] = CoinMin(upperSet[i],
6367 newSolution[iSlack] + move);
6368 newSolution[j] = columnLower[j];
6369 for (CoinBigIndex k = columnStart[j];
6370 k < columnStart[j + 1]; k++) {
6371 int iRow = row[k];
6372 rowActivity[iRow] -= move * element[k];
6373 }
6374 }
6375 }
6376 }
6377 }
6378 // sort
6379 CoinSort_2(weights, weights + n, which);
6380 for (int i = 0; i < n; i++) {
6381 int j = which[i];
6382 int iSet = whichSet[j];
6383 int iSlack = slacks[iSet];
6384 assert(iSlack >= 0);
6385 double move = 0.0;
6386 for (CoinBigIndex k = columnStart[j];
6387 k < columnStart[j + 1]; k++) {
6388 int iRow = row[k];
6389 if (rowActivity[iRow] - rowUpper_[iRow] > move * element[k]) {
6390 move = (rowActivity[iRow] - rowUpper_[iRow]) / element[k];
6391 }
6392 }
6393 move = CoinMin(move, newSolution[j] - columnLower[j]);
6394 if (move) {
6395 newSolution[j] -= move;
6396 newSolution[iSlack] += move;
6397 for (CoinBigIndex k = columnStart[j];
6398 k < columnStart[j + 1]; k++) {
6399 int iRow = row[k];
6400 rowActivity[iRow] -= move * element[k];
6401 }
6402 }
6403 }
6404 }
6405 delete[] whichSet;
6406 delete[] which;
6407 delete[] weights;
6408 delete[] gaps;
6409 // redo original status!
6410 for (int i = 0; i < numberSets; i++) {
6411 int numberBasic = 0;
6412 int numberNewBasic = 0;
6413 int j1 = -1;
6414 int j2 = -1;
6415 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6416 if (newSolution[j] > columnLower[j]) {
6417 numberNewBasic++;
6418 j2 = j;
6419 }
6420 int iOrig = whichColumns[j + numberNormal];
6421 if (iOrig < numberColumns) {
6422 if (original.getColumnStatus(iOrig) != ClpSimplex::atLowerBound) {
6423 numberBasic++;
6424 j1 = j;
6425 }
6426 } else {
6427 int iSet = iOrig - numberColumns;
6428 int iRow = whichRows[iSet + numberNonGub];
6429 if (original.getRowStatus(iRow) == ClpSimplex::basic) {
6430 numberBasic++;
6431 j1 = j;
6432 abort();
6433 }
6434 }
6435 }
6436 if (numberBasic == 1 && numberNewBasic == 1 && j1 != j2) {
6437 int iOrig1 = whichColumns[j1 + numberNormal];
6438 int iOrig2 = whichColumns[j2 + numberNormal];
6439 ClpSimplex::Status status1 = original.getColumnStatus(iOrig1);
6440 ClpSimplex::Status status2 = original.getColumnStatus(iOrig2);
6441 originalSolution[iOrig1] = newSolution[j1];
6442 originalSolution[iOrig2] = newSolution[j2];
6443 original.setColumnStatus(iOrig1, status2);
6444 original.setColumnStatus(iOrig2, status1);
6445 }
6446 }
6447 }
6448 delete[] newSolution;
6449 delete[] slacks;
6450 delete[] rowActivity;
6451 #else
6452 for (int i = 0; i < numberSets; i++) {
6453 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6454 gubMatrix->setDynamicStatus(j, ClpDynamicMatrix::atLowerBound);
6455 int iColumn = whichColumns[j + numberNormal];
6456 if (iColumn < numberColumns) {
6457 columnIsGub[iColumn] = whichRows[numberNonGub + i];
6458 }
6459 }
6460 }
6461 #endif
6462 int *numberKey = new int[numberRows];
6463 memset(numberKey, 0, numberRows * sizeof(int));
6464 for (int i = 0; i < numberGubColumns; i++) {
6465 int iOrig = whichColumns[i + numberNormal];
6466 if (iOrig < numberColumns) {
6467 if (original.getColumnStatus(iOrig) == ClpSimplex::basic) {
6468 int iRow = columnIsGub[iOrig];
6469 assert(iRow >= 0);
6470 numberKey[iRow]++;
6471 }
6472 } else {
6473 // Set slack
6474 int iSet = iOrig - numberColumns;
6475 int iRow = whichRows[iSet + numberNonGub];
6476 if (original.getRowStatus(iRow) == ClpSimplex::basic)
6477 numberKey[iRow]++;
6478 }
6479 }
6480 /* Before going into cleanMatrix we need
6481 gub status set (inSmall just means basic and active)
6482 row status set
6483 */
6484 for (int i = 0; i < numberSets; i++) {
6485 gubMatrix->setStatus(i, ClpSimplex::isFixed);
6486 }
6487 for (int i = 0; i < numberGubColumns; i++) {
6488 int iOrig = whichColumns[i + numberNormal];
6489 if (iOrig < numberColumns) {
6490 ClpSimplex::Status status = original.getColumnStatus(iOrig);
6491 if (status == ClpSimplex::atUpperBound) {
6492 gubMatrix->setDynamicStatus(i, ClpDynamicMatrix::atUpperBound);
6493 } else if (status == ClpSimplex::atLowerBound) {
6494 gubMatrix->setDynamicStatus(i, ClpDynamicMatrix::atLowerBound);
6495 } else if (status == ClpSimplex::basic) {
6496 int iRow = columnIsGub[iOrig];
6497 assert(iRow >= 0);
6498 assert(numberKey[iRow]);
6499 if (numberKey[iRow] == 1)
6500 gubMatrix->setDynamicStatus(i, ClpDynamicMatrix::soloKey);
6501 else
6502 gubMatrix->setDynamicStatus(i, ClpDynamicMatrix::inSmall);
6503 }
6504 } else {
6505 // slack
6506 int iSet = iOrig - numberColumns;
6507 int iRow = whichRows[iSet + numberNonGub];
6508 if (original.getRowStatus(iRow) == ClpSimplex::basic
6509 #ifdef TRY_IMPROVE
6510 || newSolution[i] > columnLower[i] + 1.0e-8
6511 #endif
6512 ) {
6513 assert(numberKey[iRow]);
6514 if (numberKey[iRow] == 1)
6515 gubMatrix->setDynamicStatus(i, ClpDynamicMatrix::soloKey);
6516 else
6517 gubMatrix->setDynamicStatus(i, ClpDynamicMatrix::inSmall);
6518 } else {
6519 gubMatrix->setDynamicStatus(i, ClpDynamicMatrix::atLowerBound);
6520 }
6521 }
6522 }
6523 // deal with sets without key
6524 for (int i = 0; i < numberSets; i++) {
6525 int iRow = whichRows[numberNonGub + i];
6526 if (!numberKey[iRow]) {
6527 double upper = upperSet[i] - 1.0e-7;
6528 if (original.getRowStatus(iRow) == ClpSimplex::basic)
6529 gubMatrix->setStatus(i, ClpSimplex::basic);
6530 // If not at lb make key otherwise one with smallest number els
6531 double largest = 0.0;
6532 int fewest = numberRows + 1;
6533 int chosen = -1;
6534 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6535 int length = static_cast< int >(columnStart[j + 1] - columnStart[j]);
6536 int iOrig = whichColumns[j + numberNormal];
6537 double value;
6538 if (iOrig < numberColumns) {
6539 #ifdef TRY_IMPROVE
6540 value = newSolution[j] - columnLower[j];
6541 #else
6542 value = originalSolution[iOrig] - columnLower[j];
6543 #endif
6544 if (value > upper)
6545 gubMatrix->setStatus(i, ClpSimplex::atLowerBound);
6546 } else {
6547 // slack - take value as 0.0 as will win on length
6548 value = 0.0;
6549 }
6550 if (value > largest + 1.0e-8) {
6551 largest = value;
6552 fewest = length;
6553 chosen = j;
6554 } else if (fabs(value - largest) <= 1.0e-8 && length < fewest) {
6555 largest = value;
6556 fewest = length;
6557 chosen = j;
6558 }
6559 }
6560 assert(chosen >= 0);
6561 if (gubMatrix->getStatus(i) != ClpSimplex::basic) {
6562 // set as key
6563 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6564 if (j != chosen)
6565 gubMatrix->setDynamicStatus(j, ClpDynamicMatrix::atLowerBound);
6566 else
6567 gubMatrix->setDynamicStatus(j, ClpDynamicMatrix::soloKey);
6568 }
6569 }
6570 }
6571 }
6572 for (int i = 0; i < numberNormal; i++) {
6573 int iOrig = whichColumns[i];
6574 setColumnStatus(i, original.getColumnStatus(iOrig));
6575 solution[i] = originalSolution[iOrig];
6576 }
6577 for (int i = 0; i < numberNonGub; i++) {
6578 int iOrig = whichRows[i];
6579 setRowStatus(i, original.getRowStatus(iOrig));
6580 }
6581 // Fill in current matrix
6582 gubMatrix->initialProblem();
6583 delete[] numberKey;
6584 delete[] columnIsGub;
6585 }
6586 // Restores basis to original
getGubBasis(ClpSimplex & original,const int * whichRows,const int * whichColumns) const6587 void ClpSimplexOther::getGubBasis(ClpSimplex &original, const int *whichRows,
6588 const int *whichColumns) const
6589 {
6590 ClpDynamicMatrix *gubMatrix = dynamic_cast< ClpDynamicMatrix * >(clpMatrix());
6591 assert(gubMatrix);
6592 int numberGubColumns = gubMatrix->numberGubColumns();
6593 int numberNormal = gubMatrix->firstDynamic();
6594 //int lastOdd = gubMatrix->firstAvailable();
6595 //int numberRows = original.numberRows();
6596 int numberColumns = original.numberColumns();
6597 int numberNonGub = gubMatrix->numberStaticRows();
6598 //assert (firstOdd==numberNormal);
6599 double *solution = primalColumnSolution();
6600 double *originalSolution = original.primalColumnSolution();
6601 int numberSets = gubMatrix->numberSets();
6602 const double *cost = original.objective();
6603 int lastOdd = gubMatrix->firstAvailable();
6604 //assert (numberTotalColumns==numberColumns+numberSlacks);
6605 int numberRows = original.numberRows();
6606 //int numberStaticRows = gubMatrix->numberStaticRows();
6607 const int *startSet = gubMatrix->startSets();
6608 unsigned char *status = original.statusArray();
6609 unsigned char *rowStatus = status + numberColumns;
6610 //assert (firstOdd==numberNormal);
6611 for (int i = 0; i < numberSets; i++) {
6612 int iRow = whichRows[i + numberNonGub];
6613 original.setRowStatus(iRow, ClpSimplex::atLowerBound);
6614 }
6615 const int *id = gubMatrix->id();
6616 const double *columnLower = gubMatrix->columnLower();
6617 const double *columnUpper = gubMatrix->columnUpper();
6618 for (int i = 0; i < numberGubColumns; i++) {
6619 int iOrig = whichColumns[i + numberNormal];
6620 if (iOrig < numberColumns) {
6621 if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) {
6622 originalSolution[iOrig] = columnUpper[i];
6623 status[iOrig] = 2;
6624 } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound && columnLower) {
6625 originalSolution[iOrig] = columnLower[i];
6626 status[iOrig] = 3;
6627 } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) {
6628 int iSet = gubMatrix->whichSet(i);
6629 originalSolution[iOrig] = gubMatrix->keyValue(iSet);
6630 status[iOrig] = 1;
6631 } else {
6632 originalSolution[iOrig] = 0.0;
6633 status[iOrig] = 4;
6634 }
6635 } else {
6636 // slack
6637 int iSet = iOrig - numberColumns;
6638 int iRow = whichRows[iSet + numberNonGub];
6639 if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atUpperBound) {
6640 original.setRowStatus(iRow, ClpSimplex::atLowerBound);
6641 } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::atLowerBound) {
6642 original.setRowStatus(iRow, ClpSimplex::atUpperBound);
6643 } else if (gubMatrix->getDynamicStatus(i) == ClpDynamicMatrix::soloKey) {
6644 original.setRowStatus(iRow, ClpSimplex::basic);
6645 }
6646 }
6647 }
6648 for (int i = 0; i < numberNormal; i++) {
6649 int iOrig = whichColumns[i];
6650 ClpSimplex::Status thisStatus = getStatus(i);
6651 if (thisStatus == ClpSimplex::basic)
6652 status[iOrig] = 1;
6653 else if (thisStatus == ClpSimplex::atLowerBound)
6654 status[iOrig] = 3;
6655 else if (thisStatus == ClpSimplex::atUpperBound)
6656 status[iOrig] = 2;
6657 else if (thisStatus == ClpSimplex::isFixed)
6658 status[iOrig] = 5;
6659 else
6660 abort();
6661 originalSolution[iOrig] = solution[i];
6662 }
6663 for (int i = numberNormal; i < lastOdd; i++) {
6664 int iOrig = whichColumns[id[i - numberNormal] + numberNormal];
6665 if (iOrig < numberColumns) {
6666 ClpSimplex::Status thisStatus = getStatus(i);
6667 if (thisStatus == ClpSimplex::basic)
6668 status[iOrig] = 1;
6669 else if (thisStatus == ClpSimplex::atLowerBound)
6670 status[iOrig] = 3;
6671 else if (thisStatus == ClpSimplex::atUpperBound)
6672 status[iOrig] = 2;
6673 else if (thisStatus == ClpSimplex::isFixed)
6674 status[iOrig] = 5;
6675 else
6676 abort();
6677 originalSolution[iOrig] = solution[i];
6678 } else {
6679 // slack (basic probably)
6680 int iSet = iOrig - numberColumns;
6681 int iRow = whichRows[iSet + numberNonGub];
6682 ClpSimplex::Status thisStatus = getStatus(i);
6683 if (thisStatus == ClpSimplex::atLowerBound)
6684 thisStatus = ClpSimplex::atUpperBound;
6685 else if (thisStatus == ClpSimplex::atUpperBound)
6686 thisStatus = ClpSimplex::atLowerBound;
6687 original.setRowStatus(iRow, thisStatus);
6688 }
6689 }
6690 for (int i = 0; i < numberNonGub; i++) {
6691 int iOrig = whichRows[i];
6692 ClpSimplex::Status thisStatus = getRowStatus(i);
6693 if (thisStatus == ClpSimplex::basic)
6694 rowStatus[iOrig] = 1;
6695 else if (thisStatus == ClpSimplex::atLowerBound)
6696 rowStatus[iOrig] = 3;
6697 else if (thisStatus == ClpSimplex::atUpperBound)
6698 rowStatus[iOrig] = 2;
6699 else if (thisStatus == ClpSimplex::isFixed)
6700 rowStatus[iOrig] = 5;
6701 else
6702 abort();
6703 }
6704 int *numberKey = new int[numberRows];
6705 memset(numberKey, 0, numberRows * sizeof(int));
6706 for (int i = 0; i < numberSets; i++) {
6707 int iRow = whichRows[i + numberNonGub];
6708 for (int j = startSet[i]; j < startSet[i + 1]; j++) {
6709 int iOrig = whichColumns[j + numberNormal];
6710 if (iOrig < numberColumns) {
6711 if (original.getColumnStatus(iOrig) == ClpSimplex::basic) {
6712 numberKey[iRow]++;
6713 }
6714 } else {
6715 // slack
6716 if (original.getRowStatus(iRow) == ClpSimplex::basic)
6717 numberKey[iRow]++;
6718 }
6719 }
6720 }
6721 for (int i = 0; i < numberSets; i++) {
6722 int iRow = whichRows[i + numberNonGub];
6723 if (!numberKey[iRow]) {
6724 original.setRowStatus(iRow, ClpSimplex::basic);
6725 }
6726 }
6727 delete[] numberKey;
6728 double objValue = 0.0;
6729 for (int i = 0; i < numberColumns; i++)
6730 objValue += cost[i] * originalSolution[i];
6731 //printf("objective value is %g\n", objValue);
6732 }
6733 /*
6734 Modifies coefficients etc and if necessary pivots in and out.
6735 All at same status will be done (basis may go singular).
6736 User can tell which others have been done (i.e. if status matches).
6737 If called from outside will change status and return 0 (-1 if not ClpPacked)
6738 If called from event handler returns non-zero if user has to take action.
6739 -1 - not ClpPackedMatrix
6740 0 - no pivots
6741 1 - pivoted
6742 2 - pivoted and optimal
6743 3 - refactorize
6744 4 - worse than that
6745 indices>=numberColumns are slacks (obviously no coefficients)
6746 status array is (char) Status enum
6747 */
modifyCoefficientsAndPivot(int number,const int * which,const CoinBigIndex * start,const int * row,const double * newCoefficient,const unsigned char * newStatus,const double * newLower,const double * newUpper,const double * newObjective)6748 int ClpSimplex::modifyCoefficientsAndPivot(int number,
6749 const int *which,
6750 const CoinBigIndex *start,
6751 const int *row,
6752 const double *newCoefficient,
6753 const unsigned char *newStatus,
6754 const double *newLower,
6755 const double *newUpper,
6756 const double *newObjective)
6757 {
6758 ClpPackedMatrix *clpMatrix = dynamic_cast< ClpPackedMatrix * >(matrix_);
6759 bool canPivot = lower_ != NULL && factorization_ != NULL;
6760 int returnCode = 0;
6761 if (!clpMatrix) {
6762 canPivot = false;
6763 returnCode = -1;
6764 // very slow
6765 for (int i = 0; i < number; i++) {
6766 int iSequence = which[i];
6767 if (iSequence < numberColumns_) {
6768 for (CoinBigIndex j = start[i]; j < start[i + 1]; j++) {
6769 matrix_->modifyCoefficient(row[j], iSequence, newCoefficient[j]);
6770 }
6771 } else {
6772 assert(start[i] == start[i + 1]);
6773 }
6774 }
6775 } else {
6776 #if 0
6777 // when in stable
6778 CoinPackedMatrix * matrix = clpMatrix->getPackedMatrix();
6779 matrix->modifyCoefficients(number,which,start,
6780 row,newCoefficient);
6781 #else
6782 // Copy and sort which
6783 int *which2 = new int[2 * number + 2];
6784 int *sort = which2 + number + 1;
6785 int n = 0;
6786 for (int i = 0; i < number; i++) {
6787 int iSequence = which[i];
6788 if (iSequence < numberColumns_) {
6789 which2[n] = iSequence;
6790 sort[n++] = i;
6791 } else {
6792 assert(start[i] == start[i + 1]);
6793 }
6794 }
6795 if (n) {
6796 CoinIndexedVector *rowVector = NULL;
6797 for (int i = 0; i < 4; i++) {
6798 if (rowArray_[i] && !rowArray_[i]->getNumElements()) {
6799 rowVector = rowArray_[i];
6800 break;
6801 }
6802 }
6803 bool tempVector = false;
6804 if (!rowVector) {
6805 tempVector = true;
6806 rowVector = new CoinIndexedVector(numberRows_);
6807 }
6808 CoinSort_2(which2, which2 + n, sort);
6809 // Stop at end
6810 which2[n] = numberColumns_;
6811 sort[n] = n;
6812 CoinPackedMatrix *matrix = clpMatrix->getPackedMatrix();
6813 int *rowNow = matrix->getMutableIndices();
6814 CoinBigIndex *columnStart = matrix->getMutableVectorStarts();
6815 int *columnLength = matrix->getMutableVectorLengths();
6816 double *elementByColumn = matrix->getMutableElements();
6817 double *array = rowVector->denseVector();
6818 //int * index = rowVector->getIndices();
6819 int needed = 0;
6820 bool moveUp = false;
6821 for (int i = 0; i < n; i++) {
6822 int inWhich = sort[i];
6823 int iSequence = which2[inWhich];
6824 int nZeroNew = 0;
6825 int nZeroOld = 0;
6826 for (CoinBigIndex j = start[inWhich]; j < start[inWhich + 1]; j++) {
6827 int iRow = row[j];
6828 double newValue = newCoefficient[j];
6829 if (!newValue) {
6830 newValue = COIN_INDEXED_REALLY_TINY_ELEMENT;
6831 nZeroNew++;
6832 }
6833 array[iRow] = newValue;
6834 }
6835 for (CoinBigIndex j = columnStart[iSequence];
6836 j < columnStart[iSequence] + columnLength[iSequence]; j++) {
6837 int iRow = rowNow[j];
6838 double oldValue = elementByColumn[j];
6839 if (fabs(oldValue) > COIN_INDEXED_REALLY_TINY_ELEMENT) {
6840 double newValue = array[iRow];
6841 if (oldValue != newValue) {
6842 if (newValue) {
6843 array[iRow] = 0.0;
6844 if (newValue == COIN_INDEXED_REALLY_TINY_ELEMENT) {
6845 needed--;
6846 }
6847 }
6848 }
6849 } else {
6850 nZeroOld++;
6851 }
6852 }
6853 assert(!nZeroOld);
6854 for (CoinBigIndex j = start[inWhich]; j < start[inWhich + 1]; j++) {
6855 int iRow = row[j];
6856 double newValue = array[iRow];
6857 if (newValue) {
6858 array[iRow] = 0.0;
6859 needed++;
6860 if (needed > 0)
6861 moveUp = true;
6862 }
6863 }
6864 }
6865 CoinBigIndex numberElements = matrix->getNumElements();
6866 assert(numberElements == columnStart[numberColumns_]);
6867 if (needed > 0) {
6868 // need more space
6869 matrix->reserve(numberColumns_, numberElements + needed);
6870 rowNow = matrix->getMutableIndices();
6871 elementByColumn = matrix->getMutableElements();
6872 }
6873 if (moveUp) {
6874 // move up from top
6875 CoinBigIndex top = numberElements + needed;
6876 for (int iColumn = numberColumns_ - 1; iColumn >= 0; iColumn--) {
6877 CoinBigIndex end = columnStart[iColumn + 1];
6878 columnStart[iColumn + 1] = top;
6879 CoinBigIndex startThis = columnStart[iColumn];
6880 for (CoinBigIndex j = end - 1; j >= startThis; j--) {
6881 if (elementByColumn[j]) {
6882 top--;
6883 elementByColumn[top] = elementByColumn[j];
6884 rowNow[top] = rowNow[j];
6885 }
6886 }
6887 }
6888 columnStart[0] = top;
6889 }
6890 // now move down and insert
6891 CoinBigIndex put = 0;
6892 int iColumn = 0;
6893 for (int i = 0; i < n + 1; i++) {
6894 int inWhich = sort[i];
6895 int nextMod = which2[inWhich];
6896 for (; iColumn < nextMod; iColumn++) {
6897 CoinBigIndex startThis = columnStart[iColumn];
6898 columnStart[iColumn] = put;
6899 for (CoinBigIndex j = startThis;
6900 j < columnStart[iColumn + 1]; j++) {
6901 int iRow = rowNow[j];
6902 double oldValue = elementByColumn[j];
6903 if (oldValue) {
6904 rowNow[put] = iRow;
6905 elementByColumn[put++] = oldValue;
6906 }
6907 }
6908 }
6909 if (i == n) {
6910 columnStart[iColumn] = put;
6911 break;
6912 }
6913 // Now
6914 for (CoinBigIndex j = start[inWhich]; j < start[inWhich + 1]; j++) {
6915 int iRow = row[j];
6916 double newValue = newCoefficient[j];
6917 if (!newValue) {
6918 newValue = COIN_INDEXED_REALLY_TINY_ELEMENT;
6919 }
6920 array[iRow] = newValue;
6921 }
6922 CoinBigIndex startThis = columnStart[iColumn];
6923 columnStart[iColumn] = put;
6924 for (CoinBigIndex j = startThis;
6925 j < columnStart[iColumn + 1]; j++) {
6926 int iRow = rowNow[j];
6927 double oldValue = elementByColumn[j];
6928 if (array[iRow]) {
6929 oldValue = array[iRow];
6930 if (oldValue == COIN_INDEXED_REALLY_TINY_ELEMENT)
6931 oldValue = 0.0;
6932 array[iRow] = 0.0;
6933 }
6934 if (fabs(oldValue) > COIN_INDEXED_REALLY_TINY_ELEMENT) {
6935 rowNow[put] = iRow;
6936 elementByColumn[put++] = oldValue;
6937 }
6938 }
6939 for (CoinBigIndex j = start[inWhich]; j < start[inWhich + 1]; j++) {
6940 int iRow = row[j];
6941 double newValue = array[iRow];
6942 if (newValue) {
6943 array[iRow] = 0.0;
6944 rowNow[put] = iRow;
6945 elementByColumn[put++] = newValue;
6946 }
6947 }
6948 iColumn++;
6949 }
6950 matrix->setNumElements(put);
6951 if (tempVector)
6952 delete rowVector;
6953 for (int i = 0; i < numberColumns_; i++) {
6954 columnLength[i] = static_cast< int >(columnStart[i + 1] - columnStart[i]);
6955 }
6956 }
6957 #endif
6958 if (canPivot) {
6959 // ? faster to modify row copy??
6960 if (rowCopy_ && start[number]) {
6961 delete rowCopy_;
6962 rowCopy_ = clpMatrix->reverseOrderedCopy();
6963 }
6964 assert(!newStatus); // do later
6965 int numberPivots = factorization_->pivots();
6966 int needed = 0;
6967 for (int i = 0; i < number; i++) {
6968 int iSequence = which[i];
6969 if (start[i + 1] > start[i] && getStatus(iSequence) == basic)
6970 needed++;
6971 }
6972 if (needed && numberPivots + needed < 20 && needed < -2) {
6973 // update factorization
6974 int saveIn = sequenceIn_;
6975 int savePivot = pivotRow_;
6976 int nArray = 0;
6977 CoinIndexedVector *vec[2];
6978 for (int i = 0; i < 4; i++) {
6979 if (!rowArray_[i]->getNumElements()) {
6980 vec[nArray++] = rowArray_[i];
6981 if (nArray == 2)
6982 break;
6983 }
6984 }
6985 assert(nArray == 2); // could use temp array
6986 for (int i = 0; i < number; i++) {
6987 int sequenceIn_ = which[i];
6988 if (start[i + 1] > start[i] && getStatus(sequenceIn_) == basic) {
6989 // find pivot row
6990 for (pivotRow_ = 0; pivotRow_ < numberRows_; pivotRow_++) {
6991 if (pivotVariable_[pivotRow_] == sequenceIn_)
6992 break;
6993 }
6994 assert(pivotRow_ < numberRows_);
6995 // unpack column
6996 assert(!vec[0]->getNumElements());
6997 #ifndef COIN_FAC_NEW
6998 unpackPacked(vec[0]);
6999 #else
7000 unpack(vec[0]);
7001 #endif
7002 // update
7003 assert(!vec[1]->getNumElements());
7004 factorization_->updateColumnFT(vec[1], vec[0]);
7005 const double *array = vec[0]->denseVector();
7006 #ifndef COIN_FAC_NEW
7007 // Find alpha
7008 const int *indices = vec[0]->getIndices();
7009 int n = vec[0]->getNumElements();
7010 alpha_ = 0.0;
7011 for (int i = 0; i < n; i++) {
7012 if (indices[i] == pivotRow_) {
7013 alpha_ = array[i];
7014 break;
7015 }
7016 }
7017 #else
7018 alpha_ = array[pivotRow_];
7019 #endif
7020 int updateStatus = 2;
7021 if (fabs(alpha_) > 1.0e-7)
7022 updateStatus = factorization_->replaceColumn(this,
7023 vec[1],
7024 vec[0],
7025 pivotRow_,
7026 alpha_);
7027 assert(!vec[1]->getNumElements());
7028 vec[0]->clear();
7029 if (updateStatus) {
7030 returnCode = 3;
7031 break;
7032 }
7033 }
7034 }
7035 sequenceIn_ = saveIn;
7036 pivotRow_ = savePivot;
7037 if (!returnCode)
7038 returnCode = 100; // say can do more
7039 } else if (needed) {
7040 returnCode = 3; // refactorize
7041 }
7042 }
7043 }
7044 if (newStatus) {
7045 for (int i = 0; i < number; i++) {
7046 int iSequence = which[i];
7047 status_[iSequence] = newStatus[i];
7048 }
7049 }
7050 if (newLower) {
7051 for (int i = 0; i < number; i++) {
7052 int iSequence = which[i];
7053 if (iSequence < numberColumns_) {
7054 if (columnLower_[iSequence] != newLower[i]) {
7055 columnLower_[iSequence] = newLower[i];
7056 }
7057 } else {
7058 iSequence -= numberColumns_;
7059 if (rowLower_[iSequence] != newLower[i]) {
7060 rowLower_[iSequence] = newLower[i];
7061 }
7062 }
7063 }
7064 }
7065 if (newLower) {
7066 for (int i = 0; i < number; i++) {
7067 int iSequence = which[i];
7068 if (iSequence < numberColumns_) {
7069 if (columnLower_[iSequence] != newLower[i]) {
7070 columnLower_[iSequence] = newLower[i];
7071 }
7072 } else {
7073 iSequence -= numberColumns_;
7074 if (rowLower_[iSequence] != newLower[i]) {
7075 rowLower_[iSequence] = newLower[i];
7076 }
7077 }
7078 }
7079 }
7080 if (newUpper) {
7081 for (int i = 0; i < number; i++) {
7082 int iSequence = which[i];
7083 if (iSequence < numberColumns_) {
7084 if (columnUpper_[iSequence] != newUpper[i]) {
7085 columnUpper_[iSequence] = newUpper[i];
7086 }
7087 } else {
7088 iSequence -= numberColumns_;
7089 if (rowUpper_[iSequence] != newUpper[i]) {
7090 rowUpper_[iSequence] = newUpper[i];
7091 }
7092 }
7093 }
7094 }
7095 if (newObjective) {
7096 double *obj = objective();
7097 for (int i = 0; i < number; i++) {
7098 int iSequence = which[i];
7099 if (iSequence < numberColumns_) {
7100 if (obj[iSequence] != newObjective[i]) {
7101 obj[iSequence] = newObjective[i];
7102 }
7103 } else {
7104 assert(!newObjective[i]);
7105 }
7106 }
7107 }
7108 if (canPivot) {
7109 // update lower, upper, objective and nonLinearCost
7110 assert(!rowScale_); // for now
7111 memcpy(lower_, columnLower_, numberColumns_ * sizeof(double));
7112 memcpy(lower_ + numberColumns_, rowLower_, numberRows_ * sizeof(double));
7113 memcpy(upper_, columnUpper_, numberColumns_ * sizeof(double));
7114 memcpy(upper_ + numberColumns_, rowUpper_, numberRows_ * sizeof(double));
7115 memcpy(cost_, objective(), numberColumns_ * sizeof(double));
7116 memset(cost_ + numberColumns_, 0, numberRows_ * sizeof(double));
7117 // ? parameter to say no gutsOfSolution needed
7118 // make sure slacks have correct value
7119 // see if still optimal
7120 if (returnCode == 100) {
7121 // is this needed
7122 if (nonLinearCost_) {
7123 // speed up later
7124 //nonLinearCost_->checkInfeasibilities(oldTolerance);
7125 delete nonLinearCost_;
7126 nonLinearCost_ = new ClpNonLinearCost(this);
7127 }
7128 gutsOfSolution(NULL, NULL, false);
7129 assert(!newStatus);
7130 printf("%d primal %d dual\n", numberPrimalInfeasibilities_,
7131 numberDualInfeasibilities_);
7132 returnCode = 3;
7133 } else {
7134 // is this needed
7135 if (nonLinearCost_) {
7136 // speed up later
7137 #if 1
7138 for (int i = 0; i < number; i++) {
7139 int iSequence = which[i];
7140 nonLinearCost_->setOne(iSequence, solution_[iSequence],
7141 lower_[iSequence], upper_[iSequence],
7142 cost_[iSequence]);
7143 }
7144 #else
7145 //nonLinearCost_->checkInfeasibilities(oldTolerance);
7146 delete nonLinearCost_;
7147 nonLinearCost_ = new ClpNonLinearCost(this);
7148 //nonLinearCost_->checkInfeasibilities(0.0);
7149 #endif
7150 //gutsOfSolution(NULL,NULL,false);
7151 assert(!newStatus);
7152 }
7153 }
7154 }
7155 return returnCode;
7156 }
7157
7158 /* Pivot out a variable and choose an incoing one. Assumes dual
7159 feasible - will not go through a reduced cost.
7160 Returns step length in theta
7161 Return codes as before but -1 means no acceptable pivot
7162 */
dualPivotResultPart1()7163 int ClpSimplex::dualPivotResultPart1()
7164 {
7165 return static_cast< ClpSimplexDual * >(this)->pivotResultPart1();
7166 }
7167 /* Do actual pivot
7168 state is 1,3 if got tableau column in rowArray_[1]
7169 2,3 if got tableau row in rowArray_[0] and columnArray_[0]
7170 */
pivotResultPart2(int algorithm,int state)7171 int ClpSimplex::pivotResultPart2(int algorithm, int state)
7172 {
7173 if (!(state & 1)) {
7174 // update the incoming column
7175 #ifndef COIN_FAC_NEW
7176 unpackPacked(rowArray_[1]);
7177 #else
7178 unpack(rowArray_[1]);
7179 #endif
7180 factorization_->updateColumnFT(rowArray_[2], rowArray_[1]);
7181 }
7182 #define CHECK_TABLEAU 0
7183 if (!(state & 2) || CHECK_TABLEAU) {
7184 // get tableau row
7185 // create as packed
7186 double direction = directionOut_;
7187 assert(!rowArray_[2]->getNumElements());
7188 assert(!columnArray_[1]->getNumElements());
7189 #if CHECK_TABLEAU
7190 printf("rowArray0 old\n");
7191 rowArray_[0]->print();
7192 rowArray_[0]->clear();
7193 printf("columnArray0 old\n");
7194 columnArray_[0]->print();
7195 columnArray_[0]->clear();
7196 #else
7197 assert(!columnArray_[0]->getNumElements());
7198 assert(!rowArray_[0]->getNumElements());
7199 #endif
7200 #ifndef COIN_FAC_NEW
7201 rowArray_[0]->createPacked(1, &pivotRow_, &direction);
7202 #else
7203 rowArray_[0]->createOneUnpackedElement(pivotRow_, direction);
7204 #endif
7205 factorization_->updateColumnTranspose(rowArray_[2], rowArray_[0]);
7206 rowArray_[3]->clear();
7207 // put row of tableau in rowArray[0] and columnArray[0]
7208 assert(!rowArray_[2]->getNumElements());
7209 matrix_->transposeTimes(this, -1.0,
7210 rowArray_[0], rowArray_[2], columnArray_[0]);
7211 #if CHECK_TABLEAU
7212 printf("rowArray0 new\n");
7213 rowArray_[0]->print();
7214 printf("columnArray0 new\n");
7215 columnArray_[0]->print();
7216 #endif
7217 }
7218 assert(pivotRow_ >= 0);
7219 assert(sequenceIn_ >= 0);
7220 assert(sequenceOut_ >= 0);
7221 int returnCode = -1;
7222 if (algorithm > 0) {
7223 // replace in basis
7224 int updateStatus = factorization_->replaceColumn(this,
7225 rowArray_[2],
7226 rowArray_[1],
7227 pivotRow_,
7228 alpha_);
7229 if (!updateStatus) {
7230 dualIn_ = cost_[sequenceIn_];
7231 double *work = rowArray_[1]->denseVector();
7232 int number = rowArray_[1]->getNumElements();
7233 int *which = rowArray_[1]->getIndices();
7234 for (int i = 0; i < number; i++) {
7235 int iRow = which[i];
7236 #ifndef COIN_FAC_NEW
7237 double alpha = work[i];
7238 #else
7239 double alpha = work[iRow];
7240 #endif
7241 int iPivot = pivotVariable_[iRow];
7242 dualIn_ -= alpha * cost_[iPivot];
7243 }
7244 returnCode = 0;
7245 double multiplier = dualIn_ / alpha_;
7246 // update column djs
7247 int i;
7248 int *index = columnArray_[0]->getIndices();
7249 number = columnArray_[0]->getNumElements();
7250 double *element = columnArray_[0]->denseVector();
7251 assert(columnArray_[0]->packedMode());
7252 for (i = 0; i < number; i++) {
7253 int iSequence = index[i];
7254 dj_[iSequence] += multiplier * element[i];
7255 reducedCost_[iSequence] = dj_[iSequence];
7256 element[i] = 0.0;
7257 }
7258 columnArray_[0]->setNumElements(0);
7259 // and row djs
7260 index = rowArray_[0]->getIndices();
7261 number = rowArray_[0]->getNumElements();
7262 element = rowArray_[0]->denseVector();
7263 #ifndef COIN_FAC_NEW
7264 assert(rowArray_[0]->packedMode());
7265 for (i = 0; i < number; i++) {
7266 int iSequence = index[i];
7267 dj_[iSequence + numberColumns_] += multiplier * element[i];
7268 dual_[iSequence] = dj_[iSequence + numberColumns_];
7269 element[i] = 0.0;
7270 }
7271 #else
7272 assert(!rowArray_[0]->packedMode());
7273 for (i = 0; i < number; i++) {
7274 int iSequence = index[i];
7275 dj_[iSequence + numberColumns_] += multiplier * element[iSequence];
7276 dual_[iSequence] = dj_[iSequence + numberColumns_];
7277 element[iSequence] = 0.0;
7278 }
7279 #endif
7280 rowArray_[0]->setNumElements(0);
7281 double oldCost = cost_[sequenceOut_];
7282 // update primal solution
7283
7284 double objectiveChange = 0.0;
7285 // after this rowArray_[1] is not empty - used to update djs
7286 static_cast< ClpSimplexPrimal * >(this)->updatePrimalsInPrimal(rowArray_[1], theta_, objectiveChange, 0);
7287 double oldValue = valueIn_;
7288 if (directionIn_ == -1) {
7289 // as if from upper bound
7290 if (sequenceIn_ != sequenceOut_) {
7291 // variable becoming basic
7292 valueIn_ -= fabs(theta_);
7293 } else {
7294 valueIn_ = lowerIn_;
7295 }
7296 } else {
7297 // as if from lower bound
7298 if (sequenceIn_ != sequenceOut_) {
7299 // variable becoming basic
7300 valueIn_ += fabs(theta_);
7301 } else {
7302 valueIn_ = upperIn_;
7303 }
7304 }
7305 objectiveChange += dualIn_ * (valueIn_ - oldValue);
7306 // outgoing
7307 if (sequenceIn_ != sequenceOut_) {
7308 if (directionOut_ > 0) {
7309 valueOut_ = lowerOut_;
7310 } else {
7311 valueOut_ = upperOut_;
7312 }
7313 if (valueOut_ < lower_[sequenceOut_] - primalTolerance_)
7314 valueOut_ = lower_[sequenceOut_] - 0.9 * primalTolerance_;
7315 else if (valueOut_ > upper_[sequenceOut_] + primalTolerance_)
7316 valueOut_ = upper_[sequenceOut_] + 0.9 * primalTolerance_;
7317 // may not be exactly at bound and bounds may have changed
7318 // Make sure outgoing looks feasible
7319 directionOut_ = nonLinearCost_->setOneOutgoing(sequenceOut_, valueOut_);
7320 // May have got inaccurate
7321 //if (oldCost!=cost_[sequenceOut_])
7322 //printf("costchange on %d from %g to %g\n",sequenceOut_,
7323 // oldCost,cost_[sequenceOut_]);
7324 dj_[sequenceOut_] = cost_[sequenceOut_] - oldCost; // normally updated next iteration
7325 solution_[sequenceOut_] = valueOut_;
7326 }
7327 // change cost and bounds on incoming if primal
7328 nonLinearCost_->setOne(sequenceIn_, valueIn_);
7329 progress_.startCheck(); // make sure won't worry about cycling
7330 int whatNext = housekeeping(objectiveChange);
7331 if (whatNext == 1) {
7332 returnCode = -2; // refactorize
7333 } else if (whatNext == 2) {
7334 // maximum iterations or equivalent
7335 returnCode = 3;
7336 } else if (numberIterations_ == lastGoodIteration_ + 2 * factorization_->maximumPivots()) {
7337 // done a lot of flips - be safe
7338 returnCode = -2; // refactorize
7339 }
7340 } else {
7341 // ?
7342 abort();
7343 }
7344 } else {
7345 // dual
7346 // recompute dualOut_
7347 if (directionOut_ < 0) {
7348 dualOut_ = valueOut_ - upperOut_;
7349 } else {
7350 dualOut_ = lowerOut_ - valueOut_;
7351 }
7352 // update the incoming column
7353 double btranAlpha = -alpha_ * directionOut_; // for check
7354 rowArray_[1]->clear();
7355 #ifndef COIN_FAC_NEW
7356 unpackPacked(rowArray_[1]);
7357 #else
7358 unpack(rowArray_[1]);
7359 #endif
7360 // moved into updateWeights - factorization_->updateColumnFT(rowArray_[2],rowArray_[1]);
7361 // and update dual weights (can do in parallel - with extra array)
7362 alpha_ = dualRowPivot_->updateWeights(rowArray_[0],
7363 rowArray_[2],
7364 rowArray_[3],
7365 rowArray_[1]);
7366 // see if update stable
7367 #ifdef CLP_DEBUG
7368 if ((handler_->logLevel() & 32))
7369 printf("btran alpha %g, ftran alpha %g\n", btranAlpha, alpha_);
7370 #endif
7371 double checkValue = 1.0e-7;
7372 // if can't trust much and long way from optimal then relax
7373 if (largestPrimalError_ > 10.0)
7374 checkValue = CoinMin(1.0e-4, 1.0e-8 * largestPrimalError_);
7375 if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > checkValue * (1.0 + fabs(alpha_))) {
7376 handler_->message(CLP_DUAL_CHECK, messages_)
7377 << btranAlpha
7378 << alpha_
7379 << CoinMessageEol;
7380 if (factorization_->pivots()) {
7381 dualRowPivot_->unrollWeights();
7382 problemStatus_ = -2; // factorize now
7383 rowArray_[0]->clear();
7384 rowArray_[1]->clear();
7385 columnArray_[0]->clear();
7386 returnCode = -2;
7387 abort();
7388 return returnCode;
7389 } else {
7390 // take on more relaxed criterion
7391 double test;
7392 if (fabs(btranAlpha) < 1.0e-8 || fabs(alpha_) < 1.0e-8)
7393 test = 1.0e-1 * fabs(alpha_);
7394 else
7395 test = 1.0e-4 * (1.0 + fabs(alpha_));
7396 if (fabs(btranAlpha) < 1.0e-12 || fabs(alpha_) < 1.0e-12 || fabs(btranAlpha - alpha_) > test) {
7397 abort();
7398 }
7399 }
7400 }
7401 // update duals BEFORE replaceColumn so can do updateColumn
7402 double objectiveChange = 0.0;
7403 // do duals first as variables may flip bounds
7404 // rowArray_[0] and columnArray_[0] may have flips
7405 // so use rowArray_[3] for work array from here on
7406 int nswapped = 0;
7407 //rowArray_[0]->cleanAndPackSafe(1.0e-60);
7408 //columnArray_[0]->cleanAndPackSafe(1.0e-60);
7409 // make sure incoming doesn't count
7410 Status saveStatus = getStatus(sequenceIn_);
7411 setStatus(sequenceIn_, basic);
7412 nswapped = static_cast< ClpSimplexDual * >(this)->updateDualsInDual(rowArray_[0], columnArray_[0],
7413 rowArray_[2], theta_,
7414 objectiveChange, false);
7415 assert(!nswapped);
7416 setStatus(sequenceIn_, saveStatus);
7417 double oldDualOut = dualOut_;
7418 // which will change basic solution
7419 if (nswapped) {
7420 if (rowArray_[2]->getNumElements()) {
7421 factorization_->updateColumn(rowArray_[3], rowArray_[2]);
7422 dualRowPivot_->updatePrimalSolution(rowArray_[2],
7423 1.0, objectiveChange);
7424 }
7425 // recompute dualOut_
7426 valueOut_ = solution_[sequenceOut_];
7427 if (directionOut_ < 0) {
7428 dualOut_ = valueOut_ - upperOut_;
7429 } else {
7430 dualOut_ = lowerOut_ - valueOut_;
7431 }
7432 }
7433 // amount primal will move
7434 double movement = -dualOut_ * directionOut_ / alpha_;
7435 double movementOld = oldDualOut * directionOut_ / alpha_;
7436 // so objective should increase by fabs(dj)*movement
7437 // but we already have objective change - so check will be good
7438 if (objectiveChange + fabs(movementOld * dualIn_) < -CoinMax(1.0e-5, 1.0e-12 * fabs(objectiveValue_))) {
7439 if (handler_->logLevel() & 32)
7440 printf("movement %g, swap change %g, rest %g * %g\n",
7441 objectiveChange + fabs(movement * dualIn_),
7442 objectiveChange, movement, dualIn_);
7443 }
7444 // if stable replace in basis
7445 int updateStatus = factorization_->replaceColumn(this,
7446 rowArray_[2],
7447 rowArray_[1],
7448 pivotRow_,
7449 alpha_);
7450 // If looks like bad pivot - refactorize
7451 if (fabs(dualOut_) > 1.0e50)
7452 updateStatus = 2;
7453 // if no pivots, bad update but reasonable alpha - take and invert
7454 if (updateStatus == 2 && !factorization_->pivots() && fabs(alpha_) > 1.0e-5)
7455 updateStatus = 4;
7456 if (updateStatus == 1 || updateStatus == 4) {
7457 // slight error
7458 if (factorization_->pivots() > 5 || updateStatus == 4) {
7459 problemStatus_ = -2; // factorize now
7460 returnCode = -3;
7461 }
7462 } else if (updateStatus == 2) {
7463 // major error
7464 dualRowPivot_->unrollWeights();
7465 // later we may need to unwind more e.g. fake bounds
7466 if (factorization_->pivots() && ((moreSpecialOptions_ & 16) == 0 || factorization_->pivots() > 4)) {
7467 problemStatus_ = -2; // factorize now
7468 returnCode = -2;
7469 moreSpecialOptions_ |= 16;
7470 return returnCode;
7471 } else {
7472 // need to reject something
7473 abort();
7474 }
7475 } else if (updateStatus == 3) {
7476 // out of memory
7477 // increase space if not many iterations
7478 if (factorization_->pivots() < 0.5 * factorization_->maximumPivots() && factorization_->pivots() < 200)
7479 factorization_->areaFactor(
7480 factorization_->areaFactor() * 1.1);
7481 problemStatus_ = -2; // factorize now
7482 } else if (updateStatus == 5) {
7483 problemStatus_ = -2; // factorize now
7484 }
7485 // update primal solution
7486 if (theta_ < 0.0) {
7487 if (handler_->logLevel() & 32)
7488 printf("negative theta %g\n", theta_);
7489 theta_ = 0.0;
7490 }
7491 // do actual flips (should not be any?)
7492 static_cast< ClpSimplexDual * >(this)->flipBounds(rowArray_[0], columnArray_[0]);
7493 //rowArray_[1]->expand();
7494 dualRowPivot_->updatePrimalSolution(rowArray_[1],
7495 movement,
7496 objectiveChange);
7497 // modify dualout
7498 dualOut_ /= alpha_;
7499 dualOut_ *= -directionOut_;
7500 //setStatus(sequenceIn_,basic);
7501 dj_[sequenceIn_] = 0.0;
7502 double oldValue = valueIn_;
7503 if (directionIn_ == -1) {
7504 // as if from upper bound
7505 valueIn_ = upperIn_ + dualOut_;
7506 } else {
7507 // as if from lower bound
7508 valueIn_ = lowerIn_ + dualOut_;
7509 }
7510 objectiveChange += cost_[sequenceIn_] * (valueIn_ - oldValue);
7511 // outgoing
7512 // set dj to zero unless values pass
7513 if (directionOut_ > 0) {
7514 valueOut_ = lowerOut_;
7515 dj_[sequenceOut_] = theta_;
7516 } else {
7517 valueOut_ = upperOut_;
7518 dj_[sequenceOut_] = -theta_;
7519 }
7520 solution_[sequenceOut_] = valueOut_;
7521 int whatNext = housekeeping(objectiveChange);
7522 // and set bounds correctly
7523 static_cast< ClpSimplexDual * >(this)->originalBound(sequenceIn_);
7524 static_cast< ClpSimplexDual * >(this)->changeBound(sequenceOut_);
7525 if (whatNext == 1) {
7526 problemStatus_ = -2; // refactorize
7527 } else if (whatNext == 2) {
7528 // maximum iterations or equivalent
7529 problemStatus_ = 3;
7530 returnCode = 3;
7531 abort();
7532 }
7533 }
7534 // Check event
7535 {
7536 int status = eventHandler_->event(ClpEventHandler::endOfIteration);
7537 if (status >= 0) {
7538 problemStatus_ = 5;
7539 secondaryStatus_ = ClpEventHandler::endOfIteration;
7540 returnCode = 3;
7541 }
7542 }
7543 // need to be able to refactoriza
7544 //printf("return code %d problem status %d\n",
7545 // returnCode,problemStatus_);
7546 return returnCode;
7547 }
7548 #ifdef COIN_SHORT_SORT
7549 #define USE_HASH 1
7550 #else
7551 #define USE_HASH 0
7552 #endif
7553 #if USE_HASH == 2
7554 static const unsigned int mmult[] = {
7555 262139, 259459, 256889, 254291, 251701, 249133, 246709, 244247
7556 };
7557 // Returns a hash value
7558 inline unsigned int
hashValue(double value,unsigned int maxHash)7559 hashValue(double value, unsigned int maxHash)
7560 {
7561 const char *name = reinterpret_cast< char * >(&value);
7562 unsigned int n = 0;
7563 for (int j = 0; j < 8; ++j) {
7564 n += mmult[j] * name[j];
7565 }
7566 return (n % maxHash);
7567 }
7568 /*
7569 */
sameTogether(unsigned int nin,int * which,double * weights,int * which2,double * weights2,unsigned int * hash)7570 static int sameTogether(unsigned int nin, int *which, double *weights,
7571 int *which2, double *weights2, unsigned int *hash)
7572 {
7573 if (nin <= 1)
7574 return nin;
7575 // move up and fill hash
7576 unsigned int maxHash = 4 * nin;
7577 memset(hash, 0xf0, maxHash * sizeof(int));
7578 int *spare = which2 + maxHash;
7579 int n2 = 0;
7580 unsigned int iNext = hashValue(weights[0], maxHash);
7581 unsigned int endMarker = 0x80000000 + maxHash;
7582 hash[iNext] = endMarker;
7583 unsigned int iLast = iNext;
7584 weights2[iNext] = weights[0];
7585 which2[iNext] = which[0];
7586 for (unsigned int i = 1; i < nin; i++) {
7587 double value = weights[i];
7588 unsigned int ipos = hashValue(value, maxHash);
7589 if (hash[ipos] == 0xf0f0f0f0) {
7590 hash[iLast] = ipos + 0x80000000;
7591 hash[ipos] = endMarker;
7592 weights2[ipos] = value;
7593 which2[ipos] = which[i];
7594 iLast = ipos;
7595 } else {
7596 spare[n2++] = i;
7597 }
7598 }
7599 unsigned int lastSlot = 0;
7600 for (int j = 0; j < n2; ++j) {
7601 int i = spare[j];
7602 double value = weights[i];
7603 unsigned int ipos = hashValue(value, maxHash);
7604 iLast = ipos;
7605 while (hash[ipos] <= 0x80000000) {
7606 iLast = ipos;
7607 ipos = hash[ipos];
7608 }
7609 while (hash[lastSlot] != 0xf0f0f0f0)
7610 lastSlot++;
7611 assert(lastSlot < maxHash);
7612 hash[lastSlot] = hash[ipos];
7613 hash[iLast] = lastSlot;
7614 weights2[lastSlot] = value;
7615 which2[lastSlot] = which[i];
7616 }
7617 int put = 0;
7618 //unsigned int iNext=0;
7619 int savePut = 0;
7620 while (iNext != maxHash) {
7621 weights[put] = weights2[iNext];
7622 assert(iNext < maxHash);
7623 which[put++] = which2[iNext];
7624 iNext = hash[iNext];
7625 if (iNext > 0x7fffffff) {
7626 // end
7627 if (put > savePut + 1) {
7628 CoinShortSort_2(weights + savePut, weights + put, which + savePut);
7629 // keep
7630 #if 0
7631 printf("DUP2 value %g ",weights[savePut]);
7632 for (int i=savePut;i<put;i++)
7633 printf("%d (%g) ",which[i],weights[i]);
7634 printf("\n");
7635 #endif
7636 savePut = put;
7637 } else {
7638 // no
7639 put = savePut;
7640 }
7641 iNext -= 0x80000000;
7642 }
7643 }
7644 return savePut;
7645 }
7646 #endif
7647 #include "CoinPresolveMatrix.hpp"
7648 /* Take out duplicate rows (includes scaled rows and intersections).
7649 On exit whichRows has rows to delete - return code is number can be deleted
7650 or -1 if would be infeasible.
7651 If tolerance is -1.0 use primalTolerance for equality rows and infeasibility
7652 If cleanUp not zero then spend more time trying to leave more stable row
7653 and make row bounds exact multiple of cleanUp if close enough
7654 moves status to try and delete a basic slack
7655 */
outDuplicateRows(int numberLook,int * whichRows,bool noOverlaps,double tolerance,double cleanUp)7656 int ClpSimplex::outDuplicateRows(int numberLook, int *whichRows, bool noOverlaps,
7657 double tolerance, double cleanUp)
7658 {
7659 #if USE_HASH < 2
7660 double *weights = new double[numberLook + numberColumns_];
7661 #else
7662 int numberAlloc = 5 * numberLook + numberColumns_ + ((9 * numberLook + 1) / (sizeof(double) / sizeof(int)));
7663 double *weights = new double[numberAlloc];
7664 double *weights2 = weights + numberLook + numberColumns_;
7665 #endif
7666 double *columnWeights = weights + numberLook;
7667 #ifndef COIN_REUSE_RANDOM
7668 coin_init_random_vec(columnWeights, numberColumns_);
7669 #else
7670 for (int i = 0; i < numberColumns_; i++)
7671 columnWeights[i] = randomNumberGenerator_.randomDouble();
7672 #endif
7673 #if USE_HASH == 1
7674 typedef struct {
7675 #define INTEL // need way to find out at compile time
7676 #ifdef INTEL
7677 int which;
7678 float value;
7679 #else
7680 float value;
7681 int which;
7682 #endif
7683 } hash_1;
7684 typedef struct {
7685 union {
7686 double d;
7687 hash_1 hash;
7688 } item;
7689 } hash;
7690 assert(sizeof(double) == 8);
7691 hash *hashWeights = reinterpret_cast< hash * >(weights);
7692 #endif
7693 #if 0
7694 int counts[5]={0,0,0,0,0};
7695 int countsEq[5]={0,0,0,0,0};
7696 #endif
7697 // get row copy
7698 CoinPackedMatrix rowCopy = *matrix();
7699 rowCopy.reverseOrdering();
7700 int *column = rowCopy.getMutableIndices();
7701 CoinBigIndex *rowStart = rowCopy.getMutableVectorStarts();
7702 int *rowLength = rowCopy.getMutableVectorLengths();
7703 double *element = rowCopy.getMutableElements();
7704 //double wwww[200];
7705 //assert (numberLook<=200);
7706 //int iiii[200];
7707 for (int i = 0; i < numberLook; i++) {
7708 int iRow = whichRows[i];
7709 double value = 0.0;
7710 CoinBigIndex start = rowStart[iRow];
7711 CoinBigIndex end = start + rowLength[iRow];
7712 // sort (probably in order anyway)
7713 #ifdef COIN_SHORT_SORT
7714 CoinShortSort_2(column + start, column + end, element + start);
7715 #else
7716 CoinSort_2(column + start, column + end, element + start);
7717 #endif
7718 for (CoinBigIndex j = start; j < end; j++) {
7719 int iColumn = column[j];
7720 value += columnWeights[iColumn];
7721 }
7722 #if USE_HASH == 1
7723 //printf("iLook %d weight %g (before)\n",i,value);
7724 hash temp;
7725 temp.item.d = value;
7726 temp.item.hash.which = iRow;
7727 hashWeights[i] = temp;
7728 //wwww[i]=value;
7729 //iiii[i]=iRow;
7730 #else
7731 weights[i] = value;
7732 #endif
7733 }
7734 //#define PRINT_DUP
7735 #if USE_HASH == 0
7736 #if 0
7737 if (false) {
7738 double * w =CoinCopyOfArray(weights,numberLook);
7739 int * ind = CoinCopyOfArray(whichRows,numberLook);
7740 double * weights2=new double[50000];
7741 int * which2 = reinterpret_cast<int *>(weights2+4*numberLook);
7742 unsigned int * hash = reinterpret_cast<unsigned int *>(which2+5*numberLook);
7743 int n=sameTogether(numberLook,ind,w,which2,weights2,hash);
7744 printf("Reduced length of %d\n",n);
7745 delete [] weights2;
7746 delete [] w;
7747 delete [] ind;
7748 }
7749 #endif
7750 CoinSort_2(weights, weights + numberLook, whichRows);
7751 #if 0
7752 {
7753 double value = weights[0];
7754 int firstSame=-1;
7755 int lastSame=-1;
7756 for (int iLook = 1; iLook < numberLook; iLook++) {
7757 if (weights[iLook]==value) {
7758 if (firstSame<0) {
7759 /* see how many same - if >2 but < ? may be
7760 worth looking at all combinations
7761 */
7762 firstSame=iLook-1;
7763 printf("DUPS weight %g first row %d ",value,whichRows[firstSame]);
7764 for (lastSame=iLook;lastSame<numberLook;lastSame++) {
7765 if (weights[lastSame]!=value)
7766 break;
7767 else
7768 printf(", %d ",whichRows[lastSame]);
7769 }
7770 printf("\n");
7771 //printf("dupsame %d rows have same weight",lastSame-firstSame);
7772 }
7773 } else {
7774 firstSame=-1;
7775 value=weights[iLook];
7776 }
7777 }
7778 }
7779 #endif
7780 #elif USE_HASH == 1
7781 std::sort(weights, weights + numberLook);
7782 #ifdef PRINT_DUP
7783 //CoinSort_2(wwww,wwww+numberLook,iiii);
7784 for (int i = 0; i < numberLook; i++) {
7785 hash *temp = reinterpret_cast< hash * >(weights + i);
7786 whichRows[i] = temp->item.hash.which;
7787 weights[i] = temp->item.hash.value;
7788 //printf("iLook %d weight %g (after) - true %d %g\n",
7789 // whichRows[i],weights[i],iiii[i],wwww[i]);
7790 }
7791 #undef USE_HASH
7792 #define USE_HASH 0
7793 #endif
7794 #else
7795 int *which2 = reinterpret_cast< int * >(weights2 + 4 * numberLook);
7796 unsigned int *hash = reinterpret_cast< unsigned int * >(which2 + 5 * numberLook);
7797 numberLook = sameTogether(numberLook, whichRows, weights, which2, weights2, hash);
7798 printf("Reduced length of %d\n", numberLook);
7799 #endif
7800 if (tolerance < 0.0)
7801 tolerance = primalTolerance_;
7802 int nPossible = 0;
7803 int nDelete = 0;
7804 #if USE_HASH == 1
7805 hash *temp = reinterpret_cast< hash * >(weights);
7806 int iLast = temp->item.hash.which;
7807 float value = temp->item.hash.value;
7808 #else
7809 double value = weights[0];
7810 int iLast = whichRows[0];
7811 #endif
7812 double inverseCleanup = (cleanUp > 0.0) ? 1.0 / cleanUp : 0.0;
7813 //#define PRINT_DUP
7814 #ifdef PRINT_DUP
7815 int firstSame = -1;
7816 int lastSame = -1;
7817 #endif
7818 for (int iLook = 1; iLook < numberLook; iLook++) {
7819 #if USE_HASH == 1
7820 hash *temp = reinterpret_cast< hash * >(weights + iLook);
7821 int iThis = temp->item.hash.which;
7822 float valueThis = temp->item.hash.value;
7823 #else
7824 int iThis = whichRows[iLook];
7825 double valueThis = weights[iLook];
7826 #endif
7827 if (valueThis == value) {
7828 #ifdef PRINT_DUP
7829 if (firstSame < 0) {
7830 /* see how many same - if >2 but < ? may be
7831 worth looking at all combinations
7832 */
7833 firstSame = iLook - 1;
7834 printf("DUPS weight %g first row %d ", value, whichRows[firstSame]);
7835 for (lastSame = iLook; lastSame < numberLook; lastSame++) {
7836 if (weights[lastSame] != value)
7837 break;
7838 else
7839 printf(", %d ", whichRows[lastSame]);
7840 }
7841 printf("\n");
7842 #endif
7843 CoinBigIndex start = rowStart[iThis];
7844 CoinBigIndex end = start + rowLength[iThis];
7845 if (rowLength[iThis] == rowLength[iLast]) {
7846 nPossible++;
7847 #ifdef PRINT_DUP
7848 char line[520], temp[50];
7849 #endif
7850 CoinBigIndex ishift = rowStart[iLast] - start;
7851 CoinBigIndex k;
7852 #ifdef PRINT_DUP
7853 sprintf(line, "dupj %d,%d %d els ",
7854 iThis, iLast, rowLength[iLast]);
7855 int n = strlen(line);
7856 #endif
7857 bool bad = false;
7858 double multiplier = 0.0;
7859 for (k = start; k < end; k++) {
7860 if (column[k] != column[k + ishift]) {
7861 bad = true;
7862 break;
7863 } else {
7864 #ifdef PRINT_DUP
7865 sprintf(temp, "(%g,%g) ", element[k], element[k + ishift]);
7866 #endif
7867 if (!multiplier) {
7868 multiplier = element[k] / element[k + ishift];
7869 } else if (fabs(element[k + ishift] * multiplier - element[k]) > 1.0e-8) {
7870 bad = true;
7871 }
7872 #ifdef PRINT_DUP
7873 int n2 = strlen(temp);
7874 if (n + n2 < 500) {
7875 strcat(line, temp);
7876 n += n2;
7877 } else {
7878 strcat(line, "...");
7879 break;
7880 }
7881 #endif
7882 }
7883 }
7884 if (!bad) {
7885 #ifdef PRINT_DUP
7886 printf("%s lo (%g,%g) up (%g,%g) - multiplier %g\n", line, rowLower_[iThis], rowUpper_[iThis],
7887 rowLower_[iLast], rowUpper_[iLast], multiplier);
7888 #endif
7889 double rlo1 = rowLower_[iLast];
7890 double rup1 = rowUpper_[iLast];
7891 double rlo2 = rowLower_[iThis];
7892 double rup2 = rowUpper_[iThis];
7893 // scale
7894 rlo1 *= multiplier;
7895 rup1 *= multiplier;
7896 //swap bounds if neg
7897 if (multiplier < 0.0) {
7898 double temp = rup1;
7899 rup1 = rlo1;
7900 rlo1 = temp;
7901 }
7902 /* now check rhs to see what is what */
7903 #ifdef PRINT_DUP
7904 printf("duplicate row %g %g, %g %g\n",
7905 rlo1, rup1, rlo2, rup2);
7906 #endif
7907 if (!noOverlaps) {
7908 /* we always keep this and delete last
7909 later maybe keep better formed one */
7910 rlo2 = CoinMax(rlo1, rlo2);
7911 if (rlo2 < -1.0e30)
7912 rlo2 = -COIN_DBL_MAX;
7913 rup2 = CoinMin(rup1, rup2);
7914 if (rup2 > 1.0e30)
7915 rup2 = COIN_DBL_MAX;
7916 } else {
7917 /* keep better formed one */
7918 if (rlo2 >= rlo1 - 1.0e-8 && rup2 <= rup1 + 1.0e-8) {
7919 // ok
7920 rlo2 = CoinMax(rlo1, rlo2);
7921 if (rlo2 < -1.0e30)
7922 rlo2 = -COIN_DBL_MAX;
7923 rup2 = CoinMin(rup1, rup2);
7924 if (rup2 > 1.0e30)
7925 rup2 = COIN_DBL_MAX;
7926 } else if (rlo1 >= rlo2 - 1.0e-8 && rup1 <= rup2 + 1.0e-8) {
7927 rlo2 = CoinMax(rlo1, rlo2);
7928 if (rlo2 < -1.0e30)
7929 rlo2 = -COIN_DBL_MAX;
7930 rup2 = CoinMin(rup1, rup2);
7931 if (rup2 > 1.0e30)
7932 rup2 = COIN_DBL_MAX;
7933 // swap
7934 int temp = iLast;
7935 iLast = iThis;
7936 iThis = temp;
7937 } else {
7938 // leave (for now)
7939 #if DEBUG_SOME > 0
7940 printf("row %d %g %g row %d %g %g\n", iLast, rlo1, rup1, iThis, rlo2, rup2);
7941 #endif
7942 iLast = iThis;
7943 continue;
7944 }
7945 }
7946 #ifdef PRINT_DUP
7947 printf("pre_duprow %dR %dR keep this\n", iLast, iThis);
7948 #endif
7949 #if 0
7950 if (rowLength[iThis]<4)
7951 counts[rowLength[iThis]]++;
7952 else
7953 counts[4]++;
7954 #endif
7955 if (rup2 < rlo2 - tolerance) {
7956 // infeasible
7957 nDelete = -1;
7958 break;
7959 } else if (fabs(rup2 - rlo2) <= tolerance) {
7960 // equal - choose closer to zero
7961 if (fabs(rup2) < fabs(rlo2))
7962 rlo2 = rup2;
7963 else
7964 rup2 = rlo2;
7965 #if 0
7966 if (rowLength[iThis]<4)
7967 countsEq[rowLength[iThis]]++;
7968 else
7969 countsEq[4]++;
7970 #endif
7971 #ifdef PRINT_DUP
7972 printf("Row %d has %d elements == %g\n",
7973 iThis, end - start, rlo2);
7974 #endif
7975 }
7976 if (cleanUp > 0.0) {
7977 /* see if close to multiple
7978 always allow integer values */
7979 if (rlo2 > -1.0e30) {
7980 double value = rlo2;
7981 double value2 = floor(value + 0.5);
7982 if (fabs(value - value2) < 1.0e-9) {
7983 rlo2 = value2;
7984 } else {
7985 value = rlo2 * inverseCleanup;
7986 value2 = floor(value + 0.5);
7987 if (fabs(value - value2) < 1.0e-9)
7988 rlo2 = value2 * cleanUp;
7989 }
7990 }
7991 if (rup2 < 1.0e30) {
7992 double value = rup2;
7993 double value2 = floor(value + 0.5);
7994 if (fabs(value - value2) < 1.0e-9) {
7995 rup2 = value2;
7996 } else {
7997 value = rup2 * inverseCleanup;
7998 value2 = floor(value + 0.5);
7999 if (fabs(value - value2) < 1.0e-9)
8000 rup2 = value2 * cleanUp;
8001 }
8002 }
8003 }
8004 rowLower_[iThis] = rlo2;
8005 rowUpper_[iThis] = rup2;
8006 whichRows[nDelete++] = iLast;
8007 if (getRowStatus(iLast) != basic) {
8008 if (getRowStatus(iThis) == basic) {
8009 setRowStatus(iThis, superBasic);
8010 setRowStatus(iLast, basic);
8011 }
8012 }
8013 } else {
8014 #ifdef PRINT_DUP
8015 printf("%s lo (%g,%g) up (%g,%g) - ODD\n", line, rowLower_[iThis], rowUpper_[iThis],
8016 rowLower_[iLast], rowUpper_[iLast]);
8017 #endif
8018 }
8019 }
8020 } else {
8021 #ifdef PRINT_DUP
8022 // say no match
8023 firstSame = -1;
8024 #endif
8025 value = valueThis;
8026 }
8027 iLast = iThis;
8028 }
8029 #ifdef PRINT_DUP
8030 printf("%d possible duplicate rows - deleting %d\n",
8031 nPossible, nDelete);
8032 #endif
8033 #if 0
8034 for (int i=0;i<5;i++) {
8035 if (counts[i])
8036 printf("CC counts %d %d times of which %d were equalities\n",i,counts[i],countsEq[i]);
8037 }
8038 #endif
8039 delete[] weights;
8040 return nDelete;
8041 }
8042 /* Try simple crash like techniques to get closer to primal feasibility
8043 returns final sum of infeasibilities */
8044 double
8045 ClpSimplex::moveTowardsPrimalFeasible()
8046 {
8047 memset(rowActivity_, 0, numberRows_ * sizeof(double));
8048 matrix()->times(columnActivity_, rowActivity_);
8049 double sum = 0.0;
8050 int *which = new int[numberRows_];
8051 int numberLook = 0;
8052 for (int iRow = 0; iRow < numberRows_; iRow++) {
8053 double value = rowActivity_[iRow];
8054 double infeasibility = 0.0;
8055 if (value < rowLower_[iRow] - primalTolerance_)
8056 infeasibility = rowLower_[iRow] - value;
8057 else if (value > rowUpper_[iRow] + primalTolerance_)
8058 infeasibility = value - rowUpper_[iRow];
8059 if (infeasibility) {
8060 sum += infeasibility;
8061 which[numberLook++] = iRow;
8062 }
8063 }
8064 if (numberLook) {
8065 const int *row = matrix_->getIndices();
8066 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
8067 const int *columnLength = matrix_->getVectorLengths();
8068 const double *element = matrix_->getElements();
8069 // get row copy
8070 CoinPackedMatrix rowCopy = *matrix();
8071 rowCopy.reverseOrdering();
8072 const int *column = rowCopy.getIndices();
8073 const CoinBigIndex *rowStart = rowCopy.getVectorStarts();
8074 const int *rowLength = rowCopy.getVectorLengths();
8075 const double *elementByRow = rowCopy.getElements();
8076 double lastSum = COIN_DBL_MAX;
8077 while (sum > primalTolerance_ && numberLook) {
8078 sum = 0.0;
8079 double worst = primalTolerance_;
8080 int iWorst = -1;
8081 int n = numberLook;
8082 numberLook = 0;
8083 for (int iLook = 0; iLook < n; iLook++) {
8084 int iRow = which[iLook];
8085 double value = rowActivity_[iRow];
8086 double infeasibility = 0.0;
8087 if (value < rowLower_[iRow] - primalTolerance_)
8088 infeasibility = rowLower_[iRow] - value;
8089 else if (value > rowUpper_[iRow] + primalTolerance_)
8090 infeasibility = value - rowUpper_[iRow];
8091 if (infeasibility) {
8092 sum += infeasibility;
8093 which[numberLook++] = iRow;
8094 if (infeasibility > worst) {
8095 worst = infeasibility;
8096 iWorst = iRow;
8097 }
8098 }
8099 }
8100 if (sum == 0.0 || sum >= lastSum - 1.0e-8)
8101 break;
8102 lastSum = sum;
8103 double direction;
8104 if (rowActivity_[iWorst] < rowLower_[iWorst])
8105 direction = 1.0; // increase
8106 else
8107 direction = -1.0;
8108 for (CoinBigIndex k = rowStart[iWorst];
8109 k < rowStart[iWorst] + rowLength[iWorst]; k++) {
8110 if (worst < primalTolerance_)
8111 break;
8112 int iColumn = column[k];
8113 double value = elementByRow[k] * direction;
8114 double distance = worst;
8115 double multiplier = (value > 0.0) ? 1.0 : -1.0;
8116 // but allow for column bounds
8117 double currentValue = columnActivity_[iColumn];
8118 if (multiplier > 0.0)
8119 distance = CoinMin(worst, columnUpper_[iColumn] - currentValue);
8120 else
8121 distance = CoinMin(worst, currentValue - columnLower_[iColumn]);
8122 distance /= fabs(value);
8123 for (CoinBigIndex i = columnStart[iColumn];
8124 i < columnStart[iColumn] + columnLength[iColumn]; i++) {
8125 int iRow = row[i];
8126 if (iRow != iWorst) {
8127 double value2 = element[i] * multiplier;
8128 if (value2 > 0.0) {
8129 double distance2 = rowUpper_[iRow] - rowActivity_[iRow];
8130 if (value2 * distance > distance2)
8131 distance = distance2 / value2;
8132 } else {
8133 double distance2 = rowLower_[iRow] - rowActivity_[iRow];
8134 if (value2 * distance < distance2)
8135 distance = distance2 / value2;
8136 }
8137 }
8138 }
8139 if (distance > 1.0e-12) {
8140 worst -= distance * fabs(value);
8141 distance *= multiplier;
8142 columnActivity_[iColumn] = currentValue + distance;
8143 for (CoinBigIndex i = columnStart[iColumn];
8144 i < columnStart[iColumn] + columnLength[iColumn]; i++) {
8145 int iRow = row[i];
8146 rowActivity_[iRow] += distance * element[i];
8147 }
8148 }
8149 }
8150 }
8151 }
8152 delete[] which;
8153 return sum;
8154 }
8155 /* Try simple crash like techniques to remove super basic slacks
8156 but only if > threshold */
8157 void
8158 ClpSimplex::removeSuperBasicSlacks(int threshold)
8159 {
8160 // could try going both ways - for first attempt to nearer bound
8161 memset(rowActivity_, 0, numberRows_ * sizeof(double));
8162 matrix()->times(columnActivity_, rowActivity_);
8163 double *distance = new double[numberRows_];
8164 int *whichRows = new int[numberRows_];
8165 int numberLook = 0;
8166 for (int iRow = 0; iRow < numberRows_; iRow++) {
8167 if (getRowStatus(iRow) != basic) {
8168 double value = rowActivity_[iRow];
8169 if (value > rowLower_[iRow] + primalTolerance_ && value < rowUpper_[iRow] - primalTolerance_) {
8170 setRowStatus(iRow, superBasic);
8171 distance[numberLook] = CoinMin(value - rowLower_[iRow],
8172 rowUpper_[iRow] - value);
8173 whichRows[numberLook++] = iRow;
8174 }
8175 }
8176 }
8177 if (numberLook > threshold) {
8178 CoinSort_2(distance, distance + numberLook, whichRows);
8179 const int *row = matrix_->getIndices();
8180 const CoinBigIndex *columnStart = matrix_->getVectorStarts();
8181 const int *columnLength = matrix_->getVectorLengths();
8182 const double *element = matrix_->getElements();
8183 // get row copy
8184 CoinPackedMatrix rowCopy = *matrix();
8185 rowCopy.reverseOrdering();
8186 const int *column = rowCopy.getIndices();
8187 const CoinBigIndex *rowStart = rowCopy.getVectorStarts();
8188 const int *rowLength = rowCopy.getVectorLengths();
8189 const double *elementByRow = rowCopy.getElements();
8190 int nMoved = 0;
8191 for (int iLook = 0; iLook < numberLook; iLook++) {
8192 int kRow = whichRows[iLook];
8193 double direction;
8194 double needed;
8195 if (rowUpper_[kRow] - rowActivity_[kRow] < rowActivity_[kRow] - rowLower_[kRow]) {
8196 direction = 1.0; // increase
8197 needed = rowUpper_[kRow] - rowActivity_[kRow];
8198 } else {
8199 direction = -1.0;
8200 needed = rowActivity_[kRow] - rowLower_[kRow];
8201 }
8202 for (CoinBigIndex k = rowStart[kRow];
8203 k < rowStart[kRow] + rowLength[kRow]; k++) {
8204 if (needed < primalTolerance_)
8205 break;
8206 int iColumn = column[k];
8207 if (getColumnStatus(iColumn) != basic)
8208 continue;
8209 double value = elementByRow[k] * direction;
8210 double distance;
8211 double multiplier = (value > 0.0) ? 1.0 : -1.0;
8212 // but allow for column bounds
8213 double currentValue = columnActivity_[iColumn];
8214 if (multiplier > 0.0)
8215 distance = columnUpper_[iColumn] - currentValue;
8216 else
8217 distance = currentValue - columnLower_[iColumn];
8218 for (CoinBigIndex i = columnStart[iColumn];
8219 i < columnStart[iColumn] + columnLength[iColumn]; i++) {
8220 int iRow = row[i];
8221 double value2 = element[i] * multiplier;
8222 if (value2 > 0.0) {
8223 double distance2 = rowUpper_[iRow] - rowActivity_[iRow];
8224 if (value2 * distance > distance2)
8225 distance = distance2 / value2;
8226 } else {
8227 double distance2 = rowLower_[iRow] - rowActivity_[iRow];
8228 if (value2 * distance < distance2)
8229 distance = distance2 / value2;
8230 }
8231 }
8232 if (distance > 1.0e-12) {
8233 distance *= multiplier;
8234 columnActivity_[iColumn] = currentValue + distance;
8235 for (CoinBigIndex i = columnStart[iColumn];
8236 i < columnStart[iColumn] + columnLength[iColumn]; i++) {
8237 int iRow = row[i];
8238 rowActivity_[iRow] += distance * element[i];
8239 }
8240 if (direction > 0.0) {
8241 needed = rowUpper_[kRow] - rowActivity_[kRow];
8242 } else {
8243 needed = rowActivity_[kRow] - rowLower_[kRow];
8244 }
8245 }
8246 }
8247 if (needed < primalTolerance_) {
8248 nMoved++;
8249 if (rowUpper_[kRow] - rowActivity_[kRow] < primalTolerance_)
8250 setRowStatus(kRow, atUpperBound);
8251 else if (rowActivity_[kRow] - rowLower_[kRow] < primalTolerance_)
8252 setRowStatus(kRow, atLowerBound);
8253 else
8254 assert(rowUpper_[kRow] - rowActivity_[kRow] < primalTolerance_ || rowActivity_[kRow] - rowLower_[kRow] < primalTolerance_);
8255 }
8256 }
8257 char line[100];
8258 sprintf(line, "Threshold %d found %d fixed %d", threshold, numberLook, nMoved);
8259 handler_->message(CLP_GENERAL, messages_)
8260 << line << CoinMessageEol;
8261 }
8262 delete[] distance;
8263 delete[] whichRows;
8264 }
8265 /*
8266 1 (and 4) redundant (and 8 is user)
8267 2 sub
8268 11 movable column
8269 13 empty (or initially fixed) column
8270 14 doubleton
8271 */
8272 typedef struct {
8273 double oldRowLower;
8274 double oldRowUpper;
8275 int row;
8276 int lengthRow;
8277 } clpPresolveInfo1_4_8;
8278 // can be used instead of 1_4_8
8279 typedef struct {
8280 double oldRowLower;
8281 double oldRowUpper;
8282 int row;
8283 int lengthRow;
8284 double *rowLowerX;
8285 double *rowUpperX;
8286 double *tempElement;
8287 int *tempIndex;
8288 int otherRow;
8289 } clpPresolveInfo8;
8290 typedef struct {
8291 double oldRowLower;
8292 double oldRowUpper;
8293 double oldColumnLower;
8294 double oldColumnUpper;
8295 double coefficient;
8296 // 2 is upper
8297 double oldRowLower2;
8298 double oldRowUpper2;
8299 double coefficient2;
8300 int row;
8301 int row2;
8302 int column;
8303 } clpPresolveInfo2;
8304 typedef struct {
8305 double oldColumnLower;
8306 double oldColumnUpper;
8307 double fixedTo;
8308 int column;
8309 int lengthColumn;
8310 } clpPresolveInfo11;
8311 typedef struct {
8312 double oldColumnLower;
8313 double oldColumnUpper;
8314 int column;
8315 } clpPresolveInfo13;
8316 typedef struct {
8317 double oldColumnLower;
8318 double oldColumnUpper;
8319 double oldColumnLower2;
8320 double oldColumnUpper2;
8321 double oldObjective2;
8322 double value1;
8323 double rhs;
8324 int type;
8325 int row;
8326 int column;
8327 int column2;
8328 int lengthColumn2;
8329 } clpPresolveInfo14;
8330 typedef struct {
8331 int infoOffset;
8332 int type;
8333 } clpPresolveInfo;
8334 typedef struct {
8335 int numberEntries;
8336 int maximumEntries;
8337 int numberInitial;
8338 clpPresolveInfo *start;
8339 } listInfo;
8340 typedef struct {
8341 char *putStuff;
8342 char *startStuff;
8343 CoinBigIndex maxStuff;
8344 } saveInfo;
8345 typedef struct {
8346 double *elements;
8347 int *indices;
8348 char *startStuff;
8349 } restoreInfo;
8350 // struct must match in handler
8351 typedef struct {
8352 ClpSimplex *model;
8353 CoinPackedMatrix *rowCopy;
8354 char *rowType;
8355 char *columnType;
8356 saveInfo *stuff;
8357 clpPresolveInfo *info;
8358 int *nActions;
8359 } clpPresolveMore;
8360 void ClpCopyToMiniSave(saveInfo & where, const char *info, unsigned int sizeInfo, int numberElements,
8361 const int *indices, const double *elements)
8362 {
8363 char *put = where.putStuff;
8364 CoinBigIndex n = numberElements * static_cast< int >(sizeof(int) + sizeof(double)) + static_cast< int >(sizeInfo);
8365 if (n + (put - where.startStuff) > where.maxStuff) {
8366 where.maxStuff += CoinMax(where.maxStuff / 2 + 10000, 2 * n);
8367 char *temp = new char[where.maxStuff];
8368 long k = put - where.startStuff;
8369 memcpy(temp, where.startStuff, k);
8370 delete[] where.startStuff;
8371 where.startStuff = temp;
8372 put = temp + k;
8373 }
8374 memcpy(put, info, sizeInfo);
8375 put += sizeInfo;
8376 memcpy(put, indices, numberElements * sizeof(int));
8377 put += numberElements * sizeof(int);
8378 memcpy(put, elements, numberElements * sizeof(double));
8379 put += numberElements * sizeof(double);
8380 where.putStuff = put;
8381 }
8382 static void copyFromSave(restoreInfo & where, clpPresolveInfo & info, void *thisInfoX)
8383 {
8384 char *get = where.startStuff + info.infoOffset;
8385 int type = info.type;
8386 int n = 0;
8387 switch (type) {
8388 case 1:
8389 case 4:
8390 // redundant
8391 {
8392 clpPresolveInfo1_4_8 thisInfo;
8393 memcpy(&thisInfo, get, sizeof(clpPresolveInfo1_4_8));
8394 memcpy(thisInfoX, get, sizeof(clpPresolveInfo1_4_8));
8395 get += sizeof(clpPresolveInfo1_4_8);
8396 n = thisInfo.lengthRow;
8397 }
8398 break;
8399 case 8:
8400 case 9:
8401 // redundant
8402 {
8403 clpPresolveInfo8 thisInfo;
8404 memcpy(&thisInfo, get, sizeof(clpPresolveInfo8));
8405 memcpy(thisInfoX, get, sizeof(clpPresolveInfo8));
8406 get += sizeof(clpPresolveInfo8);
8407 n = thisInfo.lengthRow;
8408 }
8409 break;
8410 case 2:
8411 // sub
8412 {
8413 clpPresolveInfo2 thisInfo;
8414 memcpy(&thisInfo, get, sizeof(clpPresolveInfo2));
8415 memcpy(thisInfoX, get, sizeof(clpPresolveInfo2));
8416 get += sizeof(clpPresolveInfo2);
8417 }
8418 break;
8419 case 11:
8420 // movable column
8421 {
8422 clpPresolveInfo11 thisInfo;
8423 memcpy(&thisInfo, get, sizeof(clpPresolveInfo11));
8424 memcpy(thisInfoX, get, sizeof(clpPresolveInfo11));
8425 get += sizeof(clpPresolveInfo11);
8426 n = thisInfo.lengthColumn;
8427 }
8428 break;
8429 case 13:
8430 // empty (or initially fixed) column
8431 {
8432 clpPresolveInfo13 thisInfo;
8433 memcpy(&thisInfo, get, sizeof(clpPresolveInfo13));
8434 memcpy(thisInfoX, get, sizeof(clpPresolveInfo13));
8435 get += sizeof(clpPresolveInfo13);
8436 }
8437 break;
8438 case 14:
8439 // doubleton
8440 {
8441 clpPresolveInfo14 thisInfo;
8442 memcpy(&thisInfo, get, sizeof(clpPresolveInfo14));
8443 memcpy(thisInfoX, get, sizeof(clpPresolveInfo14));
8444 get += sizeof(clpPresolveInfo14);
8445 n = thisInfo.lengthColumn2;
8446 }
8447 break;
8448 }
8449 if (n) {
8450 memcpy(where.indices, get, n * sizeof(int));
8451 get += n * sizeof(int);
8452 memcpy(where.elements, get, n * sizeof(double));
8453 }
8454 }
8455 #define DEBUG_SOME 0
8456 // need more space
8457 static void moveAround(int numberColumns, CoinBigIndex numberElementsOriginal,
8458 int iColumn, int lengthNeeded,
8459 int *forward, int *backward,
8460 CoinBigIndex *columnStart, int *columnLength,
8461 int *row, double *element)
8462 {
8463 // we only get here if can't fit so if iColumn is last one need shuffle
8464 int last = backward[numberColumns];
8465 bool needCompaction = false;
8466 CoinBigIndex lastElement = columnStart[numberColumns];
8467 //assert(lastElement==2*(numberElementsOriginal+numberColumns));
8468 // save length
8469 int length = columnLength[iColumn];
8470 if (iColumn != last) {
8471 CoinBigIndex put = columnStart[last] + columnLength[last] + 3;
8472 if (put + lengthNeeded <= lastElement) {
8473 // copy
8474 CoinBigIndex start = columnStart[iColumn];
8475 columnStart[iColumn] = put;
8476 memcpy(element + put, element + start, length * sizeof(double));
8477 memcpy(row + put, row + start, length * sizeof(int));
8478 // forward backward
8479 int iLast = backward[iColumn];
8480 int iNext = forward[iColumn];
8481 forward[iLast] = iNext;
8482 backward[iNext] = iLast;
8483 forward[last] = iColumn;
8484 backward[iColumn] = last;
8485 forward[iColumn] = numberColumns;
8486 backward[numberColumns] = iColumn;
8487 } else {
8488 needCompaction = true;
8489 }
8490 } else {
8491 needCompaction = true;
8492 }
8493 if (needCompaction) {
8494 printf("compacting\n");
8495 // size is lastElement+numberElementsOriginal
8496 #ifndef NDEBUG
8497 CoinBigIndex total = lengthNeeded - columnLength[iColumn];
8498 for (int i = 0; i < numberColumns; i++)
8499 total += columnLength[i];
8500 assert(total <= numberElementsOriginal + lengthNeeded);
8501 #endif
8502 CoinBigIndex put = lastElement;
8503 for (int i = 0; i < numberColumns; i++) {
8504 CoinBigIndex start = columnStart[i];
8505 columnStart[i] = put;
8506 int n = columnLength[i];
8507 memcpy(element + put, element + start, n * sizeof(double));
8508 memcpy(row + put, row + start, n * sizeof(int));
8509 put += n;
8510 }
8511 // replace length (may mean copying uninitialized)
8512 columnLength[iColumn] = lengthNeeded;
8513 CoinBigIndex spare = (2 * lastElement - put - (lengthNeeded - length) - numberElementsOriginal) / numberColumns;
8514 assert(spare >= 0);
8515 // copy back
8516 put = 0;
8517 for (int i = 0; i < numberColumns; i++) {
8518 CoinBigIndex start = columnStart[i];
8519 columnStart[i] = put;
8520 int n = columnLength[i];
8521 memcpy(element + put, element + start, n * sizeof(double));
8522 memcpy(row + put, row + start, n * sizeof(int));
8523 put += n + spare;
8524 }
8525 assert(put <= lastElement);
8526 columnLength[iColumn] = length;
8527 // redo forward,backward
8528 for (int i = -1; i < numberColumns; i++)
8529 forward[i] = i + 1;
8530 forward[numberColumns] = -1;
8531 for (int i = 0; i <= numberColumns; i++)
8532 backward[i] = i - 1;
8533 backward[-1] = -1;
8534 }
8535 //abort();
8536 #if DEBUG_SOME > 0
8537 printf("moved column %d\n", iColumn);
8538 #endif
8539 }
8540 #if DEBUG_SOME > 0
8541 #ifndef NDEBUG
8542 static void checkBasis(ClpSimplex * model, char *rowType, char *columnType)
8543 {
8544 int numberRows = model->numberRows();
8545 int nRowBasic = 0;
8546 int nRows = 0;
8547 for (int i = 0; i < numberRows; i++) {
8548 if (rowType[i] <= 0 || rowType[i] == 55) {
8549 nRows++;
8550 if (model->getRowStatus(i) == ClpSimplex::basic)
8551 nRowBasic++;
8552 }
8553 }
8554 int numberColumns = model->numberColumns();
8555 int nColumnBasic = 0;
8556 for (int i = 0; i < numberColumns; i++) {
8557 if ((columnType[i] < 11 || columnType[i] == 55) && model->getColumnStatus(i) == ClpSimplex::basic)
8558 nColumnBasic++;
8559 }
8560 ClpTraceDebug(nRowBasic + nColumnBasic == nRows);
8561 }
8562 #endif
8563 #endif
8564 #if DEBUG_SOME > 0
8565 static int xxxxxx = 2999999;
8566 #endif
8567 /* Mini presolve (faster)
8568 Char arrays must be numberRows and numberColumns long
8569 on entry second part must be filled in as follows -
8570 0 - possible
8571 >0 - take out and do something (depending on value - TBD)
8572 1 - redundant row
8573 2 - sub
8574 11 - column can be moved to bound
8575 4 - row redundant (duplicate)
8576 13 - empty (or initially fixed) column
8577 14 - == row (also column deleted by row)
8578 3 - column altered by a 14
8579 5 - temporary marker for truly redundant sub row
8580 8 - other
8581 -1 row/column can't vanish but can have entries removed/changed
8582 -2 don't touch at all
8583 on exit <=0 ones will be in presolved problem
8584 struct will be created and will be long enough
8585 (information on length etc in first entry)
8586 user must delete struct
8587 */
8588 ClpSimplex *
8589 ClpSimplex::miniPresolve(char *rowType, char *columnType, void **infoOut)
8590 {
8591 // Big enough structure
8592 int numberTotal = numberRows_ + numberColumns_;
8593 CoinBigIndex lastElement = matrix_->getNumElements();
8594 CoinBigIndex maxInfoStuff = 5 * lastElement * static_cast< int >(sizeof(double)) + numberTotal * static_cast< int >(sizeof(clpPresolveInfo2));
8595 clpPresolveInfo *infoA = new clpPresolveInfo[numberTotal];
8596 char *startStuff = new char[maxInfoStuff];
8597 memset(infoA, 'B', numberTotal * sizeof(clpPresolveInfo));
8598 memset(startStuff, 'B', maxInfoStuff);
8599 int nActions = 0;
8600 int *whichRows = new int[2 * numberRows_ + numberColumns_];
8601 int *whichColumns = whichRows + numberRows_;
8602 int *whichRows2 = whichColumns + numberColumns_;
8603 double *array = new double[numberRows_];
8604 memset(array, 0, numberRows_ * sizeof(double));
8605 // New model (put in modification to increase size of matrix) and pack
8606 bool needExtension = numberColumns_ > matrix_->getNumCols();
8607 if (needExtension) {
8608 matrix()->reserve(numberColumns_, lastElement, true);
8609 CoinBigIndex *columnStart = matrix()->getMutableVectorStarts();
8610 for (int i = numberColumns_; i >= 0; i--) {
8611 if (columnStart[i] == 0)
8612 columnStart[i] = lastElement;
8613 else
8614 break;
8615 }
8616 assert(lastElement == columnStart[numberColumns_]);
8617 }
8618 #define TWOFER
8619 #ifdef TWOFER
8620 ClpSimplex *newModel = NULL;
8621 CoinBigIndex lastPossible = 3 * lastElement;
8622 CoinBigIndex lastGood = 2 * lastElement;
8623 clpPresolveMore moreInfo;
8624 moreInfo.model = NULL;
8625 moreInfo.rowType = rowType;
8626 moreInfo.columnType = columnType;
8627 int addColumns = eventHandler_->eventWithInfo(ClpEventHandler::modifyMatrixInMiniPresolve, &moreInfo);
8628 if (moreInfo.model) {
8629 newModel = moreInfo.model;
8630 } else {
8631 newModel = new ClpSimplex(*this);
8632 newModel->matrix()->reserve(numberColumns_ + addColumns, lastPossible, true);
8633 }
8634 #else
8635 ClpSimplex *newModel = new ClpSimplex(*this);
8636 //newModel->matrix()->reserve(numberColumns_,lastElement,true);
8637 #endif
8638 newModel->dropNames();
8639 double *rowLower = newModel->rowLower();
8640 double *rowUpper = newModel->rowUpper();
8641 //double * rowActivity = newModel->primalRowSolution();
8642 unsigned char *rowStatus = newModel->statusArray() + numberColumns_;
8643 // use top bit of status as marker for whichRows update
8644 for (int i = 0; i < numberRows_; i++)
8645 rowStatus[i] &= 127;
8646 double *columnLower = newModel->columnLower();
8647 double *columnUpper = newModel->columnUpper();
8648 //double * columnActivity = newModel->primalColumnSolution();
8649 //unsigned char * columnStatus = newModel->statusArray();
8650 // Take out marked stuff
8651 saveInfo stuff;
8652 stuff.putStuff = startStuff;
8653 stuff.startStuff = startStuff;
8654 stuff.maxStuff = maxInfoStuff;
8655 CoinPackedMatrix *matrix = newModel->matrix();
8656 int *row = matrix->getMutableIndices();
8657 CoinBigIndex *columnStart = matrix->getMutableVectorStarts();
8658 int *columnLength = matrix->getMutableVectorLengths();
8659 double *element = matrix->getMutableElements();
8660 // get row copy
8661 CoinPackedMatrix rowCopy = *matrix;
8662 rowCopy.reverseOrdering();
8663 int *column = rowCopy.getMutableIndices();
8664 CoinBigIndex *rowStart = rowCopy.getMutableVectorStarts();
8665 double *elementByRow = rowCopy.getMutableElements();
8666 int *rowLength = rowCopy.getMutableVectorLengths();
8667 for (int iRow = 0; iRow < numberRows_; iRow++) {
8668 if (rowType[iRow] > 0) {
8669 clpPresolveInfo1_4_8 thisInfo;
8670 thisInfo.row = iRow;
8671 thisInfo.oldRowLower = (rowLower_[iRow] > -1.0e30) ? rowLower_[iRow] - rowLower[iRow] : rowLower[iRow];
8672 thisInfo.oldRowUpper = (rowUpper_[iRow] < 1.0e30) ? rowUpper_[iRow] - rowUpper[iRow] : rowUpper[iRow];
8673 int n = rowLength[iRow];
8674 CoinBigIndex start = rowStart[iRow];
8675 thisInfo.lengthRow = n;
8676 //thisInfo.column=-1;
8677 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
8678 infoA[nActions].type = 4; //rowType[iRow];
8679 nActions++;
8680 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo1_4_8),
8681 n, column + start, elementByRow + start);
8682 }
8683 }
8684 CoinBigIndex put = 0;
8685 bool anyDeleted = false;
8686 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
8687 CoinBigIndex start = columnStart[iColumn];
8688 int length = columnLength[iColumn];
8689 if (columnType[iColumn] > 0 || (columnType[iColumn] == 0 && (!length || columnLower_[iColumn] == columnUpper_[iColumn]))) {
8690 clpPresolveInfo13 thisInfo;
8691 //thisInfo.row=-1;
8692 thisInfo.oldColumnLower = columnLower[iColumn];
8693 thisInfo.oldColumnUpper = columnUpper[iColumn];
8694 thisInfo.column = iColumn;
8695 CoinBigIndex start = columnStart[iColumn];
8696 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
8697 infoA[nActions].type = (columnType[iColumn] > 0) ? columnType[iColumn] : 13;
8698 nActions++;
8699 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo13),
8700 0, NULL, NULL);
8701 columnType[iColumn] = 13;
8702 if (length) {
8703 double solValue = columnLower[iColumn];
8704 if (solValue) {
8705 for (CoinBigIndex j = start; j < start + length; j++) {
8706 int iRow = row[j];
8707 double value = element[j] * solValue;
8708 double lower = rowLower[iRow];
8709 if (lower > -1.0e20)
8710 rowLower[iRow] = lower - value;
8711 double upper = rowUpper[iRow];
8712 if (upper < 1.0e20)
8713 rowUpper[iRow] = upper - value;
8714 }
8715 }
8716 anyDeleted = true;
8717 length = 0;
8718 }
8719 }
8720 columnStart[iColumn] = put;
8721 for (CoinBigIndex i = start; i < start + length; i++) {
8722 int iRow = row[i];
8723 if (rowType[iRow] <= 0) {
8724 row[put] = iRow;
8725 element[put++] = element[i];
8726 }
8727 }
8728 columnLength[iColumn] = static_cast< int >(put - columnStart[iColumn]);
8729 }
8730 int numberInitial = nActions;
8731 columnStart[numberColumns_] = put;
8732 matrix->setNumElements(put);
8733 // get row copy if changed
8734 if (anyDeleted) {
8735 rowCopy = *matrix;
8736 rowCopy.reverseOrdering();
8737 column = rowCopy.getMutableIndices();
8738 rowStart = rowCopy.getMutableVectorStarts();
8739 elementByRow = rowCopy.getMutableElements();
8740 rowLength = rowCopy.getMutableVectorLengths();
8741 }
8742 double *objective = newModel->objective();
8743 double offset = objectiveOffset();
8744 int numberRowsLook = 0;
8745 #ifdef TWOFER
8746 bool orderedMatrix = true;
8747 #endif
8748 int nChanged = 1;
8749 bool feasible = true;
8750 //#define CLP_NO_SUBS
8751 for (int iRow = 0; iRow < numberRows_; iRow++) {
8752 #if DEBUG_SOME > 0
8753 #ifndef NDEBUG
8754 checkBasis(newModel, rowType, columnType);
8755 #endif
8756 #endif
8757 int nPoss = 2;
8758 #if DEBUG_SOME > 0
8759 xxxxxx--;
8760 if (xxxxxx <= 0)
8761 nPoss = 1;
8762 if (xxxxxx < -1000)
8763 nPoss = -1;
8764 if (xxxxxx == 1) {
8765 printf("bad\n");
8766 }
8767 #endif
8768 if (rowLength[iRow] <= nPoss && !rowType[iRow]) {
8769 if (rowLength[iRow] <= 1) {
8770 if (rowLength[iRow] == 1) {
8771 #ifndef CLP_NO_SUBS
8772 // See if already marked
8773 if ((rowStatus[iRow] & 128) == 0) {
8774 rowStatus[iRow] |= 128;
8775 whichRows[numberRowsLook++] = iRow;
8776 assert(numberRowsLook <= numberRows_);
8777 }
8778 #endif
8779 } else {
8780 #if DEBUG_SOME > 0
8781 printf("Dropping null row %d (status %d) - nActions %d\n",
8782 iRow, getRowStatus(iRow), nActions);
8783 #endif
8784 if (rowLower[iRow] > primalTolerance_ || rowUpper[iRow] < -primalTolerance_) {
8785 feasible = false;
8786 nChanged = -1;
8787 numberRowsLook = 0;
8788 break;
8789 }
8790 rowType[iRow] = 1;
8791 clpPresolveInfo1_4_8 thisInfo;
8792 thisInfo.oldRowLower = (rowLower_[iRow] > -1.0e30) ? rowLower_[iRow] - rowLower[iRow] : rowLower[iRow];
8793 thisInfo.oldRowUpper = (rowUpper_[iRow] < 1.0e30) ? rowUpper_[iRow] - rowUpper[iRow] : rowUpper[iRow];
8794 thisInfo.row = iRow;
8795 int n = rowLength[iRow];
8796 CoinBigIndex start = rowStart[iRow];
8797 thisInfo.lengthRow = n;
8798 //thisInfo.column=-1;
8799 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
8800 infoA[nActions].type = 1;
8801 nActions++;
8802 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo1_4_8),
8803 n, column + start, elementByRow + start);
8804 }
8805 #ifdef TWOFER
8806 } else if (rowLower[iRow] == rowUpper[iRow]) {
8807 #ifndef CLP_NO_SUBS
8808 // See if already marked
8809 if ((rowStatus[iRow] & 128) == 0) {
8810 rowStatus[iRow] |= 128;
8811 whichRows[numberRowsLook++] = iRow;
8812 assert(numberRowsLook <= numberRows_);
8813 }
8814 #endif
8815 CoinBigIndex start = rowStart[iRow];
8816 int iColumn1 = column[start];
8817 double value1 = elementByRow[start];
8818 int iColumn2 = column[start + 1];
8819 double value2 = elementByRow[start + 1];
8820 bool swap = false;
8821 double ratio = fabs(value1 / value2);
8822 if (ratio < 0.001 || ratio > 1000.0) {
8823 if (fabs(value1) < fabs(value2)) {
8824 swap = true;
8825 }
8826 } else if (columnLength[iColumn1] < columnLength[iColumn2]) {
8827 swap = true;
8828 }
8829 if (swap) {
8830 iColumn1 = iColumn2;
8831 value1 = value2;
8832 iColumn2 = column[start];
8833 value2 = elementByRow[start];
8834 }
8835 // column bounds
8836 double dropLower = columnLower[iColumn2];
8837 double dropUpper = columnUpper[iColumn2];
8838 double newLower;
8839 double newUpper;
8840 double rhs = rowLower[iRow] / value1;
8841 double multiplier = value2 / value1;
8842 if (multiplier > 0.0) {
8843 newLower = (dropUpper < 1.0e30) ? rhs - multiplier * dropUpper : -COIN_DBL_MAX;
8844 newUpper = (dropLower > -1.0e30) ? rhs - multiplier * dropLower : COIN_DBL_MAX;
8845 } else {
8846 newUpper = (dropUpper < 1.0e30) ? rhs - multiplier * dropUpper : COIN_DBL_MAX;
8847 newLower = (dropLower > -1.0e30) ? rhs - multiplier * dropLower : -COIN_DBL_MAX;
8848 }
8849 //columnType[iColumn1]=3;
8850 columnType[iColumn2] = 14;
8851 rowType[iRow] = 14;
8852 rhs = rowLower[iRow] / value2;
8853 multiplier = value1 / value2;
8854 clpPresolveInfo14 thisInfo;
8855 thisInfo.oldColumnLower = columnLower[iColumn1];
8856 thisInfo.oldColumnUpper = columnUpper[iColumn1];
8857 thisInfo.oldColumnLower2 = columnLower[iColumn2];
8858 thisInfo.oldColumnUpper2 = columnUpper[iColumn2];
8859 thisInfo.oldObjective2 = objective[iColumn2];
8860 thisInfo.value1 = value1;
8861 thisInfo.rhs = rowLower[iRow];
8862 thisInfo.row = iRow;
8863 thisInfo.column = iColumn1;
8864 thisInfo.column2 = iColumn2;
8865 int nel = columnLength[iColumn2];
8866 CoinBigIndex startCol = columnStart[iColumn2];
8867 thisInfo.lengthColumn2 = nel;
8868 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
8869 infoA[nActions].type = 14;
8870 nActions++;
8871 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo14),
8872 nel, row + startCol, element + startCol);
8873 newLower = CoinMax(newLower, columnLower[iColumn1]);
8874 newUpper = CoinMin(newUpper, columnUpper[iColumn1]);
8875 if (newLower > newUpper + primalTolerance_) {
8876 feasible = false;
8877 nChanged = -1;
8878 numberRowsLook = 0;
8879 break;
8880 }
8881 columnLower[iColumn1] = newLower;
8882 columnUpper[iColumn1] = newUpper;
8883 #if DEBUG_SOME > 0
8884 printf("Dropping doubleton row %d (status %d) keeping column %d (status %d) dropping %d (status %d) (mult,rhs %g %g) - nActions %d\n",
8885 iRow, getRowStatus(iRow), iColumn1, getColumnStatus(iColumn1), iColumn2, getColumnStatus(iColumn2), multiplier, rhs, nActions);
8886 #endif
8887 objective[iColumn1] -= objective[iColumn2] * multiplier;
8888 offset -= rowLower[iRow] * (objective[iColumn2] * multiplier);
8889 bool needDrop = false;
8890 if (newModel->getRowStatus(iRow) != basic) {
8891 if (newModel->getColumnStatus(iColumn2) != basic) {
8892 // On way back may as well have column basic
8893 newModel->setColumnStatus(iColumn2, basic);
8894 // need to drop basic
8895 if (newModel->getColumnStatus(iColumn1) == basic) {
8896 //setColumnStatus(iColumn1,superBasic);
8897 newModel->setColumnStatus(iColumn1, superBasic);
8898 } else {
8899 // not much we can do
8900 #if DEBUG_SOME > 0
8901 printf("dropping but no basic a\n");
8902 #endif
8903 }
8904 } else {
8905 // looks good
8906 }
8907 } else {
8908 if (newModel->getColumnStatus(iColumn2) != basic) {
8909 // looks good
8910 } else {
8911 // need to keep a basic
8912 if (newModel->getColumnStatus(iColumn1) != basic) {
8913 //setColumnStatus(iColumn2,superBasic);
8914 //setColumnStatus(iColumn1,basic);
8915 newModel->setColumnStatus(iColumn1, basic);
8916 } else {
8917 // not much we can do
8918 #if DEBUG_SOME > 0
8919 printf("dropping but all basic a\n");
8920 #endif
8921 needDrop = true;
8922 //setColumnStatus(iColumn2,superBasic);
8923 }
8924 }
8925 }
8926 int n = 0;
8927 start = columnStart[iColumn1];
8928 for (CoinBigIndex i = start; i < start + columnLength[iColumn1];
8929 i++) {
8930 int jRow = row[i];
8931 if (jRow != iRow) {
8932 array[jRow] = element[i];
8933 whichRows2[n++] = jRow;
8934 }
8935 }
8936 rowLength[iRow] = 0;
8937 start = columnStart[iColumn2];
8938 for (CoinBigIndex i = start; i < start + columnLength[iColumn2];
8939 i++) {
8940 int jRow = row[i];
8941 if (jRow != iRow) {
8942 double value = array[jRow];
8943 double valueNew = value - multiplier * element[i];
8944 double rhsMod = rhs * element[i];
8945 if (rowLower[jRow] > -1.0e30)
8946 rowLower[jRow] -= rhsMod;
8947 if (rowUpper[jRow] < 1.0e30)
8948 rowUpper[jRow] -= rhsMod;
8949 if (!value) {
8950 array[jRow] = valueNew;
8951 whichRows2[n++] = jRow;
8952 } else {
8953 if (!valueNew)
8954 valueNew = 1.0e-100;
8955 array[jRow] = valueNew;
8956 }
8957 }
8958 }
8959 columnLength[iColumn2] = 0;
8960 start = columnStart[iColumn1];
8961 if (n > columnLength[iColumn1]) {
8962 orderedMatrix = false;
8963 if (lastElement + n > lastGood) {
8964 // pack down
8965 CoinBigIndex put = lastElement;
8966 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
8967 CoinBigIndex start = columnStart[iColumn];
8968 columnStart[iColumn] = put - lastElement;
8969 int length = columnLength[iColumn];
8970 for (CoinBigIndex j = start; j < start + length; j++) {
8971 row[put] = row[j];
8972 element[put++] = element[j];
8973 }
8974 }
8975 CoinBigIndex numberElements = put - lastElement;
8976 columnStart[numberColumns_] = numberElements;
8977 memcpy(row, row + lastElement, numberElements * sizeof(int));
8978 memcpy(element, element + lastElement, numberElements * sizeof(double));
8979 lastElement = numberElements;
8980 }
8981 start = lastElement;
8982 columnStart[iColumn1] = start;
8983 }
8984 CoinBigIndex put = start;
8985 for (int i = 0; i < n; i++) {
8986 int jRow = whichRows2[i];
8987 double value = array[jRow];
8988 //#define FUNNY_CHECK
8989 #ifdef FUNNY_CHECK
8990 if (rowType[jRow] == -2)
8991 printf("iColumn1 %d iColumn2 %d row %d value %g\n",
8992 iColumn1, iColumn2, jRow, value);
8993 #endif
8994 array[jRow] = 0.0;
8995 if (fabs(value) < 1.0e-13)
8996 value = 0.0;
8997 if (value) {
8998 row[put] = jRow;
8999 element[put++] = value;
9000 if (needDrop && newModel->getRowStatus(jRow) != basic) {
9001 newModel->setRowStatus(jRow, basic);
9002 needDrop = false;
9003 }
9004 }
9005 // take out of row copy
9006 CoinBigIndex startR = rowStart[jRow];
9007 CoinBigIndex putR = startR;
9008 for (CoinBigIndex i = startR; i < startR + rowLength[jRow]; i++) {
9009 int iColumn = column[i];
9010 if (iColumn != iColumn1 && iColumn != iColumn2) {
9011 column[putR] = iColumn;
9012 elementByRow[putR++] = elementByRow[i];
9013 } else if (value) {
9014 column[putR] = iColumn1;
9015 elementByRow[putR++] = value;
9016 value = 0.0;
9017 }
9018 }
9019 int rowLength2 = static_cast< int >(putR - startR);
9020 #ifndef CLP_NO_SUBS
9021 if (rowLength2 <= 1 && rowLength[jRow] > 1 && jRow < iRow) {
9022 // may be interesting
9023 // See if already marked
9024 if ((rowStatus[jRow] & 128) == 0) {
9025 rowStatus[jRow] |= 128;
9026 whichRows[numberRowsLook++] = jRow;
9027 assert(numberRowsLook <= numberRows_);
9028 }
9029 }
9030 #endif
9031 rowLength[jRow] = rowLength2;
9032 }
9033 columnLength[iColumn1] = static_cast< int >(put - start);
9034 lastElement = CoinMax(lastElement, put);
9035 #endif
9036 }
9037 } else if (true && rowLower[iRow] == -COIN_DBL_MAX && rowUpper[iRow] == COIN_DBL_MAX) {
9038 #if DEBUG_SOME > 0
9039 printf("Dropping null free row %d (status %d) - nActions %d\n",
9040 iRow, getRowStatus(iRow), nActions);
9041 #endif
9042 rowType[iRow] = 1;
9043 clpPresolveInfo1_4_8 thisInfo;
9044 thisInfo.oldRowLower = (rowLower_[iRow] > -1.0e30) ? rowLower_[iRow] - rowLower[iRow] : rowLower[iRow];
9045 thisInfo.oldRowUpper = (rowUpper_[iRow] < 1.0e30) ? rowUpper_[iRow] - rowUpper[iRow] : rowUpper[iRow];
9046 thisInfo.row = iRow;
9047 int n = rowLength[iRow];
9048 CoinBigIndex start = rowStart[iRow];
9049 thisInfo.lengthRow = n;
9050 //thisInfo.column=-1;
9051 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
9052 infoA[nActions].type = 1;
9053 nActions++;
9054 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo1_4_8),
9055 n, column + start, elementByRow + start);
9056 // need to take out row
9057 CoinBigIndex end = start + n;
9058 rowLength[iRow] = 0;
9059 for (CoinBigIndex k = start; k < end; k++) {
9060 int iColumn = column[k];
9061 CoinBigIndex startColumn = columnStart[iColumn];
9062 int n = columnLength[iColumn];
9063 CoinBigIndex endColumn = startColumn + n;
9064 columnLength[iColumn] = n - 1;
9065 for (CoinBigIndex j = startColumn; j < endColumn; j++) {
9066 int jRow = row[j];
9067 if (jRow == iRow) {
9068 endColumn--;
9069 row[j] = row[endColumn];
9070 element[j] = element[endColumn];
9071 break;
9072 }
9073 }
9074 assert(endColumn == startColumn + n - 1);
9075 }
9076 }
9077 }
9078 #if DEBUG_SOME > 0
9079 if (xxxxxx < -1000)
9080 nChanged = -1;
9081 #endif
9082 while (nChanged > 0) {
9083 nChanged = 0;
9084 int numberColumnsLook = 0;
9085 for (int i = 0; i < numberRowsLook; i++) {
9086 #if DEBUG_SOME > 0
9087 #ifndef NDEBUG
9088 checkBasis(newModel, rowType, columnType);
9089 #endif
9090 #endif
9091 int iRow = whichRows[i];
9092 // unmark
9093 assert((rowStatus[iRow] & 128) != 0);
9094 rowStatus[iRow] &= 127;
9095 if (rowLength[iRow] == 1) {
9096 //rowType[iRow]=55;
9097 int iColumn = column[rowStart[iRow]];
9098 if (/*columnType[iColumn]==14||*/ columnType[iColumn] < -1)
9099 continue;
9100 if (!columnType[iColumn]) {
9101 columnType[iColumn] = 55;
9102 whichColumns[numberColumnsLook++] = iColumn;
9103 nChanged++;
9104 }
9105 #if 0
9106 } else if (rowLength[iRow]==2) {
9107 if (rowLower[iRow]==rowUpper[iRow]) {
9108 CoinBigIndex start = rowStart[iRow];
9109 int iColumn1 = column[start];
9110 int iColumn2 = column[start+1];
9111 if (!columnType[iColumn1]&&!columnType[iColumn2]) {
9112 if (fabs(elementByRow[start])<fabs(elementByRow[start+1])) {
9113 iColumn1 = iColumn2;
9114 iColumn2 = column[start];
9115 }
9116 // iColumn2 will be deleted
9117 columnType[iColumn1]=56;
9118 columnType[iColumn2]=56;
9119 }
9120 } else {
9121 printf("why here in miniPresolve row %d\n",iRow);
9122 }
9123 #endif
9124 }
9125 }
9126 // mark one row as ub and take out row in column copy
9127 numberRowsLook = 0;
9128 for (int iLook = 0; iLook < numberColumnsLook; iLook++) {
9129 #if DEBUG_SOME > 0
9130 #ifndef NDEBUG
9131 checkBasis(newModel, rowType, columnType);
9132 #endif
9133 #endif
9134 nChanged++;
9135 int iColumn = whichColumns[iLook];
9136 if (columnType[iColumn] != 55 && columnType[iColumn] > 10)
9137 continue;
9138 if (columnType[iColumn] == 55)
9139 columnType[iColumn] = 0;
9140 CoinBigIndex start = columnStart[iColumn];
9141 int jRowLower = -1;
9142 double newLower = columnLower[iColumn];
9143 int jRowUpper = -1;
9144 double newUpper = columnUpper[iColumn];
9145 double coefficientLower = 0.0;
9146 double coefficientUpper = 0.0;
9147 for (CoinBigIndex i = start; i < start + columnLength[iColumn];
9148 i++) {
9149 int iRow = row[i];
9150 if (rowLength[iRow] == 1 && rowType[iRow] == 0) {
9151 rowType[iRow] = 1;
9152 assert(columnType[iColumn] >= 0);
9153 // adjust bounds
9154 double value = elementByRow[rowStart[iRow]];
9155 double lower = newLower;
9156 double upper = newUpper;
9157 if (value > 0.0) {
9158 if (rowUpper[iRow] < 1.0e30)
9159 upper = rowUpper[iRow] / value;
9160 if (rowLower[iRow] > -1.0e30)
9161 lower = rowLower[iRow] / value;
9162 } else {
9163 if (rowUpper[iRow] < 1.0e30)
9164 lower = rowUpper[iRow] / value;
9165 if (rowLower[iRow] > -1.0e30)
9166 upper = rowLower[iRow] / value;
9167 }
9168 if (lower > newLower + primalTolerance_) {
9169 if (lower > newUpper + primalTolerance_) {
9170 feasible = false;
9171 nChanged = -1;
9172 numberColumnsLook = 0;
9173 break;
9174 } else if (lower > newUpper - primalTolerance_) {
9175 newLower = newUpper;
9176 } else {
9177 newLower = CoinMax(lower, newLower);
9178 }
9179 jRowLower = iRow;
9180 coefficientLower = value;
9181 }
9182 if (upper < newUpper - primalTolerance_) {
9183 if (upper < newLower - primalTolerance_) {
9184 feasible = false;
9185 nChanged = -1;
9186 numberColumnsLook = 0;
9187 break;
9188 } else if (upper < newLower + primalTolerance_) {
9189 newUpper = newLower;
9190 } else {
9191 newUpper = CoinMin(upper, newUpper);
9192 }
9193 jRowUpper = iRow;
9194 coefficientUpper = value;
9195 }
9196 }
9197 }
9198 CoinBigIndex put = start;
9199 int iFlag = 0;
9200 int nonFree = 0;
9201 int numberNonBasicSlacksOut = 0;
9202 if (jRowLower >= 0 || jRowUpper >= 0) {
9203 clpPresolveInfo2 thisInfo;
9204 if (jRowLower >= 0) {
9205 thisInfo.oldRowLower = (rowLower_[jRowLower] > -1.0e30) ? rowLower_[jRowLower] - rowLower[jRowLower] : rowLower[jRowLower];
9206 thisInfo.oldRowUpper = (rowUpper_[jRowLower] < 1.0e30) ? rowUpper_[jRowLower] - rowUpper[jRowLower] : rowUpper[jRowLower];
9207 thisInfo.row = jRowLower;
9208 thisInfo.coefficient = coefficientLower;
9209 } else {
9210 thisInfo.row = -1;
9211 #ifndef NDEBUG
9212 thisInfo.oldRowLower = COIN_DBL_MAX;
9213 thisInfo.oldRowUpper = -COIN_DBL_MAX;
9214 thisInfo.coefficient = 0.0;
9215 #endif
9216 }
9217 if (jRowUpper >= 0 && jRowLower != jRowUpper) {
9218 thisInfo.oldRowLower2 = (rowLower_[jRowUpper] > -1.0e30) ? rowLower_[jRowUpper] - rowLower[jRowUpper] : rowLower[jRowUpper];
9219 thisInfo.oldRowUpper2 = (rowUpper_[jRowUpper] < 1.0e30) ? rowUpper_[jRowUpper] - rowUpper[jRowUpper] : rowUpper[jRowUpper];
9220 thisInfo.row2 = jRowUpper;
9221 thisInfo.coefficient2 = coefficientUpper;
9222 } else {
9223 thisInfo.row2 = -1;
9224 #ifndef NDEBUG
9225 thisInfo.oldRowLower2 = COIN_DBL_MAX;
9226 thisInfo.oldRowUpper2 = -COIN_DBL_MAX;
9227 thisInfo.coefficient2 = 0.0;
9228 #endif
9229 }
9230 thisInfo.oldColumnLower = columnLower[iColumn];
9231 thisInfo.oldColumnUpper = columnUpper[iColumn];
9232 columnLower[iColumn] = newLower;
9233 columnUpper[iColumn] = newUpper;
9234 thisInfo.column = iColumn;
9235 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
9236 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo2),
9237 0, NULL, NULL);
9238 infoA[nActions].type = 2;
9239 nActions++;
9240 }
9241 for (CoinBigIndex i = start; i < start + columnLength[iColumn];
9242 i++) {
9243 int iRow = row[i];
9244 if (rowLength[iRow] == 1 && rowType[iRow] >= 0 && rowType[iRow] != 5) {
9245 #if DEBUG_SOME > 0
9246 printf("Dropping singleton row %d (status %d) because of column %d (status %d) - jRow lower/upper %d/%d - nActions %d\n",
9247 iRow, getRowStatus(iRow), iColumn,
9248 getColumnStatus(iColumn), jRowLower, jRowUpper, nActions);
9249 #endif
9250 if (newModel->getRowStatus(iRow) != basic) {
9251 //newModel->setRowStatus(iRow,basic);
9252 numberNonBasicSlacksOut++;
9253 }
9254 rowType[iRow] = 1;
9255 if (iRow != jRowLower && iRow != jRowUpper) {
9256 // mark as redundant
9257 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
9258 clpPresolveInfo1_4_8 thisInfo;
9259 thisInfo.oldRowLower = (rowLower_[iRow] > -1.0e30) ? rowLower_[iRow] - rowLower[iRow] : rowLower[iRow];
9260 thisInfo.oldRowUpper = (rowUpper_[iRow] < 1.0e30) ? rowUpper_[iRow] - rowUpper[iRow] : rowUpper[iRow];
9261 thisInfo.row = iRow;
9262 int n = rowLength[iRow];
9263 CoinBigIndex start = rowStart[iRow];
9264 thisInfo.lengthRow = n;
9265 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo1_4_8),
9266 n, column + start, elementByRow + start);
9267 infoA[nActions].type = 1;
9268 nActions++;
9269 }
9270 rowLength[iRow] = 0;
9271 } else if (rowType[iRow] <= 0) {
9272 row[put] = iRow;
9273 double value = element[i];
9274 element[put++] = value;
9275 if (rowType[iRow] >= 0 && iFlag < 3) {
9276 assert(rowType[iRow] == 0);
9277 double lower = rowLower[iRow];
9278 double upper = rowUpper[iRow];
9279 if (-1.0e20 < lower && upper < 1.0e20) {
9280 // bounded - we lose
9281 iFlag = -1;
9282 //break;
9283 } else if (-1.0e20 < lower || upper < 1.0e20) {
9284 nonFree++;
9285 }
9286 // see what this particular row says
9287 // jFlag == 2 ==> up is towards feasibility
9288 int jFlag = (value > 0.0
9289 ? (upper > 1.0e20 ? 2 : 1)
9290 : (lower < -1.0e20 ? 2 : 1));
9291
9292 if (iFlag) {
9293 // check that it agrees with iFlag.
9294 if (iFlag != jFlag) {
9295 iFlag = -1;
9296 }
9297 } else {
9298 // first row -- initialize iFlag
9299 iFlag = jFlag;
9300 }
9301 } else if (rowType[iRow] < 0) {
9302 iFlag = -1; // be safe
9303 }
9304 }
9305 }
9306 // Do we need to switch status of iColumn?
9307 if (numberNonBasicSlacksOut > 0) {
9308 // make iColumn non basic if possible
9309 if (newModel->getColumnStatus(iColumn) == basic) {
9310 newModel->setColumnStatus(iColumn, superBasic);
9311 }
9312 }
9313 double cost = objective[iColumn] * optimizationDirection_;
9314 int length = static_cast< int >(put - columnStart[iColumn]);
9315 if (!length) {
9316 if (!cost) {
9317 // put to closest to zero
9318 if (fabs(columnLower[iColumn]) < fabs(columnUpper[iColumn]))
9319 iFlag = 1;
9320 else
9321 iFlag = 2;
9322 } else if (cost > 0.0) {
9323 iFlag = 1;
9324 } else {
9325 iFlag = 2;
9326 }
9327 } else {
9328 if (cost > 0.0 && iFlag == 2)
9329 iFlag = -1;
9330 else if (cost < 0.0 && iFlag == 1)
9331 iFlag = -1;
9332 }
9333 columnLength[iColumn] = length;
9334 //#define NO_MOVABLE
9335 #ifdef NO_MOVABLE
9336 iFlag = -1;
9337 #endif
9338 if (iFlag > 0 && nonFree) {
9339 double newValue;
9340 if (iFlag == 2) {
9341 // fix to upper
9342 newValue = CoinMin(columnUpper[iColumn], 1.0e20);
9343 } else {
9344 // fix to lower
9345 newValue = CoinMax(columnLower[iColumn], -1.0e20);
9346 }
9347 columnActivity_[iColumn] = newValue;
9348 #if DEBUG_SOME > 0
9349 if (newModel->getColumnStatus(iColumn) == basic) {
9350 // ? move basic back onto sub if can?
9351 iFlag += 2;
9352 }
9353 printf("Dropping movable column %d - iFlag %d - jRow lower/upper %d/%d - nActions %d\n",
9354 iColumn, iFlag, jRowLower, jRowUpper, nActions);
9355 #endif
9356 columnType[iColumn] = 11;
9357 if (newModel->getColumnStatus(iColumn) == basic) {
9358 // need to put status somewhere else
9359 int shortestNumber = numberColumns_;
9360 int shortest = -1;
9361 for (CoinBigIndex j = start; j < start + length; j++) {
9362 int iRow = row[j];
9363 if (rowLength[iRow] < shortestNumber && newModel->getRowStatus(iRow) != basic) {
9364 shortest = iRow;
9365 shortestNumber = rowLength[iRow];
9366 }
9367 }
9368 if (shortest >= 0) {
9369 // make basic
9370 newModel->setRowStatus(shortest, basic);
9371 newModel->setColumnStatus(iColumn, superBasic);
9372 } else {
9373 // put on a column
9374 shortestNumber = numberColumns_;
9375 shortest = -1;
9376 for (CoinBigIndex j = start; j < start + length; j++) {
9377 int iRow = row[j];
9378 if (rowLength[iRow] < shortestNumber) {
9379 CoinBigIndex start = rowStart[iRow];
9380 for (CoinBigIndex i = start; i < start + rowLength[iRow]; i++) {
9381 int jColumn = column[i];
9382 if (iColumn != jColumn && newModel->getColumnStatus(jColumn) != basic) {
9383 shortest = jColumn;
9384 shortestNumber = rowLength[iRow];
9385 }
9386 }
9387 }
9388 }
9389 if (shortest >= 0) {
9390 // make basic
9391 newModel->setColumnStatus(shortest, basic);
9392 } else {
9393 #if DEBUG_SOME > 0
9394 printf("what now - dropping - basic\n");
9395 #endif
9396 }
9397 }
9398 }
9399 clpPresolveInfo11 thisInfo;
9400 thisInfo.oldColumnLower = columnLower[iColumn];
9401 thisInfo.oldColumnUpper = columnUpper[iColumn];
9402 thisInfo.fixedTo = newValue;
9403 columnLower[iColumn] = newValue;
9404 columnUpper[iColumn] = newValue;
9405 thisInfo.column = iColumn;
9406 int n = columnLength[iColumn];
9407 CoinBigIndex start = columnStart[iColumn];
9408 thisInfo.lengthColumn = n;
9409 infoA[nActions].infoOffset = static_cast< int >(stuff.putStuff - startStuff);
9410 infoA[nActions].type = 11;
9411 nActions++;
9412 ClpCopyToMiniSave(stuff, reinterpret_cast< char * >(&thisInfo), sizeof(clpPresolveInfo11),
9413 n, row + start, element + start);
9414 // adjust rhs and take out of rows
9415 columnLength[iColumn] = 0;
9416 nChanged++;
9417 for (CoinBigIndex j = start; j < start + length; j++) {
9418 int iRow = row[j];
9419 double value = element[j] * newValue;
9420 double lower = rowLower[iRow];
9421 if (lower > -1.0e20)
9422 rowLower[iRow] = lower - value;
9423 double upper = rowUpper[iRow];
9424 if (upper < 1.0e20)
9425 rowUpper[iRow] = upper - value;
9426 // take out of row copy (and put on list)
9427 assert(rowType[iRow] <= 0 && rowType[iRow] > -2);
9428 // See if already marked (will get to row later in loop
9429 if ((rowStatus[iRow] & 128) == 0) {
9430 rowStatus[iRow] |= 128;
9431 whichRows[numberRowsLook++] = iRow;
9432 assert(numberRowsLook <= numberRows_);
9433 }
9434 CoinBigIndex start = rowStart[iRow];
9435 CoinBigIndex put = start;
9436 for (CoinBigIndex i = start; i < start + rowLength[iRow]; i++) {
9437 int jColumn = column[i];
9438 if (iColumn != jColumn) {
9439 column[put] = jColumn;
9440 elementByRow[put++] = elementByRow[i];
9441 }
9442 }
9443 rowLength[iRow] = static_cast< int >(put - start);
9444 }
9445 }
9446 }
9447 }
9448 if (feasible) {
9449 clpPresolveMore moreInfo;
9450 moreInfo.model = newModel;
9451 moreInfo.rowCopy = &rowCopy;
9452 moreInfo.rowType = rowType;
9453 moreInfo.columnType = columnType;
9454 moreInfo.stuff = &stuff;
9455 moreInfo.info = infoA;
9456 moreInfo.nActions = &nActions;
9457 eventHandler_->eventWithInfo(ClpEventHandler::moreMiniPresolve, &moreInfo);
9458 newModel->setObjectiveOffset(offset);
9459 int nChar2 = nActions * static_cast< int >(sizeof(clpPresolveInfo)) + static_cast< int >(stuff.putStuff - startStuff);
9460 clpPresolveInfo *infoData = reinterpret_cast< clpPresolveInfo * >(new char[nChar2]);
9461 memcpy(infoData, infoA, nActions * sizeof(clpPresolveInfo));
9462 char *info2 = reinterpret_cast< char * >(infoData + nActions);
9463 memcpy(info2, startStuff, stuff.putStuff - startStuff);
9464 listInfo *infoNew = new listInfo;
9465 infoNew->numberEntries = nActions;
9466 infoNew->maximumEntries = nActions;
9467 infoNew->start = infoData;
9468 infoNew->numberInitial = numberInitial;
9469 *infoOut = infoNew;
9470 int nRows = 0;
9471 for (int iRow = 0; iRow < numberRows_; iRow++) {
9472 if (rowType[iRow] > 0)
9473 whichRows[nRows++] = iRow;
9474 }
9475 int nColumns = 0;
9476 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9477 if (columnType[iColumn] > 10)
9478 whichColumns[nColumns++] = iColumn;
9479 }
9480 #ifdef FUNNY_CHECK
9481 {
9482 CoinPackedMatrix rowCopy2 = *this->matrix();
9483 rowCopy2.reverseOrdering();
9484 int *column2 = rowCopy2.getMutableIndices();
9485 CoinBigIndex *rowStart2 = rowCopy2.getMutableVectorStarts();
9486 double *elementByRow2 = rowCopy2.getMutableElements();
9487 int *rowLength2 = rowCopy2.getMutableVectorLengths();
9488 printf("Odd rows\n");
9489 for (int iRow = 0; iRow < numberRows_; iRow++) {
9490 if (rowType[iRow] == -2) {
9491 CoinBigIndex start = rowStart[iRow];
9492 int length = rowLength[iRow];
9493 printf("Odd row %d -> ", iRow);
9494 for (CoinBigIndex j = start; j < start + length; j++) {
9495 int iColumn = column[j];
9496 printf("(%d %g) ", iColumn, elementByRow[j]);
9497 }
9498 printf("Original ");
9499 start = rowStart2[iRow];
9500 length = rowLength2[iRow];
9501 for (CoinBigIndex j = start; j < start + length; j++) {
9502 int iColumn = column2[j];
9503 printf("(%d %g) ", iColumn, elementByRow2[j]);
9504 }
9505 printf(">= %g/%g\n", rowLower[iRow], rowLower_[iRow]);
9506 }
9507 }
9508 printf("now columns\n");
9509 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9510 CoinBigIndex start = columnStart[iColumn];
9511 int length = columnLength[iColumn];
9512 for (CoinBigIndex j = start; j < start + length; j++) {
9513 int iRow = row[j];
9514 if (rowType[iRow] == -2)
9515 printf("Column %d row %d value %g\n",
9516 iColumn, iRow, element[j]);
9517 }
9518 }
9519 }
9520 #endif
9521 #ifdef TWOFER
9522 if (!orderedMatrix) {
9523 //lastElement;
9524 // move up
9525 CoinBigIndex put = lastElement;
9526 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9527 CoinBigIndex start = columnStart[iColumn];
9528 columnStart[iColumn] = put - lastElement;
9529 int length = columnLength[iColumn];
9530 for (CoinBigIndex j = start; j < start + length; j++) {
9531 row[put] = row[j];
9532 element[put++] = element[j];
9533 }
9534 }
9535 CoinBigIndex numberElements = put - lastElement;
9536 columnStart[numberColumns_] = numberElements;
9537 memcpy(row, row + lastElement, numberElements * sizeof(int));
9538 memcpy(element, element + lastElement, numberElements * sizeof(double));
9539 }
9540 #endif
9541 // could just shrink - would be faster
9542 #if DEBUG_SOME > 0
9543 printf("%d Row types and lookup\n", nRows);
9544 int nBNew = 0;
9545 int iNew = 0;
9546 for (int iRow = 0; iRow < numberRows_; iRow++) {
9547 int type = rowType[iRow];
9548 char xNew = 'O';
9549 if (type <= 0) {
9550 xNew = 'N';
9551 if (newModel->getRowStatus(iRow) == basic) {
9552 nBNew++;
9553 xNew = 'B';
9554 }
9555 printf("%d -> %d type %d - new status %c\n", iRow, iNew, rowType[iRow], xNew);
9556 iNew++;
9557 }
9558 }
9559 printf("%d Column types and lookup\n", nColumns);
9560 iNew = 0;
9561 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9562 int type = columnType[iColumn];
9563 char xNew = 'O';
9564 if (type <= 10) {
9565 xNew = 'N';
9566 if (newModel->getColumnStatus(iColumn) == basic) {
9567 nBNew++;
9568 xNew = 'B';
9569 }
9570 printf("%d -> %d type %d - new status %c\n", iColumn, iNew, columnType[iColumn], xNew);
9571 iNew++;
9572 }
9573 }
9574 printf("Deleting %d rows (now %d) and %d columns (%d basic)\n", nRows, numberRows_ - nRows,
9575 nColumns, nBNew);
9576 #else
9577 #if DEBUG_SOME > 0
9578 printf("Deleting %d rows (now %d) and %d columns\n", nRows, numberRows_ - nRows,
9579 nColumns);
9580 #endif
9581 #endif
9582 #if 0
9583 newModel->deleteRows(nRows,whichRows);
9584 newModel->deleteColumns(nColumns,whichColumns);
9585 #else
9586 newModel->deleteRowsAndColumns(nRows, whichRows, nColumns, whichColumns);
9587 #endif
9588 } else {
9589 delete newModel;
9590 newModel = NULL;
9591 *infoOut = NULL;
9592 }
9593 delete[] whichRows;
9594 delete[] infoA;
9595 delete[] startStuff;
9596 delete[] array;
9597 return newModel;
9598 }
9599 // After mini presolve
9600 void
9601 ClpSimplex::miniPostsolve(const ClpSimplex *presolvedModel, void *infoIn)
9602 {
9603 int numberTotal = numberRows_ + numberColumns_;
9604 listInfo *infoX = reinterpret_cast< listInfo * >(infoIn);
9605 int nActions = infoX->numberEntries;
9606 #if DEBUG_SOME > 0
9607 #ifndef NDEBUG
9608 int numberInitial = infoX->numberInitial;
9609 #endif
9610 #endif
9611 clpPresolveInfo *infoA = infoX->start;
9612 char *startStuff = reinterpret_cast< char * >(infoA + nActions);
9613 // move status and solution across
9614 int numberColumns2 = presolvedModel->numberColumns();
9615 const double *solution2 = presolvedModel->primalColumnSolution();
9616 unsigned char *rowStatus2 = presolvedModel->statusArray() + numberColumns2;
9617 unsigned char *columnStatus2 = presolvedModel->statusArray();
9618 unsigned char *rowStatus = status_ + numberColumns_;
9619 unsigned char *columnStatus = status_;
9620 char *rowType = new char[numberTotal];
9621 memset(rowType, 0, numberTotal);
9622 char *columnType = rowType + numberRows_;
9623 double *rowLowerX = new double[3 * numberRows_ + 3 * numberColumns_ + CoinMax(numberRows_, numberColumns_)];
9624 double *rowUpperX = rowLowerX + numberRows_;
9625 double *columnLowerX = rowUpperX + numberRows_;
9626 double *columnUpperX = columnLowerX + numberColumns_;
9627 double *objectiveX = columnUpperX + numberColumns_;
9628 double *tempElement = objectiveX + numberColumns_;
9629 double *array = tempElement + CoinMax(numberRows_, numberColumns_);
9630 memset(array, 0, numberRows_ * sizeof(double));
9631 int *tempIndex = new int[CoinMax(numberRows_, numberColumns_) + 4 + 2 * numberColumns_ + numberRows_];
9632 int *forward = tempIndex + CoinMax(numberRows_, numberColumns_) + 1;
9633 int *backward = forward + numberColumns_ + 2;
9634 int *whichRows2 = backward + numberColumns_ + 1;
9635 for (int i = -1; i < numberColumns_; i++)
9636 forward[i] = i + 1;
9637 forward[numberColumns_] = -1;
9638 for (int i = 0; i <= numberColumns_; i++)
9639 backward[i] = i - 1;
9640 backward[-1] = -1;
9641 restoreInfo restore;
9642 restore.elements = tempElement;
9643 restore.indices = tempIndex;
9644 restore.startStuff = startStuff;
9645 #ifndef NDEBUG
9646 for (int i = 0; i < numberRows_; i++) {
9647 rowLowerX[i] = COIN_DBL_MAX;
9648 rowUpperX[i] = -COIN_DBL_MAX;
9649 }
9650 for (int i = 0; i < numberColumns_; i++) {
9651 columnLowerX[i] = COIN_DBL_MAX;
9652 columnUpperX[i] = -COIN_DBL_MAX;
9653 }
9654 #endif
9655 memset(rowActivity_, 0, numberRows_ * sizeof(double));
9656 memset(dual_, 0, numberRows_ * sizeof(double));
9657 // Get presolved contribution
9658 const int *row = matrix()->getIndices();
9659 const CoinBigIndex *columnStart = matrix()->getVectorStarts();
9660 const int *columnLength = matrix()->getVectorLengths();
9661 const double *element = matrix()->getElements();
9662 // forwards so dropped column at end
9663 for (int i = 0; i < nActions; i++) {
9664 int type = infoA[i].type;
9665 char *getStuff = startStuff + infoA[i].infoOffset;
9666 int iRow = -1;
9667 int iColumn = -1;
9668 switch (type) {
9669 case 1:
9670 case 4:
9671 case 8:
9672 case 9:
9673 // redundant
9674 {
9675 clpPresolveInfo1_4_8 thisInfo;
9676 memcpy(&thisInfo, getStuff, sizeof(clpPresolveInfo1_4_8));
9677 iRow = thisInfo.row;
9678 rowType[iRow] = static_cast< char >(type);
9679 }
9680 break;
9681 case 2:
9682 // sub
9683 {
9684 clpPresolveInfo2 thisInfo;
9685 memcpy(&thisInfo, getStuff, sizeof(clpPresolveInfo2));
9686 iRow = thisInfo.row;
9687 if (iRow >= 0)
9688 rowType[iRow] = 2;
9689 iRow = thisInfo.row2;
9690 if (iRow >= 0)
9691 rowType[iRow] = 2;
9692 iColumn = thisInfo.column;
9693 columnType[iColumn] = 2;
9694 }
9695 break;
9696 case 11:
9697 // movable column
9698 {
9699 clpPresolveInfo11 thisInfo;
9700 memcpy(&thisInfo, getStuff, sizeof(clpPresolveInfo11));
9701 iColumn = thisInfo.column;
9702 columnType[iColumn] = 11;
9703 }
9704 break;
9705 case 13:
9706 // empty column
9707 {
9708 clpPresolveInfo13 thisInfo;
9709 memcpy(&thisInfo, getStuff, sizeof(clpPresolveInfo13));
9710 iColumn = thisInfo.column;
9711 columnType[iColumn] = 13;
9712 }
9713 break;
9714 case 14:
9715 // doubleton
9716 {
9717 clpPresolveInfo14 thisInfo;
9718 memcpy(&thisInfo, getStuff, sizeof(clpPresolveInfo14));
9719 iRow = thisInfo.row;
9720 iColumn = thisInfo.column;
9721 int iColumn2 = thisInfo.column2;
9722 columnType[iColumn] = 3;
9723 columnType[iColumn2] = 14;
9724 rowType[iRow] = 3;
9725 }
9726 break;
9727 }
9728 #if DEBUG_SOME > 0
9729 printf("Action %d type %d row %d column %d\n",
9730 i, type, iRow, iColumn);
9731 #endif
9732 }
9733 int iGet = 0;
9734 const double *rowLowerY = presolvedModel->rowLower();
9735 const double *rowUpperY = presolvedModel->rowUpper();
9736 for (int iRow = 0; iRow < numberRows_; iRow++) {
9737 if (!rowType[iRow]) {
9738 rowStatus[iRow] = rowStatus2[iGet];
9739 rowActivity_[iRow] = presolvedModel->rowActivity_[iGet];
9740 dual_[iRow] = presolvedModel->dual_[iGet];
9741 rowLowerX[iRow] = rowLowerY[iGet];
9742 rowUpperX[iRow] = rowUpperY[iGet];
9743 tempIndex[iGet] = iRow;
9744 iGet++;
9745 } else {
9746 setRowStatus(iRow, basic);
9747 }
9748 }
9749 assert(iGet == presolvedModel->numberRows());
9750 CoinPackedMatrix matrixX;
9751 CoinBigIndex numberElementsOriginal = matrix_->getNumElements();
9752 const int *rowY = presolvedModel->matrix()->getIndices();
9753 const CoinBigIndex *columnStartY = presolvedModel->matrix()->getVectorStarts();
9754 const int *columnLengthY = presolvedModel->matrix()->getVectorLengths();
9755 const double *elementY = presolvedModel->matrix()->getElements();
9756 iGet = 0;
9757 CoinBigIndex put = 0;
9758 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9759 if (columnType[iColumn] < 11) {
9760 put += CoinMax(columnLength[iColumn], columnLengthY[iGet]);
9761 iGet++;
9762 } else {
9763 put += columnLength[iColumn];
9764 }
9765 }
9766 CoinBigIndex lastElement = 2 * (put + numberColumns_) + 1000;
9767 int spare = static_cast< int >((lastElement - put) / numberColumns_);
9768 //printf("spare %d\n",spare);
9769 matrixX.reserve(numberColumns_, lastElement + 2 * numberElementsOriginal);
9770 int *rowX = matrixX.getMutableIndices();
9771 CoinBigIndex *columnStartX = matrixX.getMutableVectorStarts();
9772 int *columnLengthX = matrixX.getMutableVectorLengths();
9773 double *elementX = matrixX.getMutableElements();
9774 const double *columnLowerY = presolvedModel->columnLower();
9775 const double *columnUpperY = presolvedModel->columnUpper();
9776 iGet = 0;
9777 put = 0;
9778 memcpy(objectiveX, this->objective(), numberColumns_ * sizeof(double));
9779 const double *objectiveY = presolvedModel->objective();
9780 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9781 columnStartX[iColumn] = put;
9782 if (columnType[iColumn] < 11) {
9783 CoinBigIndex next = put + columnLengthY[iGet];
9784 if (spare >= 0)
9785 next += CoinMax(columnLength[iColumn] - columnLengthY[iGet], 0) + spare;
9786 columnStatus[iColumn] = columnStatus2[iGet];
9787 columnActivity_[iColumn] = solution2[iGet];
9788 columnLowerX[iColumn] = columnLowerY[iGet];
9789 columnUpperX[iColumn] = columnUpperY[iGet];
9790 columnLengthX[iColumn] = columnLengthY[iGet];
9791 objectiveX[iColumn] = objectiveY[iGet];
9792 for (CoinBigIndex j = columnStartY[iGet]; j < columnStartY[iGet] + columnLengthY[iGet]; j++) {
9793 rowX[put] = tempIndex[rowY[j]];
9794 elementX[put++] = elementY[j];
9795 }
9796 columnActivity_[iColumn] = presolvedModel->columnActivity_[iGet];
9797 iGet++;
9798 columnType[iColumn] = 0;
9799 put = next;
9800 } else {
9801 put += CoinMax(columnLength[iColumn] + spare, 0);
9802 columnActivity_[iColumn] = 0.0;
9803 columnType[iColumn] = 1;
9804 columnLengthX[iColumn] = 0;
9805 setColumnStatus(iColumn, superBasic);
9806 }
9807 }
9808 assert(put <= lastElement);
9809 columnStartX[numberColumns_] = lastElement + numberElementsOriginal;
9810 assert(put <= lastElement);
9811 assert(iGet == numberColumns2);
9812 matrixX.times(columnActivity_, rowActivity_);
9813 if (optimizationDirection_ < 0) {
9814 for (int i = 0; i < numberColumns_; i++)
9815 objectiveX[i] = -objectiveX[i];
9816 }
9817 #if 0
9818 // get row copy
9819 CoinPackedMatrix rowCopy = *matrix();
9820 rowCopy.reverseOrdering();
9821 const int * column = rowCopy.getIndices();
9822 const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
9823 const int * rowLength = rowCopy.getVectorLengths();
9824 const double * elementByRow = rowCopy.getElements();
9825 #endif
9826 #if 1 //DEBUG_SOME > 0
9827 double *tempRhs = new double[numberRows_];
9828 #endif
9829 #ifndef NDEBUG
9830 bool checkMatrixAtEnd = true;
9831 #endif
9832 for (int i = nActions - 1; i >= 0; i--) {
9833 #if DEBUG_SOME > 0
9834 #if 1 //ndef NDEBUG
9835 memset(tempRhs, 0, numberRows_ * sizeof(double));
9836 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9837 //if (columnActivity_[iColumn]<columnLower_[iColumn]-1.0e-5||
9838 // columnActivity_[iColumn]>columnUpper_[iColumn]+1.0e-5)
9839 //printf ("Bad column %d %g <= %g <= %g\n",iColumn,
9840 // columnLower_[iColumn],columnActivity_[iColumn],columnUpper_[iColumn]);
9841 double value = columnActivity_[iColumn];
9842 for (CoinBigIndex j = columnStartX[iColumn];
9843 j < columnStartX[iColumn] + columnLengthX[iColumn]; j++) {
9844 int jRow = rowX[j];
9845 tempRhs[jRow] += value * elementX[j];
9846 }
9847 }
9848 int nBadRow = 0;
9849 for (int iRow = 0; iRow < numberRows_; iRow++) {
9850 if (rowLowerX[iRow] == COIN_DBL_MAX)
9851 continue;
9852 if (fabs(tempRhs[iRow] - rowActivity_[iRow]) > 1.0e-4)
9853 printf("Row %d temprhs %g rowActivity_ %g\n", iRow, tempRhs[iRow],
9854 rowActivity_[iRow]);
9855 if (tempRhs[iRow] < rowLowerX[iRow] - 1.0e-4 || tempRhs[iRow] > rowUpperX[iRow] + 1.0e-4) {
9856 printf("Row %d %g %g %g\n", iRow, rowLowerX[iRow],
9857 tempRhs[iRow], rowUpperX[iRow]);
9858 nBadRow++;
9859 }
9860 }
9861 assert(!nBadRow);
9862 #endif
9863 #ifndef NDEBUG
9864 if (i >= numberInitial && true) {
9865 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
9866 if (columnLengthX[iColumn]) {
9867 double djValue = objectiveX[iColumn];
9868 for (CoinBigIndex j = columnStartX[iColumn];
9869 j < columnStartX[iColumn] + columnLengthX[iColumn]; j++) {
9870 int jRow = rowX[j];
9871 djValue -= dual_[jRow] * elementX[j];
9872 }
9873 char inOut = columnType[iColumn] ? 'O' : 'I';
9874 if (djValue > 10.0 * dualTolerance_ && columnActivity_[iColumn] > columnLowerX[iColumn] + primalTolerance_)
9875 printf("bad dj on column %d lb dj %g in/out %c\n", iColumn, djValue, inOut);
9876 else if (djValue < -10.0 * dualTolerance_ && columnActivity_[iColumn] < columnUpperX[iColumn] - primalTolerance_)
9877 printf("bad dj on column %d ub dj %g in/out %c\n", iColumn, djValue, inOut);
9878 }
9879 }
9880 }
9881 #endif
9882 #endif
9883 int type = infoA[i].type;
9884 int iRow = -1;
9885 int iColumn = -1;
9886 #if DEBUG_SOME > 0
9887 printf("Action %d type %d\n", i, type);
9888 #ifndef NDEBUG
9889 checkBasis(this, rowType, columnType);
9890 #endif
9891 #endif
9892 switch (type) {
9893 case 1:
9894 case 4:
9895 case 8:
9896 case 9:
9897 // redundant
9898 {
9899 #ifndef NDEBUG
9900 if (type == 4)
9901 checkMatrixAtEnd = false;
9902 #endif
9903 clpPresolveInfo8 thisInfo;
9904 copyFromSave(restore, infoA[i], &thisInfo);
9905 iRow = thisInfo.row;
9906 // Insert row and modify RHS
9907 #ifdef CLP_USER_DRIVEN
9908 if (type >= 8) {
9909 thisInfo.tempElement = tempElement;
9910 thisInfo.tempIndex = tempIndex;
9911 thisInfo.rowLowerX = rowLowerX;
9912 thisInfo.rowUpperX = rowUpperX;
9913 eventHandler_->eventWithInfo(ClpEventHandler::modifyMatrixInMiniPostsolve, &thisInfo);
9914 } else {
9915 #endif
9916 if (rowLower_[iRow] > -1.0e30)
9917 rowLowerX[iRow] = rowLower_[iRow] - thisInfo.oldRowLower;
9918 else
9919 rowLowerX[iRow] = thisInfo.oldRowLower;
9920 if (rowUpper_[iRow] < 1.0e30)
9921 rowUpperX[iRow] = rowUpper_[iRow] - thisInfo.oldRowUpper;
9922 else
9923 rowUpperX[iRow] = thisInfo.oldRowUpper;
9924 #ifdef CLP_USER_DRIVEN
9925 }
9926 #endif
9927 int n = thisInfo.lengthRow;
9928 double rhs = 0.0;
9929 for (int i = 0; i < n; i++) {
9930 int iColumn = tempIndex[i];
9931 double value = tempElement[i];
9932 rhs += value * columnActivity_[iColumn];
9933 int length = columnLengthX[iColumn];
9934 CoinBigIndex start = columnStartX[iColumn];
9935 int nextColumn = forward[iColumn];
9936 CoinBigIndex startNext = columnStartX[nextColumn];
9937 if (start + length == startNext) {
9938 // need more
9939 moveAround(numberColumns_, numberElementsOriginal,
9940 iColumn, length + 1,
9941 forward, backward, columnStartX, columnLengthX,
9942 rowX, elementX);
9943 start = columnStartX[iColumn];
9944 }
9945 columnLengthX[iColumn]++;
9946 rowX[start + length] = iRow;
9947 elementX[start + length] = value;
9948 }
9949 rowActivity_[iRow] = rhs;
9950 rowType[iRow] = 0;
9951 assert(getRowStatus(iRow) == basic);
9952 }
9953 break;
9954 case 2:
9955 // sub
9956 {
9957 clpPresolveInfo2 thisInfo;
9958 copyFromSave(restore, infoA[i], &thisInfo);
9959 iColumn = thisInfo.column;
9960 columnType[iColumn] = 0;
9961 int jRowLower = thisInfo.row;
9962 int jRowUpper = thisInfo.row2;
9963 int length = columnLengthX[iColumn];
9964 CoinBigIndex start = columnStartX[iColumn];
9965 int nextColumn = forward[iColumn];
9966 CoinBigIndex startNext = columnStartX[nextColumn];
9967 if (start + length == startNext) {
9968 // need more
9969 moveAround(numberColumns_, numberElementsOriginal,
9970 iColumn, length + ((jRowLower < 0 || jRowUpper < 0) ? 1 : 2),
9971 forward, backward, columnStartX, columnLengthX,
9972 rowX, elementX);
9973 start = columnStartX[iColumn];
9974 }
9975 // modify
9976 double valueLower = thisInfo.coefficient;
9977 double valueUpper = thisInfo.coefficient2;
9978 if (jRowLower >= 0) {
9979 rowType[jRowLower] = 0;
9980 if (rowLower_[jRowLower] > -1.0e30)
9981 rowLowerX[jRowLower] = rowLower_[jRowLower] - thisInfo.oldRowLower;
9982 else
9983 rowLowerX[jRowLower] = thisInfo.oldRowLower;
9984 if (rowUpper_[jRowLower] < 1.0e30)
9985 rowUpperX[jRowLower] = rowUpper_[jRowLower] - thisInfo.oldRowUpper;
9986 else
9987 rowUpperX[jRowLower] = thisInfo.oldRowUpper;
9988 columnLengthX[iColumn]++;
9989 rowX[start + length] = jRowLower;
9990 elementX[start + length] = valueLower;
9991 rowActivity_[jRowLower] = valueLower * columnActivity_[iColumn];
9992 // start off with slack basic
9993 setRowStatus(jRowLower, basic);
9994 length++;
9995 }
9996 if (jRowUpper >= 0) {
9997 rowType[jRowUpper] = 0;
9998 if (rowLower_[jRowUpper] > -1.0e30)
9999 rowLowerX[jRowUpper] = rowLower_[jRowUpper] - thisInfo.oldRowLower2;
10000 else
10001 rowLowerX[jRowUpper] = thisInfo.oldRowLower2;
10002 if (rowUpper_[jRowUpper] < 1.0e30)
10003 rowUpperX[jRowUpper] = rowUpper_[jRowUpper] - thisInfo.oldRowUpper2;
10004 else
10005 rowUpperX[jRowUpper] = thisInfo.oldRowUpper2;
10006 columnLengthX[iColumn]++;
10007 rowX[start + length] = jRowUpper;
10008 elementX[start + length] = valueUpper;
10009 rowActivity_[jRowUpper] = valueUpper * columnActivity_[iColumn];
10010 // start off with slack basic
10011 setRowStatus(jRowUpper, basic);
10012 length++;
10013 }
10014 double djValue = objectiveX[iColumn];
10015 for (CoinBigIndex j = columnStartX[iColumn];
10016 j < columnStartX[iColumn] + columnLengthX[iColumn]; j++) {
10017 int jRow = rowX[j];
10018 djValue -= dual_[jRow] * elementX[j];
10019 }
10020 if (thisInfo.oldColumnLower == thisInfo.oldColumnUpper)
10021 djValue = 0.0;
10022 if (getColumnStatus(iColumn) != basic) {
10023 setColumnStatus(iColumn, superBasic);
10024 double solValue = columnActivity_[iColumn];
10025 bool hasToBeBasic = false;
10026 if (getColumnStatus(iColumn) != isFree) {
10027 if (solValue > thisInfo.oldColumnLower + primalTolerance_ && solValue < thisInfo.oldColumnUpper - primalTolerance_)
10028 hasToBeBasic = true;
10029 } else {
10030 hasToBeBasic = fabs(djValue) > dualTolerance_;
10031 }
10032 if (solValue <= thisInfo.oldColumnLower + primalTolerance_ && djValue < -dualTolerance_) {
10033 #if DEBUG_SOME > 1
10034 printf("odd column %d at lb of %g has dj of %g\n",
10035 iColumn, thisInfo.oldColumnLower, djValue);
10036 #endif
10037 hasToBeBasic = true;
10038 } else if (solValue >= thisInfo.oldColumnUpper - primalTolerance_ && djValue > dualTolerance_) {
10039 #if DEBUG_SOME > 1
10040 printf("odd column %d at ub of %g has dj of %g\n",
10041 iColumn, thisInfo.oldColumnUpper, djValue);
10042 #endif
10043 hasToBeBasic = true;
10044 }
10045 if (hasToBeBasic) {
10046 if (jRowLower >= 0 && jRowUpper >= 0) {
10047 // choose
10048 #if DEBUG_SOME > 1
10049 printf("lower row %d %g <= %g <= %g\n",
10050 jRowLower, rowLowerX[jRowLower], rowActivity_[jRowLower],
10051 rowUpperX[jRowLower]);
10052 #endif
10053 double awayLower = CoinMin(rowActivity_[jRowLower] - rowLowerX[jRowLower],
10054 rowUpperX[jRowLower] - rowActivity_[jRowLower]);
10055 #if DEBUG_SOME > 1
10056 printf("upper row %d %g <= %g <= %g\n",
10057 jRowUpper, rowLowerX[jRowUpper], rowActivity_[jRowUpper],
10058 rowUpperX[jRowUpper]);
10059 #endif
10060 double awayUpper = CoinMin(rowActivity_[jRowUpper] - rowLowerX[jRowUpper],
10061 rowUpperX[jRowUpper] - rowActivity_[jRowUpper]);
10062 if (awayLower > awayUpper)
10063 jRowLower = -1;
10064 }
10065 if (jRowLower < 0) {
10066 setRowStatus(jRowUpper, superBasic);
10067 setColumnStatus(iColumn, basic);
10068 dual_[jRowUpper] = djValue / valueUpper;
10069 } else {
10070 setRowStatus(jRowLower, superBasic);
10071 setColumnStatus(iColumn, basic);
10072 dual_[jRowLower] = djValue / valueLower;
10073 }
10074 }
10075 }
10076 columnLowerX[iColumn] = thisInfo.oldColumnLower;
10077 columnUpperX[iColumn] = thisInfo.oldColumnUpper;
10078 }
10079 break;
10080 case 11:
10081 // movable column
10082 {
10083 clpPresolveInfo11 thisInfo;
10084 copyFromSave(restore, infoA[i], &thisInfo);
10085 iColumn = thisInfo.column;
10086 columnType[iColumn] = 0;
10087 assert(!columnLengthX[iColumn]);
10088 int newLength = thisInfo.lengthColumn;
10089 CoinBigIndex start = columnStartX[iColumn];
10090 int nextColumn = forward[iColumn];
10091 CoinBigIndex startNext = columnStartX[nextColumn];
10092 if (start + newLength > startNext) {
10093 // need more
10094 moveAround(numberColumns_, numberElementsOriginal,
10095 iColumn, newLength,
10096 forward, backward, columnStartX, columnLengthX,
10097 rowX, elementX);
10098 start = columnStartX[iColumn];
10099 }
10100 columnLengthX[iColumn] = newLength;
10101 memcpy(rowX + start, tempIndex, newLength * sizeof(int));
10102 memcpy(elementX + start, tempElement, newLength * sizeof(double));
10103 double solValue = thisInfo.fixedTo;
10104 columnActivity_[iColumn] = solValue;
10105 if (solValue) {
10106 for (CoinBigIndex j = columnStartX[iColumn];
10107 j < columnStartX[iColumn] + columnLengthX[iColumn]; j++) {
10108 int jRow = rowX[j];
10109 double value = elementX[j] * solValue;
10110 rowActivity_[jRow] += value;
10111 if (rowLowerX[jRow] > -1.0e30)
10112 rowLowerX[jRow] += value;
10113 if (rowUpperX[jRow] < 1.0e30)
10114 rowUpperX[jRow] += value;
10115 }
10116 }
10117 double djValue = objectiveX[iColumn];
10118 for (CoinBigIndex j = columnStartX[iColumn];
10119 j < columnStartX[iColumn] + columnLengthX[iColumn]; j++) {
10120 int jRow = rowX[j];
10121 djValue -= dual_[jRow] * elementX[j];
10122 }
10123 if (thisInfo.oldColumnLower == thisInfo.oldColumnUpper)
10124 djValue = 0.0;
10125 if (getColumnStatus(iColumn) != basic) {
10126 setColumnStatus(iColumn, superBasic);
10127 bool hasToBeBasic = false;
10128 if (getColumnStatus(iColumn) != isFree) {
10129 if (solValue > thisInfo.oldColumnLower + primalTolerance_ && solValue < thisInfo.oldColumnUpper - primalTolerance_)
10130 hasToBeBasic = true;
10131 } else {
10132 hasToBeBasic = fabs(djValue) > dualTolerance_;
10133 }
10134 if (solValue <= thisInfo.oldColumnLower + primalTolerance_ && djValue < -dualTolerance_) {
10135 #if DEBUG_SOME > 1
10136 printf("odd column %d at lb of %g has dj of %g\n",
10137 iColumn, thisInfo.oldColumnLower, djValue);
10138 #endif
10139 hasToBeBasic = true;
10140 } else if (solValue >= thisInfo.oldColumnUpper - primalTolerance_ && djValue > dualTolerance_) {
10141 #if DEBUG_SOME > 1
10142 printf("odd column %d at ub of %g has dj of %g\n",
10143 iColumn, thisInfo.oldColumnUpper, djValue);
10144 #endif
10145 hasToBeBasic = true;
10146 }
10147 if (hasToBeBasic) {
10148 //abort();
10149 //setRowStatus(iRow,superBasic);
10150 setColumnStatus(iColumn, basic);
10151 //dual_[iRow]=djValue/value;
10152 }
10153 }
10154 columnLowerX[iColumn] = thisInfo.oldColumnLower;
10155 columnUpperX[iColumn] = thisInfo.oldColumnUpper;
10156 }
10157 break;
10158 case 13:
10159 // empty (or initially fixed) column
10160 {
10161 clpPresolveInfo13 thisInfo;
10162 copyFromSave(restore, infoA[i], &thisInfo);
10163 iColumn = thisInfo.column;
10164 columnType[iColumn] = 0;
10165 columnLowerX[iColumn] = thisInfo.oldColumnLower;
10166 columnUpperX[iColumn] = thisInfo.oldColumnUpper;
10167 assert(!columnLengthX[iColumn]);
10168 int newLength = columnLength[iColumn];
10169 CoinBigIndex startOriginal = columnStart[iColumn];
10170 double solValue = columnLower_[iColumn];
10171 columnActivity_[iColumn] = solValue;
10172 if (newLength && solValue) {
10173 for (CoinBigIndex j = startOriginal; j < startOriginal + newLength; j++) {
10174 int iRow = row[j];
10175 double value = element[j] * solValue;
10176 rowActivity_[iRow] += value;
10177 double lower = rowLowerX[iRow];
10178 if (lower > -1.0e20)
10179 rowLowerX[iRow] = lower + value;
10180 double upper = rowUpperX[iRow];
10181 if (upper < 1.0e20)
10182 rowUpperX[iRow] = upper + value;
10183 }
10184 }
10185 #ifndef NDEBUG
10186 // copy from original
10187 CoinBigIndex start = columnStartX[iColumn];
10188 int nextColumn = forward[iColumn];
10189 CoinBigIndex startNext = columnStartX[nextColumn];
10190 if (start + newLength > startNext) {
10191 // need more
10192 moveAround(numberColumns_, numberElementsOriginal,
10193 iColumn, newLength,
10194 forward, backward, columnStartX, columnLengthX,
10195 rowX, elementX);
10196 start = columnStartX[iColumn];
10197 }
10198 columnLengthX[iColumn] = newLength;
10199 memcpy(rowX + start, row + startOriginal, newLength * sizeof(int));
10200 memcpy(elementX + start, element + startOriginal, newLength * sizeof(double));
10201 #endif
10202 }
10203 break;
10204 case 14:
10205 // doubleton
10206 {
10207 clpPresolveInfo14 thisInfo;
10208 copyFromSave(restore, infoA[i], &thisInfo);
10209 iRow = thisInfo.row;
10210 rowType[iRow] = 0;
10211 int iColumn1 = thisInfo.column;
10212 int iColumn2 = thisInfo.column2;
10213 columnType[iColumn2] = 0;
10214 double value1 = thisInfo.value1;
10215 int length = columnLengthX[iColumn1];
10216 CoinBigIndex start = columnStartX[iColumn1];
10217 for (int i = 0; i < length; i++) {
10218 int jRow = rowX[i + start];
10219 array[jRow] = elementX[i + start];
10220 whichRows2[i] = jRow;
10221 }
10222 int n = length;
10223 length = columnLengthX[iColumn2];
10224 assert(!length);
10225 int newLength = thisInfo.lengthColumn2;
10226 start = columnStartX[iColumn2];
10227 int nextColumn = forward[iColumn2];
10228 CoinBigIndex startNext = columnStartX[nextColumn];
10229 if (start + newLength > startNext) {
10230 // need more
10231 moveAround(numberColumns_, numberElementsOriginal,
10232 iColumn2, newLength,
10233 forward, backward, columnStartX, columnLengthX,
10234 rowX, elementX);
10235 start = columnStartX[iColumn2];
10236 }
10237 columnLengthX[iColumn2] = newLength;
10238 memcpy(rowX + start, tempIndex, newLength * sizeof(int));
10239 memcpy(elementX + start, tempElement, newLength * sizeof(double));
10240 double value2 = 0.0;
10241 for (int i = 0; i < newLength; i++) {
10242 int jRow = tempIndex[i];
10243 double value = tempElement[i];
10244 if (jRow == iRow) {
10245 value2 = value;
10246 break;
10247 }
10248 }
10249 assert(value2);
10250 double rhs = thisInfo.rhs;
10251 double multiplier1 = rhs / value2;
10252 double multiplier = value1 / value2;
10253 for (int i = 0; i < newLength; i++) {
10254 int jRow = tempIndex[i];
10255 double value = array[jRow];
10256 double valueNew = value + multiplier * tempElement[i];
10257 double rhsMod = multiplier1 * tempElement[i];
10258 if (rowLowerX[jRow] > -1.0e30)
10259 rowLowerX[jRow] += rhsMod;
10260 if (rowUpperX[jRow] < 1.0e30)
10261 rowUpperX[jRow] += rhsMod;
10262 rowActivity_[jRow] += rhsMod;
10263 if (!value) {
10264 array[jRow] = valueNew;
10265 whichRows2[n++] = jRow;
10266 } else {
10267 if (!valueNew)
10268 valueNew = 1.0e-100;
10269 array[jRow] = valueNew;
10270 }
10271 }
10272 length = 0;
10273 for (int i = 0; i < n; i++) {
10274 int jRow = whichRows2[i];
10275 double value = array[jRow];
10276 array[jRow] = 0.0;
10277 if (fabs(value) < 1.0e-13)
10278 value = 0.0;
10279 if (value) {
10280 tempIndex[length] = jRow;
10281 tempElement[length++] = value;
10282 }
10283 }
10284 start = columnStartX[iColumn1];
10285 nextColumn = forward[iColumn1];
10286 startNext = columnStartX[nextColumn];
10287 if (start + length > startNext) {
10288 // need more
10289 moveAround(numberColumns_, numberElementsOriginal,
10290 iColumn1, length,
10291 forward, backward, columnStartX, columnLengthX,
10292 rowX, elementX);
10293 start = columnStartX[iColumn1];
10294 }
10295 columnLengthX[iColumn1] = length;
10296 memcpy(rowX + start, tempIndex, length * sizeof(int));
10297 memcpy(elementX + start, tempElement, length * sizeof(double));
10298 objectiveX[iColumn2] = thisInfo.oldObjective2;
10299 objectiveX[iColumn1] += objectiveX[iColumn2] * multiplier;
10300 //offset += rhs*(objectiveX[iColumn2]*multiplier);
10301 double value = multiplier1 - columnActivity_[iColumn1] * multiplier;
10302 #if DEBUG_SOME > 0
10303 printf("type14 column2 %d rhs %g value1 %g - value %g\n",
10304 iColumn2, thisInfo.rhs, thisInfo.value1, value);
10305 #endif
10306 columnActivity_[iColumn2] = value;
10307 double djValue1 = objectiveX[iColumn1];
10308 for (CoinBigIndex j = columnStartX[iColumn1];
10309 j < columnStartX[iColumn1] + columnLengthX[iColumn1]; j++) {
10310 int jRow = rowX[j];
10311 djValue1 -= dual_[jRow] * elementX[j];
10312 }
10313 bool fixed = (thisInfo.oldColumnLower == thisInfo.oldColumnUpper);
10314 columnLowerX[iColumn1] = thisInfo.oldColumnLower;
10315 columnUpperX[iColumn1] = thisInfo.oldColumnUpper;
10316 double djValue2 = objectiveX[iColumn2];
10317 for (CoinBigIndex j = columnStartX[iColumn2];
10318 j < columnStartX[iColumn2] + columnLengthX[iColumn2]; j++) {
10319 int jRow = rowX[j];
10320 djValue2 -= dual_[jRow] * elementX[j];
10321 }
10322 bool fixed2 = (thisInfo.oldColumnLower2 == thisInfo.oldColumnUpper2);
10323 columnLowerX[iColumn2] = thisInfo.oldColumnLower2;
10324 columnUpperX[iColumn2] = thisInfo.oldColumnUpper2;
10325 if (getColumnStatus(iColumn1) != basic) {
10326 setColumnStatus(iColumn1, superBasic);
10327 double solValue = columnActivity_[iColumn1];
10328 double lowerValue = columnLowerX[iColumn1];
10329 double upperValue = columnUpperX[iColumn1];
10330 setColumnStatus(iColumn2, superBasic);
10331 double solValue2 = columnActivity_[iColumn2];
10332 double lowerValue2 = columnLowerX[iColumn2];
10333 double upperValue2 = columnUpperX[iColumn2];
10334 int choice = -1;
10335 double best = COIN_DBL_MAX;
10336 for (int iTry = 0; iTry < 3; iTry++) {
10337 double pi = 0.0;
10338 switch (iTry) {
10339 // leave
10340 case 0:
10341 break;
10342 // iColumn1 basic
10343 case 1:
10344 pi = djValue1 / value1;
10345 break;
10346 // iColumn2 basic
10347 case 2:
10348 pi = djValue2 / value2;
10349 break;
10350 }
10351 // djs
10352 double dj1 = djValue1 - value1 * pi;
10353 ;
10354 double bad1 = 0.0;
10355 if (!fixed) {
10356 if (dj1 < -dualTolerance_ && solValue <= lowerValue + primalTolerance_)
10357 bad1 = -dj1;
10358 else if (dj1 > dualTolerance_ && solValue >= upperValue - primalTolerance_)
10359 bad1 = dj1;
10360 }
10361 double dj2 = djValue2 - value2 * pi;
10362 double bad2 = 0.0;
10363 if (!fixed2) {
10364 if (dj2 < -dualTolerance_ && solValue2 <= lowerValue2 + primalTolerance_)
10365 bad2 = -dj2;
10366 else if (dj2 > dualTolerance_ && solValue2 >= upperValue2 - primalTolerance_)
10367 bad2 = dj2;
10368 }
10369 if (CoinMax(bad1, bad2) < best) {
10370 best = CoinMax(bad1, bad2);
10371 choice = iTry;
10372 }
10373 }
10374 // but values override
10375 if (solValue > lowerValue + primalTolerance_ && solValue < upperValue - primalTolerance_) {
10376 if (getColumnStatus(iColumn1) != isFree || fabs(djValue1) > dualTolerance_)
10377 choice = 1;
10378 } else if (solValue2 > lowerValue2 + primalTolerance_ && solValue2 < upperValue2 - primalTolerance_) {
10379 if (getColumnStatus(iColumn2) != isFree || fabs(djValue2) > dualTolerance_)
10380 choice = 2;
10381 }
10382 if (choice == 1) {
10383 // iColumn1 in basis
10384 setRowStatus(iRow, superBasic);
10385 setColumnStatus(iColumn1, basic);
10386 dual_[iRow] = djValue1 / value1;
10387 } else if (choice == 2) {
10388 // iColumn2 in basis
10389 setRowStatus(iRow, superBasic);
10390 setColumnStatus(iColumn2, basic);
10391 dual_[iRow] = djValue2 / value2;
10392 }
10393 } else {
10394 if (fabs(djValue1) > 10.0 * dualTolerance_) {
10395 // iColumn2 in basis
10396 setRowStatus(iRow, superBasic);
10397 setColumnStatus(iColumn2, basic);
10398 dual_[iRow] = djValue2 / value2;
10399 } else {
10400 // do we need iColumn2 in basis
10401 double solValue2 = columnActivity_[iColumn2];
10402 double lowerValue2 = columnLowerX[iColumn2];
10403 double upperValue2 = columnUpperX[iColumn2];
10404 if (solValue2 > lowerValue2 + primalTolerance_ && solValue2 < upperValue2 - primalTolerance_ && getColumnStatus(iColumn2) != isFree) {
10405 // iColumn2 in basis
10406 setRowStatus(iRow, superBasic);
10407 setColumnStatus(iColumn2, basic);
10408 dual_[iRow] = djValue2 / value2;
10409 }
10410 }
10411 }
10412 rowLowerX[iRow] = rhs;
10413 rowUpperX[iRow] = rhs;
10414 //abort();
10415 }
10416 break;
10417 }
10418 }
10419 #ifndef NDEBUG
10420 #ifndef CLP_USER_DRIVEN
10421 // otherwise user may be fudging rhs
10422 for (int iRow = 0; iRow < numberRows_; iRow++) {
10423 #ifndef CLP_USER_DRIVEN
10424 assert(fabs(rowLower_[iRow] - rowLowerX[iRow]) < 1.0e-4);
10425 assert(fabs(rowUpper_[iRow] - rowUpperX[iRow]) < 1.0e-4);
10426 #else
10427 if (fabs(rowLower_[iRow] - rowLowerX[iRow]) > 1.0e-4 || fabs(rowUpper_[iRow] - rowUpperX[iRow]) > 1.0e-4)
10428 printf("USER row %d lower,x %g %g upper,x %g %g\n", iRow, rowLower_[iRow], rowLowerX[iRow],
10429 rowUpper_[iRow], rowUpperX[iRow]);
10430
10431 #endif
10432 }
10433 double *objective = this->objective();
10434 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
10435 assert(columnLower_[iColumn] == columnLowerX[iColumn]);
10436 assert(columnUpper_[iColumn] == columnUpperX[iColumn]);
10437 assert(fabs(objective[iColumn] - objectiveX[iColumn] * optimizationDirection_) < 1.0e-3);
10438 }
10439 #endif
10440 if (checkMatrixAtEnd) {
10441 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
10442 assert(columnLength[iColumn] == columnLengthX[iColumn]);
10443 int length = columnLengthX[iColumn];
10444 CoinBigIndex startX = columnStartX[iColumn];
10445 CoinSort_2(rowX + startX, rowX + startX + length, elementX + startX);
10446 CoinBigIndex start = columnStart[iColumn];
10447 memcpy(tempIndex, row + start, length * sizeof(int));
10448 memcpy(tempElement, element + start, length * sizeof(double));
10449 CoinSort_2(tempIndex, tempIndex + length, tempElement);
10450 for (int i = 0; i < length; i++) {
10451 assert(rowX[i + startX] == tempIndex[i]);
10452 assert(fabs(elementX[i + startX] - tempElement[i]) < 1.0e-5);
10453 }
10454 }
10455 }
10456 #endif
10457 delete[] rowType;
10458 delete[] tempIndex;
10459 // use temp matrix and do this every action
10460 #if DEBUG_SOME > 0
10461 matrix()->times(columnActivity_, rowActivity_);
10462 for (int i = 0; i < numberColumns_; i++)
10463 assert(columnActivity_[i] >= columnLower_[i] - 1.0e-5 && columnActivity_[i] <= columnUpper_[i] + 1.0e-5);
10464 int nBad = 0;
10465 for (int i = 0; i < numberRows_; i++) {
10466 if (rowActivity_[i] < rowLower_[i] - 1.0e-5 || rowActivity_[i] > rowUpper_[i] + 1.0e-5) {
10467 printf("Row %d %g %g %g\n", i, rowLower_[i],
10468 rowActivity_[i], rowUpper_[i]);
10469 nBad++;
10470 }
10471 }
10472 ClpTraceDebug(!nBad);
10473 #endif
10474 #if 1 //DEBUG_SOME > 0
10475 delete[] tempRhs;
10476 #endif
10477 delete infoX;
10478 delete[] infoA;
10479 delete[] rowLowerX;
10480 }
10481 // mini presolve and solve
10482 void
10483 ClpSimplex::miniSolve(char *rowType, char *columnType, int algorithm, int startUp)
10484 {
10485 listInfo *info = NULL;
10486 ClpSimplex *small2 = miniPresolve(rowType, columnType, reinterpret_cast< void ** >(&info));
10487 if (algorithm < 0)
10488 small2->dual(startUp);
10489 else
10490 small2->primal(startUp);
10491 miniPostsolve(small2, info);
10492 delete info;
10493 }
10494 // Create a string of commands to guess at best strategy for model
10495 // At present mode is ignored
10496 char *
10497 ClpSimplexOther::guess(int mode) const
10498 {
10499 if (!numberColumns_) {
10500 handler_->message(CLP_GENERAL, messages_)
10501 << "Null model" << CoinMessageEol;
10502 return NULL;
10503 }
10504 char *environment = new char[100];
10505 double *obj = CoinCopyOfArray(objective(), numberColumns_);
10506 std::sort(obj, obj + numberColumns_);
10507 bool allInt = true;
10508 double average = 0.0;
10509 double median = obj[numberColumns_ / 2];
10510 for (int i = 0; i < numberColumns_; i++) {
10511 if (!isInteger(i) && columnUpper_[i] > columnLower_[i])
10512 allInt = false;
10513 average += obj[i];
10514 }
10515 delete[] obj;
10516 average /= numberColumns_;
10517 if (allInt) {
10518 if (average <= 0.0086207)
10519 sprintf(environment, "-idiot 30 -pertvalue -1483 -primals");
10520 else
10521 sprintf(environment, "-idiot 60 -primals");
10522 } else {
10523 if (median <= 0.75)
10524 sprintf(environment, "-dualpivot pesteep -psi 1.0 -pertv 52 -duals");
10525 else
10526 sprintf(environment, "-idiot 80 -primals");
10527 }
10528 char line[140];
10529 sprintf(line, "%s %s", "Commands generated by guess -", environment);
10530 handler_->message(CLP_GENERAL, messages_)
10531 << line << CoinMessageEol;
10532 return environment;
10533 }
10534