1/* $Id: ClpSimplex.cpp 1871 2012-07-30 10:21:53Z forrest $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others. All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6//#undef NDEBUG
7
8#include "ClpConfig.h"
9
10#include "CoinPragma.hpp"
11#include <math.h>
12
13#if SLIM_CLP==2
14#define SLIM_NOIO
15#endif
16#include "CoinHelperFunctions.hpp"
17#include "CoinFloatEqual.hpp"
18#include "ClpSimplex.hpp"
19#include "ClpFactorization.hpp"
20#include "ClpPackedMatrix.hpp"
21#include "CoinIndexedVector.hpp"
22#include "ClpDualRowDantzig.hpp"
23#include "ClpDualRowSteepest.hpp"
24#include "ClpPrimalColumnDantzig.hpp"
25#include "ClpPrimalColumnSteepest.hpp"
26#include "ClpNonLinearCost.hpp"
27#include "ClpMessage.hpp"
28#include "ClpEventHandler.hpp"
29#include "ClpLinearObjective.hpp"
30#include "ClpHelperFunctions.hpp"
31#include "CoinModel.hpp"
32#include "CoinLpIO.hpp"
33#include <cfloat>
34
35#include <string>
36#include <stdio.h>
37#include <iostream>
38//#############################################################################
39
40ClpSimplex::ClpSimplex (bool emptyMessages) :
41
42 ClpModel(emptyMessages),
43 bestPossibleImprovement_(0.0),
44 zeroTolerance_(1.0e-13),
45 columnPrimalSequence_(-2),
46 rowPrimalSequence_(-2),
47 bestObjectiveValue_(-COIN_DBL_MAX),
48 moreSpecialOptions_(2),
49 baseIteration_(0),
50 primalToleranceToGetOptimal_(-1.0),
51 largeValue_(1.0e15),
52 largestPrimalError_(0.0),
53 largestDualError_(0.0),
54 alphaAccuracy_(-1.0),
55 dualBound_(1.0e10),
56 alpha_(0.0),
57 theta_(0.0),
58 lowerIn_(0.0),
59 valueIn_(0.0),
60 upperIn_(-COIN_DBL_MAX),
61 dualIn_(0.0),
62 lowerOut_(-1),
63 valueOut_(-1),
64 upperOut_(-1),
65 dualOut_(-1),
66 dualTolerance_(1.0e-7),
67 primalTolerance_(1.0e-7),
68 sumDualInfeasibilities_(0.0),
69 sumPrimalInfeasibilities_(0.0),
70 infeasibilityCost_(1.0e10),
71 sumOfRelaxedDualInfeasibilities_(0.0),
72 sumOfRelaxedPrimalInfeasibilities_(0.0),
73 acceptablePivot_(1.0e-8),
74 lower_(NULL),
75 rowLowerWork_(NULL),
76 columnLowerWork_(NULL),
77 upper_(NULL),
78 rowUpperWork_(NULL),
79 columnUpperWork_(NULL),
80 cost_(NULL),
81 rowObjectiveWork_(NULL),
82 objectiveWork_(NULL),
83 sequenceIn_(-1),
84 directionIn_(-1),
85 sequenceOut_(-1),
86 directionOut_(-1),
87 pivotRow_(-1),
88 lastGoodIteration_(-100),
89 dj_(NULL),
90 rowReducedCost_(NULL),
91 reducedCostWork_(NULL),
92 solution_(NULL),
93 rowActivityWork_(NULL),
94 columnActivityWork_(NULL),
95 numberDualInfeasibilities_(0),
96 numberDualInfeasibilitiesWithoutFree_(0),
97 numberPrimalInfeasibilities_(100),
98 numberRefinements_(0),
99 pivotVariable_(NULL),
100 factorization_(NULL),
101 savedSolution_(NULL),
102 numberTimesOptimal_(0),
103 disasterArea_(NULL),
104 changeMade_(1),
105 algorithm_(0),
106 forceFactorization_(-1),
107 perturbation_(100),
108 nonLinearCost_(NULL),
109 lastBadIteration_(-999999),
110 lastFlaggedIteration_(-999999),
111 numberFake_(0),
112 numberChanged_(0),
113 progressFlag_(0),
114 firstFree_(-1),
115 numberExtraRows_(0),
116 maximumBasic_(0),
117 dontFactorizePivots_(0),
118 incomingInfeasibility_(1.0),
119 allowedInfeasibility_(10.0),
120 automaticScale_(0),
121 maximumPerturbationSize_(0),
122 perturbationArray_(NULL),
123 baseModel_(NULL)
124{
125 int i;
126 for (i = 0; i < 6; i++) {
127 rowArray_[i] = NULL;
128 columnArray_[i] = NULL;
129 }
130 for (i = 0; i < 4; i++) {
131 spareIntArray_[i] = 0;
132 spareDoubleArray_[i] = 0.0;
133 }
134 saveStatus_ = NULL;
135 // get an empty factorization so we can set tolerances etc
136 getEmptyFactorization();
137 // Say sparse
138 factorization_->sparseThreshold(1);
139 // say Steepest pricing
140 dualRowPivot_ = new ClpDualRowSteepest();
141 // say Steepest pricing
142 primalColumnPivot_ = new ClpPrimalColumnSteepest();
143 solveType_ = 1; // say simplex based life form
144
145}
146
147// Subproblem constructor
148ClpSimplex::ClpSimplex ( const ClpModel * rhs,
149 int numberRows, const int * whichRow,
150 int numberColumns, const int * whichColumn,
151 bool dropNames, bool dropIntegers, bool fixOthers)
152 : ClpModel(rhs, numberRows, whichRow,
153 numberColumns, whichColumn, dropNames, dropIntegers),
154 bestPossibleImprovement_(0.0),
155 zeroTolerance_(1.0e-13),
156 columnPrimalSequence_(-2),
157 rowPrimalSequence_(-2),
158 bestObjectiveValue_(-COIN_DBL_MAX),
159 moreSpecialOptions_(2),
160 baseIteration_(0),
161 primalToleranceToGetOptimal_(-1.0),
162 largeValue_(1.0e15),
163 largestPrimalError_(0.0),
164 largestDualError_(0.0),
165 alphaAccuracy_(-1.0),
166 dualBound_(1.0e10),
167 alpha_(0.0),
168 theta_(0.0),
169 lowerIn_(0.0),
170 valueIn_(0.0),
171 upperIn_(-COIN_DBL_MAX),
172 dualIn_(0.0),
173 lowerOut_(-1),
174 valueOut_(-1),
175 upperOut_(-1),
176 dualOut_(-1),
177 dualTolerance_(1.0e-7),
178 primalTolerance_(1.0e-7),
179 sumDualInfeasibilities_(0.0),
180 sumPrimalInfeasibilities_(0.0),
181 infeasibilityCost_(1.0e10),
182 sumOfRelaxedDualInfeasibilities_(0.0),
183 sumOfRelaxedPrimalInfeasibilities_(0.0),
184 acceptablePivot_(1.0e-8),
185 lower_(NULL),
186 rowLowerWork_(NULL),
187 columnLowerWork_(NULL),
188 upper_(NULL),
189 rowUpperWork_(NULL),
190 columnUpperWork_(NULL),
191 cost_(NULL),
192 rowObjectiveWork_(NULL),
193 objectiveWork_(NULL),
194 sequenceIn_(-1),
195 directionIn_(-1),
196 sequenceOut_(-1),
197 directionOut_(-1),
198 pivotRow_(-1),
199 lastGoodIteration_(-100),
200 dj_(NULL),
201 rowReducedCost_(NULL),
202 reducedCostWork_(NULL),
203 solution_(NULL),
204 rowActivityWork_(NULL),
205 columnActivityWork_(NULL),
206 numberDualInfeasibilities_(0),
207 numberDualInfeasibilitiesWithoutFree_(0),
208 numberPrimalInfeasibilities_(100),
209 numberRefinements_(0),
210 pivotVariable_(NULL),
211 factorization_(NULL),
212 savedSolution_(NULL),
213 numberTimesOptimal_(0),
214 disasterArea_(NULL),
215 changeMade_(1),
216 algorithm_(0),
217 forceFactorization_(-1),
218 perturbation_(100),
219 nonLinearCost_(NULL),
220 lastBadIteration_(-999999),
221 lastFlaggedIteration_(-999999),
222 numberFake_(0),
223 numberChanged_(0),
224 progressFlag_(0),
225 firstFree_(-1),
226 numberExtraRows_(0),
227 maximumBasic_(0),
228 dontFactorizePivots_(0),
229 incomingInfeasibility_(1.0),
230 allowedInfeasibility_(10.0),
231 automaticScale_(0),
232 maximumPerturbationSize_(0),
233 perturbationArray_(NULL),
234 baseModel_(NULL)
235{
236 int i;
237 for (i = 0; i < 6; i++) {
238 rowArray_[i] = NULL;
239 columnArray_[i] = NULL;
240 }
241 for (i = 0; i < 4; i++) {
242 spareIntArray_[i] = 0;
243 spareDoubleArray_[i] = 0.0;
244 }
245 saveStatus_ = NULL;
246 // get an empty factorization so we can set tolerances etc
247 getEmptyFactorization();
248 // say Steepest pricing
249 dualRowPivot_ = new ClpDualRowSteepest();
250 // say Steepest pricing
251 primalColumnPivot_ = new ClpPrimalColumnSteepest();
252 solveType_ = 1; // say simplex based life form
253 if (fixOthers) {
254 int numberOtherColumns = rhs->numberColumns();
255 int numberOtherRows = rhs->numberRows();
256 double * solution = new double [numberOtherColumns];
257 CoinZeroN(solution, numberOtherColumns);
258 int i;
259 for (i = 0; i < numberColumns; i++) {
260 int iColumn = whichColumn[i];
261 if (solution[iColumn])
262 fixOthers = false; // duplicates
263 solution[iColumn] = 1.0;
264 }
265 if (fixOthers) {
266 const double * otherSolution = rhs->primalColumnSolution();
267 const double * objective = rhs->objective();
268 double offset = 0.0;
269 for (i = 0; i < numberOtherColumns; i++) {
270 if (solution[i]) {
271 solution[i] = 0.0; // in
272 } else {
273 solution[i] = otherSolution[i];
274 offset += objective[i] * otherSolution[i];
275 }
276 }
277 double * rhsModification = new double [numberOtherRows];
278 CoinZeroN(rhsModification, numberOtherRows);
279 rhs->matrix()->times(solution, rhsModification) ;
280 for ( i = 0; i < numberRows; i++) {
281 int iRow = whichRow[i];
282 if (rowLower_[i] > -1.0e20)
283 rowLower_[i] -= rhsModification[iRow];
284 if (rowUpper_[i] < 1.0e20)
285 rowUpper_[i] -= rhsModification[iRow];
286 }
287 delete [] rhsModification;
288 setObjectiveOffset(rhs->objectiveOffset() - offset);
289 // And set objective value to match
290 setObjectiveValue(rhs->objectiveValue());
291 }
292 delete [] solution;
293 }
294}
295// Subproblem constructor
296ClpSimplex::ClpSimplex ( const ClpSimplex * rhs,
297 int numberRows, const int * whichRow,
298 int numberColumns, const int * whichColumn,
299 bool dropNames, bool dropIntegers, bool fixOthers)
300 : ClpModel(rhs, numberRows, whichRow,
301 numberColumns, whichColumn, dropNames, dropIntegers),
302 bestPossibleImprovement_(0.0),
303 zeroTolerance_(1.0e-13),
304 columnPrimalSequence_(-2),
305 rowPrimalSequence_(-2),
306 bestObjectiveValue_(-COIN_DBL_MAX),
307 moreSpecialOptions_(2),
308 baseIteration_(0),
309 primalToleranceToGetOptimal_(-1.0),
310 largeValue_(1.0e15),
311 largestPrimalError_(0.0),
312 largestDualError_(0.0),
313 alphaAccuracy_(-1.0),
314 dualBound_(1.0e10),
315 alpha_(0.0),
316 theta_(0.0),
317 lowerIn_(0.0),
318 valueIn_(0.0),
319 upperIn_(-COIN_DBL_MAX),
320 dualIn_(0.0),
321 lowerOut_(-1),
322 valueOut_(-1),
323 upperOut_(-1),
324 dualOut_(-1),
325 dualTolerance_(rhs->dualTolerance_),
326 primalTolerance_(rhs->primalTolerance_),
327 sumDualInfeasibilities_(0.0),
328 sumPrimalInfeasibilities_(0.0),
329 infeasibilityCost_(1.0e10),
330 sumOfRelaxedDualInfeasibilities_(0.0),
331 sumOfRelaxedPrimalInfeasibilities_(0.0),
332 acceptablePivot_(1.0e-8),
333 lower_(NULL),
334 rowLowerWork_(NULL),
335 columnLowerWork_(NULL),
336 upper_(NULL),
337 rowUpperWork_(NULL),
338 columnUpperWork_(NULL),
339 cost_(NULL),
340 rowObjectiveWork_(NULL),
341 objectiveWork_(NULL),
342 sequenceIn_(-1),
343 directionIn_(-1),
344 sequenceOut_(-1),
345 directionOut_(-1),
346 pivotRow_(-1),
347 lastGoodIteration_(-100),
348 dj_(NULL),
349 rowReducedCost_(NULL),
350 reducedCostWork_(NULL),
351 solution_(NULL),
352 rowActivityWork_(NULL),
353 columnActivityWork_(NULL),
354 numberDualInfeasibilities_(0),
355 numberDualInfeasibilitiesWithoutFree_(0),
356 numberPrimalInfeasibilities_(100),
357 numberRefinements_(0),
358 pivotVariable_(NULL),
359 factorization_(NULL),
360 savedSolution_(NULL),
361 numberTimesOptimal_(0),
362 disasterArea_(NULL),
363 changeMade_(1),
364 algorithm_(0),
365 forceFactorization_(-1),
366 perturbation_(100),
367 nonLinearCost_(NULL),
368 lastBadIteration_(-999999),
369 lastFlaggedIteration_(-999999),
370 numberFake_(0),
371 numberChanged_(0),
372 progressFlag_(0),
373 firstFree_(-1),
374 numberExtraRows_(0),
375 maximumBasic_(0),
376 dontFactorizePivots_(0),
377 incomingInfeasibility_(1.0),
378 allowedInfeasibility_(10.0),
379 automaticScale_(0),
380 maximumPerturbationSize_(0),
381 perturbationArray_(NULL),
382 baseModel_(NULL)
383{
384 int i;
385 for (i = 0; i < 6; i++) {
386 rowArray_[i] = NULL;
387 columnArray_[i] = NULL;
388 }
389 for (i = 0; i < 4; i++) {
390 spareIntArray_[i] = 0;
391 spareDoubleArray_[i] = 0.0;
392 }
393 saveStatus_ = NULL;
394 factorization_ = new ClpFactorization(*rhs->factorization_, -numberRows_);
395 //factorization_ = new ClpFactorization(*rhs->factorization_,
396 // rhs->factorization_->goDenseThreshold());
397 ClpDualRowDantzig * pivot =
398 dynamic_cast< ClpDualRowDantzig*>(rhs->dualRowPivot_);
399 // say Steepest pricing
400 if (!pivot)
401 dualRowPivot_ = new ClpDualRowSteepest();
402 else
403 dualRowPivot_ = new ClpDualRowDantzig();
404 // say Steepest pricing
405 primalColumnPivot_ = new ClpPrimalColumnSteepest();
406 solveType_ = 1; // say simplex based life form
407 if (fixOthers) {
408 int numberOtherColumns = rhs->numberColumns();
409 int numberOtherRows = rhs->numberRows();
410 double * solution = new double [numberOtherColumns];
411 CoinZeroN(solution, numberOtherColumns);
412 int i;
413 for (i = 0; i < numberColumns; i++) {
414 int iColumn = whichColumn[i];
415 if (solution[iColumn])
416 fixOthers = false; // duplicates
417 solution[iColumn] = 1.0;
418 }
419 if (fixOthers) {
420 const double * otherSolution = rhs->primalColumnSolution();
421 const double * objective = rhs->objective();
422 double offset = 0.0;
423 for (i = 0; i < numberOtherColumns; i++) {
424 if (solution[i]) {
425 solution[i] = 0.0; // in
426 } else {
427 solution[i] = otherSolution[i];
428 offset += objective[i] * otherSolution[i];
429 }
430 }
431 double * rhsModification = new double [numberOtherRows];
432 CoinZeroN(rhsModification, numberOtherRows);
433 rhs->matrix()->times(solution, rhsModification) ;
434 for ( i = 0; i < numberRows; i++) {
435 int iRow = whichRow[i];
436 if (rowLower_[i] > -1.0e20)
437 rowLower_[i] -= rhsModification[iRow];
438 if (rowUpper_[i] < 1.0e20)
439 rowUpper_[i] -= rhsModification[iRow];
440 }
441 delete [] rhsModification;
442 setObjectiveOffset(rhs->objectiveOffset() - offset);
443 // And set objective value to match
444 setObjectiveValue(rhs->objectiveValue());
445 }
446 delete [] solution;
447 }
448 if (rhs->maximumPerturbationSize_) {
449 maximumPerturbationSize_ = 2 * numberColumns;
450 perturbationArray_ = new double [maximumPerturbationSize_];
451 for (i = 0; i < numberColumns; i++) {
452 int iColumn = whichColumn[i];
453 perturbationArray_[2*i] = rhs->perturbationArray_[2*iColumn];
454 perturbationArray_[2*i+1] = rhs->perturbationArray_[2*iColumn+1];
455 }
456 }
457}
458// Puts solution back small model
459void
460ClpSimplex::getbackSolution(const ClpSimplex & smallModel, const int * whichRow, const int * whichColumn)
461{
462 setSumDualInfeasibilities(smallModel.sumDualInfeasibilities());
463 setNumberDualInfeasibilities(smallModel.numberDualInfeasibilities());
464 setSumPrimalInfeasibilities(smallModel.sumPrimalInfeasibilities());
465 setNumberPrimalInfeasibilities(smallModel.numberPrimalInfeasibilities());
466 setNumberIterations(smallModel.numberIterations());
467 setProblemStatus(smallModel.status());
468 setObjectiveValue(smallModel.objectiveValue());
469 const double * solution2 = smallModel.primalColumnSolution();
470 int i;
471 int numberRows2 = smallModel.numberRows();
472 int numberColumns2 = smallModel.numberColumns();
473 const double * dj2 = smallModel.dualColumnSolution();
474 for ( i = 0; i < numberColumns2; i++) {
475 int iColumn = whichColumn[i];
476 columnActivity_[iColumn] = solution2[i];
477 reducedCost_[iColumn] = dj2[i];
478 setStatus(iColumn, smallModel.getStatus(i));
479 }
480 const double * dual2 = smallModel.dualRowSolution();
481 memset(dual_, 0, numberRows_ * sizeof(double));
482 for (i = 0; i < numberRows2; i++) {
483 int iRow = whichRow[i];
484 setRowStatus(iRow, smallModel.getRowStatus(i));
485 dual_[iRow] = dual2[i];
486 }
487 CoinZeroN(rowActivity_, numberRows_);
488#if 0
489 if (!problemStatus_) {
490 ClpDisjointCopyN(smallModel.objective(), smallModel.numberColumns_, smallModel.reducedCost_);
491 smallModel.matrix_->transposeTimes(-1.0, smallModel.dual_, smallModel.reducedCost_);
492 for (int i = 0; i < smallModel.numberColumns_; i++) {
493 if (smallModel.getColumnStatus(i) == basic)
494 assert (fabs(smallModel.reducedCost_[i]) < 1.0e-5);
495 }
496 ClpDisjointCopyN(objective(), numberColumns_, reducedCost_);
497 matrix_->transposeTimes(-1.0, dual_, reducedCost_);
498 for (int i = 0; i < numberColumns_; i++) {
499 if (getColumnStatus(i) == basic)
500 assert (fabs(reducedCost_[i]) < 1.0e-5);
501 }
502 }
503#endif
504 matrix()->times(columnActivity_, rowActivity_) ;
505}
506
507//-----------------------------------------------------------------------------
508
509ClpSimplex::~ClpSimplex ()
510{
511 setPersistenceFlag(0);
512 gutsOfDelete(0);
513 delete nonLinearCost_;
514}
515//#############################################################################
516void ClpSimplex::setLargeValue( double value)
517{
518 if (value > 0.0 && value < COIN_DBL_MAX)
519 largeValue_ = value;
520}
521int
522ClpSimplex::gutsOfSolution ( double * givenDuals,
523 const double * givenPrimals,
524 bool valuesPass)
525{
526
527
528 // if values pass, save values of basic variables
529 double * save = NULL;
530 double oldValue = 0.0;
531 if (valuesPass) {
532 assert(algorithm_ > 0); // only primal at present
533 assert(nonLinearCost_);
534 int iRow;
535 checkPrimalSolution( rowActivityWork_, columnActivityWork_);
536 // get correct bounds on all variables
537 nonLinearCost_->checkInfeasibilities(primalTolerance_);
538 oldValue = nonLinearCost_->largestInfeasibility();
539 save = new double[numberRows_];
540 for (iRow = 0; iRow < numberRows_; iRow++) {
541 int iPivot = pivotVariable_[iRow];
542 save[iRow] = solution_[iPivot];
543 }
544 }
545 // do work
546 computePrimals(rowActivityWork_, columnActivityWork_);
547 // If necessary - override results
548 if (givenPrimals) {
549 CoinMemcpyN(givenPrimals, numberColumns_, columnActivityWork_);
550 memset(rowActivityWork_, 0, numberRows_ * sizeof(double));
551 times(-1.0, columnActivityWork_, rowActivityWork_);
552 }
553 double objectiveModification = 0.0;
554 if (algorithm_ > 0 && nonLinearCost_ != NULL) {
555 // primal algorithm
556 // get correct bounds on all variables
557 // If 4 bit set - Force outgoing variables to exact bound (primal)
558 if ((specialOptions_ & 4) == 0)
559 nonLinearCost_->checkInfeasibilities(primalTolerance_);
560 else
561 nonLinearCost_->checkInfeasibilities(0.0);
562 objectiveModification += nonLinearCost_->changeInCost();
563 if (nonLinearCost_->numberInfeasibilities())
564 if (handler_->detail(CLP_SIMPLEX_NONLINEAR, messages_) < 100) {
565 handler_->message(CLP_SIMPLEX_NONLINEAR, messages_)
566 << nonLinearCost_->changeInCost()
567 << nonLinearCost_->numberInfeasibilities()
568 << CoinMessageEol;
569 }
570 }
571 if (valuesPass) {
572 double badInfeasibility = nonLinearCost_->largestInfeasibility();
573#ifdef CLP_DEBUG
574 std::cout << "Largest given infeasibility " << oldValue
575 << " now " << nonLinearCost_->largestInfeasibility() << std::endl;
576#endif
577 int numberOut = 0;
578 // But may be very large rhs etc
579 double useError = CoinMin(largestPrimalError_,
580 1.0e5 / maximumAbsElement(solution_, numberRows_ + numberColumns_));
581 if ((oldValue < incomingInfeasibility_ || badInfeasibility >
582 (CoinMax(10.0 * allowedInfeasibility_, 100.0 * oldValue)))
583 && (badInfeasibility > CoinMax(incomingInfeasibility_, allowedInfeasibility_) ||
584 useError > 1.0e-3)) {
585 //printf("Original largest infeas %g, now %g, primalError %g\n",
586 // oldValue,nonLinearCost_->largestInfeasibility(),
587 // largestPrimalError_);
588 // throw out up to 1000 structurals
589 int iRow;
590 int * sort = new int[numberRows_];
591 // first put back solution and store difference
592 for (iRow = 0; iRow < numberRows_; iRow++) {
593 int iPivot = pivotVariable_[iRow];
594 double difference = fabs(solution_[iPivot] - save[iRow]);
595 solution_[iPivot] = save[iRow];
596 save[iRow] = difference;
597 }
598 int numberBasic = 0;
599 for (iRow = 0; iRow < numberRows_; iRow++) {
600 int iPivot = pivotVariable_[iRow];
601
602 if (iPivot < numberColumns_) {
603 // column
604 double difference = save[iRow];
605 if (difference > 1.0e-4) {
606 sort[numberOut] = iRow;
607 save[numberOut++] = -difference;
608 if (getStatus(iPivot) == basic)
609 numberBasic++;
610 }
611 }
612 }
613 if (!numberBasic) {
614 //printf("no errors on basic - going to all slack - numberOut %d\n",numberOut);
615#if 0
616 allSlackBasis(true);
617 CoinIotaN(pivotVariable_, numberRows_, numberColumns_);
618#else
619 // allow
620 numberOut = 0;
621#endif
622 }
623 CoinSort_2(save, save + numberOut, sort);
624 numberOut = CoinMin(1000, numberOut);
625 for (iRow = 0; iRow < numberOut; iRow++) {
626 int jRow = sort[iRow];
627 int iColumn = pivotVariable_[jRow];
628 setColumnStatus(iColumn, superBasic);
629 setRowStatus(jRow, basic);
630 pivotVariable_[jRow] = jRow + numberColumns_;
631 if (fabs(solution_[iColumn]) > 1.0e10) {
632 if (upper_[iColumn] < 0.0) {
633 solution_[iColumn] = upper_[iColumn];
634 } else if (lower_[iColumn] > 0.0) {
635 solution_[iColumn] = lower_[iColumn];
636 } else {
637 solution_[iColumn] = 0.0;
638 }
639 }
640 }
641 delete [] sort;
642 }
643 delete [] save;
644 if (numberOut)
645 return numberOut;
646 }
647 if ((moreSpecialOptions_ & 128) != 0 && !numberIterations_) {
648 //printf("trying feas pump\n");
649 const char * integerType = integerInformation();
650 assert (integerType);
651 assert (perturbationArray_);
652 CoinZeroN(cost_, numberRows_ + numberColumns_);
653 for (int i = 0; i < numberRows_ - numberRows_; i++) {
654 int iSequence = pivotVariable_[i];
655 if (iSequence < numberColumns_ && integerType[iSequence]) {
656 double lower = lower_[iSequence];
657 double upper = upper_[iSequence];
658 double value = solution_[iSequence];
659 if (value >= lower - primalTolerance_ &&
660 value <= upper + primalTolerance_) {
661 double sign;
662 if (value - lower < upper - value)
663 sign = 1.0;
664 else
665 sign = -1.0;
666 cost_[iSequence] = sign * perturbationArray_[iSequence];
667 }
668 }
669 }
670 }
671 computeDuals(givenDuals);
672 if ((moreSpecialOptions_ & 128) != 0 && !numberIterations_) {
673 const char * integerType = integerInformation();
674 // Need to do columns and rows to stay dual feasible
675 for (int iSequence = 0; iSequence < numberColumns_; iSequence++) {
676 if (integerType[iSequence] && getStatus(iSequence) != basic) {
677 double djValue = dj_[iSequence];
678 double change = 0.0;
679 if (getStatus(iSequence) == atLowerBound)
680 change = CoinMax(-djValue, 10.0 * perturbationArray_[iSequence]);
681 else if (getStatus(iSequence) == atUpperBound)
682 change = CoinMin(-djValue, -10.0 * perturbationArray_[iSequence]);
683 cost_[iSequence] = change;
684 dj_[iSequence] += change;
685 }
686 }
687 }
688
689 // now check solutions
690 //checkPrimalSolution( rowActivityWork_, columnActivityWork_);
691 //checkDualSolution();
692 checkBothSolutions();
693 objectiveValue_ += objectiveModification / (objectiveScale_ * rhsScale_);
694 if (handler_->logLevel() > 3 || (largestPrimalError_ > 1.0e-2 ||
695 largestDualError_ > 1.0e-2))
696 handler_->message(CLP_SIMPLEX_ACCURACY, messages_)
697 << largestPrimalError_
698 << largestDualError_
699 << CoinMessageEol;
700 if (largestPrimalError_ > 1.0e-1 && numberRows_ > 100 && numberIterations_) {
701 // Change factorization tolerance
702 if (factorization_->zeroTolerance() > 1.0e-18)
703 factorization_->zeroTolerance(1.0e-18);
704 }
705 // Switch off false values pass indicator
706 if (!valuesPass && algorithm_ > 0)
707 firstFree_ = -1;
708 return 0;
709}
710void
711ClpSimplex::computePrimals ( const double * rowActivities,
712 const double * columnActivities)
713{
714
715 //work space
716 CoinIndexedVector * workSpace = rowArray_[0];
717
718 CoinIndexedVector * arrayVector = rowArray_[1];
719 arrayVector->clear();
720 CoinIndexedVector * previousVector = rowArray_[2];
721 previousVector->clear();
722 // accumulate non basic stuff
723
724 int iRow;
725 // order is this way for scaling
726 if (columnActivities != columnActivityWork_)
727 ClpDisjointCopyN(columnActivities, numberColumns_, columnActivityWork_);
728 if (rowActivities != rowActivityWork_)
729 ClpDisjointCopyN(rowActivities, numberRows_, rowActivityWork_);
730 double * array = arrayVector->denseVector();
731 int * index = arrayVector->getIndices();
732 int number = 0;
733 const double * rhsOffset = matrix_->rhsOffset(this, false, true);
734 if (!rhsOffset) {
735 // Use whole matrix every time to make it easier for ClpMatrixBase
736 // So zero out basic
737 for (iRow = 0; iRow < numberRows_; iRow++) {
738 int iPivot = pivotVariable_[iRow];
739 assert (iPivot >= 0);
740 solution_[iPivot] = 0.0;
741#ifdef CLP_INVESTIGATE
742 assert (getStatus(iPivot) == basic);
743#endif
744 }
745 // Extended solution before "update"
746 matrix_->primalExpanded(this, 0);
747 times(-1.0, columnActivityWork_, array);
748 for (iRow = 0; iRow < numberRows_; iRow++) {
749 double value = array[iRow] + rowActivityWork_[iRow];
750 if (value) {
751 array[iRow] = value;
752 index[number++] = iRow;
753 } else {
754 array[iRow] = 0.0;
755 }
756 }
757 } else {
758 // we have an effective rhs lying around
759 // zero out basic (really just for slacks)
760 for (iRow = 0; iRow < numberRows_; iRow++) {
761 int iPivot = pivotVariable_[iRow];
762 solution_[iPivot] = 0.0;
763 }
764 for (iRow = 0; iRow < numberRows_; iRow++) {
765 double value = rhsOffset[iRow] + rowActivityWork_[iRow];
766 if (value) {
767 array[iRow] = value;
768 index[number++] = iRow;
769 } else {
770 array[iRow] = 0.0;
771 }
772 }
773 }
774 arrayVector->setNumElements(number);
775#ifdef CLP_DEBUG
776 if (numberIterations_ == -3840) {
777 int i;
778 for (i = 0; i < numberRows_ + numberColumns_; i++)
779 printf("%d status %d\n", i, status_[i]);
780 printf("xxxxx1\n");
781 for (i = 0; i < numberRows_; i++)
782 if (array[i])
783 printf("%d rhs %g\n", i, array[i]);
784 printf("xxxxx2\n");
785 for (i = 0; i < numberRows_ + numberColumns_; i++)
786 if (getStatus(i) != basic)
787 printf("%d non basic %g %g %g\n", i, lower_[i], solution_[i], upper_[i]);
788 printf("xxxxx3\n");
789 }
790#endif
791 // Ftran adjusted RHS and iterate to improve accuracy
792 double lastError = COIN_DBL_MAX;
793 int iRefine;
794 CoinIndexedVector * thisVector = arrayVector;
795 CoinIndexedVector * lastVector = previousVector;
796 if (number)
797 factorization_->updateColumn(workSpace, thisVector);
798 double * work = workSpace->denseVector();
799#ifdef CLP_DEBUG
800 if (numberIterations_ == -3840) {
801 int i;
802 for (i = 0; i < numberRows_; i++)
803 if (array[i])
804 printf("%d after rhs %g\n", i, array[i]);
805 printf("xxxxx4\n");
806 }
807#endif
808 bool goodSolution = true;
809 for (iRefine = 0; iRefine < numberRefinements_ + 1; iRefine++) {
810
811 int numberIn = thisVector->getNumElements();
812 int * indexIn = thisVector->getIndices();
813 double * arrayIn = thisVector->denseVector();
814 // put solution in correct place
815 if (!rhsOffset) {
816 int j;
817 for (j = 0; j < numberIn; j++) {
818 iRow = indexIn[j];
819 int iPivot = pivotVariable_[iRow];
820 solution_[iPivot] = arrayIn[iRow];
821 //assert (fabs(solution_[iPivot])<1.0e100);
822 }
823 } else {
824 for (iRow = 0; iRow < numberRows_; iRow++) {
825 int iPivot = pivotVariable_[iRow];
826 solution_[iPivot] = arrayIn[iRow];
827 //assert (fabs(solution_[iPivot])<1.0e100);
828 }
829 }
830 // Extended solution after "update"
831 matrix_->primalExpanded(this, 1);
832 // check Ax == b (for all)
833 // signal column generated matrix to just do basic (and gub)
834 unsigned int saveOptions = specialOptions();
835 setSpecialOptions(16);
836 times(-1.0, columnActivityWork_, work);
837 setSpecialOptions(saveOptions);
838 largestPrimalError_ = 0.0;
839 double multiplier = 131072.0;
840 for (iRow = 0; iRow < numberRows_; iRow++) {
841 double value = work[iRow] + rowActivityWork_[iRow];
842 work[iRow] = value * multiplier;
843 if (fabs(value) > largestPrimalError_) {
844 largestPrimalError_ = fabs(value);
845 }
846 }
847 if (largestPrimalError_ >= lastError) {
848 // restore
849 CoinIndexedVector * temp = thisVector;
850 thisVector = lastVector;
851 lastVector = temp;
852 goodSolution = false;
853 break;
854 }
855 if (iRefine < numberRefinements_ && largestPrimalError_ > 1.0e-10) {
856 // try and make better
857 // save this
858 CoinIndexedVector * temp = thisVector;
859 thisVector = lastVector;
860 lastVector = temp;
861 int * indexOut = thisVector->getIndices();
862 int number = 0;
863 array = thisVector->denseVector();
864 thisVector->clear();
865 for (iRow = 0; iRow < numberRows_; iRow++) {
866 double value = work[iRow];
867 if (value) {
868 array[iRow] = value;
869 indexOut[number++] = iRow;
870 work[iRow] = 0.0;
871 }
872 }
873 thisVector->setNumElements(number);
874 lastError = largestPrimalError_;
875 factorization_->updateColumn(workSpace, thisVector);
876 multiplier = 1.0 / multiplier;
877 double * previous = lastVector->denseVector();
878 number = 0;
879 for (iRow = 0; iRow < numberRows_; iRow++) {
880 double value = previous[iRow] + multiplier * array[iRow];
881 if (value) {
882 array[iRow] = value;
883 indexOut[number++] = iRow;
884 } else {
885 array[iRow] = 0.0;
886 }
887 }
888 thisVector->setNumElements(number);
889 } else {
890 break;
891 }
892 }
893
894 // solution as accurate as we are going to get
895 ClpFillN(work, numberRows_, 0.0);
896 if (!goodSolution) {
897 array = thisVector->denseVector();
898 // put solution in correct place
899 for (iRow = 0; iRow < numberRows_; iRow++) {
900 int iPivot = pivotVariable_[iRow];
901 solution_[iPivot] = array[iRow];
902 //assert (fabs(solution_[iPivot])<1.0e100);
903 }
904 }
905 arrayVector->clear();
906 previousVector->clear();
907#ifdef CLP_DEBUG
908 if (numberIterations_ == -3840) {
909 exit(77);
910 }
911#endif
912}
913// now dual side
914void
915ClpSimplex::computeDuals(double * givenDjs)
916{
917#ifndef SLIM_CLP
918 if (objective_->type() == 1 || !objective_->activated()) {
919#endif
920 // Linear
921 //work space
922 CoinIndexedVector * workSpace = rowArray_[0];
923
924 CoinIndexedVector * arrayVector = rowArray_[1];
925 arrayVector->clear();
926 CoinIndexedVector * previousVector = rowArray_[2];
927 previousVector->clear();
928 int iRow;
929#ifdef CLP_DEBUG
930 workSpace->checkClear();
931#endif
932 double * array = arrayVector->denseVector();
933 int * index = arrayVector->getIndices();
934 int number = 0;
935 if (!givenDjs) {
936 for (iRow = 0; iRow < numberRows_; iRow++) {
937 int iPivot = pivotVariable_[iRow];
938 double value = cost_[iPivot];
939 if (value) {
940 array[iRow] = value;
941 index[number++] = iRow;
942 }
943 }
944 } else {
945 // dual values pass - djs may not be zero
946 for (iRow = 0; iRow < numberRows_; iRow++) {
947 int iPivot = pivotVariable_[iRow];
948 // make sure zero if done
949 if (!pivoted(iPivot))
950 givenDjs[iPivot] = 0.0;
951 double value = cost_[iPivot] - givenDjs[iPivot];
952 if (value) {
953 array[iRow] = value;
954 index[number++] = iRow;
955 }
956 }
957 }
958 arrayVector->setNumElements(number);
959 // Extended duals before "updateTranspose"
960 matrix_->dualExpanded(this, arrayVector, givenDjs, 0);
961
962 // Btran basic costs and get as accurate as possible
963 double lastError = COIN_DBL_MAX;
964 int iRefine;
965 double * work = workSpace->denseVector();
966 CoinIndexedVector * thisVector = arrayVector;
967 CoinIndexedVector * lastVector = previousVector;
968 factorization_->updateColumnTranspose(workSpace, thisVector);
969
970 for (iRefine = 0; iRefine < numberRefinements_ + 1; iRefine++) {
971 // check basic reduced costs zero
972 largestDualError_ = 0.0;
973 if (!numberExtraRows_) {
974 // Just basic
975 int * index2 = workSpace->getIndices();
976 // use reduced costs for slacks as work array
977 double * work2 = reducedCostWork_ + numberColumns_;
978 int numberStructurals = 0;
979 for (iRow = 0; iRow < numberRows_; iRow++) {
980 int iPivot = pivotVariable_[iRow];
981 if (iPivot < numberColumns_)
982 index2[numberStructurals++] = iPivot;
983 }
984 matrix_->listTransposeTimes(this, array, index2, numberStructurals, work2);
985 numberStructurals = 0;
986 if (!givenDjs) {
987 for (iRow = 0; iRow < numberRows_; iRow++) {
988 int iPivot = pivotVariable_[iRow];
989 double value;
990 if (iPivot >= numberColumns_) {
991 // slack
992 value = rowObjectiveWork_[iPivot-numberColumns_]
993 + array[iPivot-numberColumns_];
994 } else {
995 // column
996 value = objectiveWork_[iPivot] - work2[numberStructurals++];
997 }
998 work[iRow] = value;
999 if (fabs(value) > largestDualError_) {
1000 largestDualError_ = fabs(value);
1001 }
1002 }
1003 } else {
1004 for (iRow = 0; iRow < numberRows_; iRow++) {
1005 int iPivot = pivotVariable_[iRow];
1006 if (iPivot >= numberColumns_) {
1007 // slack
1008 work[iRow] = rowObjectiveWork_[iPivot-numberColumns_]
1009 + array[iPivot-numberColumns_] - givenDjs[iPivot];
1010 } else {
1011 // column
1012 work[iRow] = objectiveWork_[iPivot] - work2[numberStructurals++]
1013 - givenDjs[iPivot];
1014 }
1015 if (fabs(work[iRow]) > largestDualError_) {
1016 largestDualError_ = fabs(work[iRow]);
1017 //assert (largestDualError_<1.0e-7);
1018 //if (largestDualError_>1.0e-7)
1019 //printf("large dual error %g\n",largestDualError_);
1020 }
1021 }
1022 }
1023 } else {
1024 // extra rows - be more careful
1025#if 1
1026 // would be faster to do just for basic but this reduces code
1027 ClpDisjointCopyN(objectiveWork_, numberColumns_, reducedCostWork_);
1028 transposeTimes(-1.0, array, reducedCostWork_);
1029#else
1030 // Just basic
1031 int * index2 = workSpace->getIndices();
1032 int numberStructurals = 0;
1033 for (iRow = 0; iRow < numberRows_; iRow++) {
1034 int iPivot = pivotVariable_[iRow];
1035 if (iPivot < numberColumns_)
1036 index2[numberStructurals++] = iPivot;
1037 }
1038 matrix_->listTransposeTimes(this, array, index2, numberStructurals, work);
1039 for (iRow = 0; iRow < numberStructurals; iRow++) {
1040 int iPivot = index2[iRow];
1041 reducedCostWork_[iPivot] = objectiveWork_[iPivot] - work[iRow];
1042 }
1043#endif
1044 // update by duals on sets
1045 matrix_->dualExpanded(this, NULL, NULL, 1);
1046 if (!givenDjs) {
1047 for (iRow = 0; iRow < numberRows_; iRow++) {
1048 int iPivot = pivotVariable_[iRow];
1049 double value;
1050 if (iPivot >= numberColumns_) {
1051 // slack
1052 value = rowObjectiveWork_[iPivot-numberColumns_]
1053 + array[iPivot-numberColumns_];
1054 } else {
1055 // column
1056 value = reducedCostWork_[iPivot];
1057 }
1058 work[iRow] = value;
1059 if (fabs(value) > largestDualError_) {
1060 largestDualError_ = fabs(value);
1061 }
1062 }
1063 } else {
1064 for (iRow = 0; iRow < numberRows_; iRow++) {
1065 int iPivot = pivotVariable_[iRow];
1066 if (iPivot >= numberColumns_) {
1067 // slack
1068 work[iRow] = rowObjectiveWork_[iPivot-numberColumns_]
1069 + array[iPivot-numberColumns_] - givenDjs[iPivot];
1070 } else {
1071 // column
1072 work[iRow] = reducedCostWork_[iPivot] - givenDjs[iPivot];
1073 }
1074 if (fabs(work[iRow]) > largestDualError_) {
1075 largestDualError_ = fabs(work[iRow]);
1076 //assert (largestDualError_<1.0e-7);
1077 //if (largestDualError_>1.0e-7)
1078 //printf("large dual error %g\n",largestDualError_);
1079 }
1080 }
1081 }
1082 }
1083 if (largestDualError_ >= lastError) {
1084 // restore
1085 CoinIndexedVector * temp = thisVector;
1086 thisVector = lastVector;
1087 lastVector = temp;
1088 break;
1089 }
1090 if (iRefine < numberRefinements_ && largestDualError_ > 1.0e-10
1091 && !givenDjs) {
1092 // try and make better
1093 // save this
1094 CoinIndexedVector * temp = thisVector;
1095 thisVector = lastVector;
1096 lastVector = temp;
1097 int * indexOut = thisVector->getIndices();
1098 int number = 0;
1099 array = thisVector->denseVector();
1100 thisVector->clear();
1101 double multiplier = 131072.0;
1102 for (iRow = 0; iRow < numberRows_; iRow++) {
1103 double value = multiplier * work[iRow];
1104 if (value) {
1105 array[iRow] = value;
1106 indexOut[number++] = iRow;
1107 work[iRow] = 0.0;
1108 }
1109 work[iRow] = 0.0;
1110 }
1111 thisVector->setNumElements(number);
1112 lastError = largestDualError_;
1113 factorization_->updateColumnTranspose(workSpace, thisVector);
1114 multiplier = 1.0 / multiplier;
1115 double * previous = lastVector->denseVector();
1116 number = 0;
1117 for (iRow = 0; iRow < numberRows_; iRow++) {
1118 double value = previous[iRow] + multiplier * array[iRow];
1119 if (value) {
1120 array[iRow] = value;
1121 indexOut[number++] = iRow;
1122 } else {
1123 array[iRow] = 0.0;
1124 }
1125 }
1126 thisVector->setNumElements(number);
1127 } else {
1128 break;
1129 }
1130 }
1131 // now look at dual solution
1132 array = thisVector->denseVector();
1133 for (iRow = 0; iRow < numberRows_; iRow++) {
1134 // slack
1135 double value = array[iRow];
1136 dual_[iRow] = value;
1137 value += rowObjectiveWork_[iRow];
1138 rowReducedCost_[iRow] = value;
1139 }
1140 // can use work if problem scaled (for better cache)
1141 ClpPackedMatrix* clpMatrix =
1142 dynamic_cast< ClpPackedMatrix*>(matrix_);
1143 double * saveRowScale = rowScale_;
1144 //double * saveColumnScale = columnScale_;
1145 if (scaledMatrix_) {
1146 rowScale_ = NULL;
1147 clpMatrix = scaledMatrix_;
1148 }
1149 if (clpMatrix && (clpMatrix->flags() & 2) == 0) {
1150 CoinIndexedVector * cVector = columnArray_[0];
1151 int * whichColumn = cVector->getIndices();
1152 assert (!cVector->getNumElements());
1153 int n = 0;
1154 for (int i = 0; i < numberColumns_; i++) {
1155 if (getColumnStatus(i) != basic) {
1156 whichColumn[n++] = i;
1157 reducedCostWork_[i] = objectiveWork_[i];
1158 } else {
1159 reducedCostWork_[i] = 0.0;
1160 }
1161 }
1162 if (numberRows_ > 4000)
1163 clpMatrix->transposeTimesSubset(n, whichColumn, dual_, reducedCostWork_,
1164 rowScale_, columnScale_, work);
1165 else
1166 clpMatrix->transposeTimesSubset(n, whichColumn, dual_, reducedCostWork_,
1167 rowScale_, columnScale_, NULL);
1168 } else {
1169 ClpDisjointCopyN(objectiveWork_, numberColumns_, reducedCostWork_);
1170 if (numberRows_ > 4000)
1171 matrix_->transposeTimes(-1.0, dual_, reducedCostWork_,
1172 rowScale_, columnScale_, work);
1173 else
1174 matrix_->transposeTimes(-1.0, dual_, reducedCostWork_,
1175 rowScale_, columnScale_, NULL);
1176 }
1177 rowScale_ = saveRowScale;
1178 //columnScale_ = saveColumnScale;
1179 ClpFillN(work, numberRows_, 0.0);
1180 // Extended duals and check dual infeasibility
1181 if (!matrix_->skipDualCheck() || algorithm_ < 0 || problemStatus_ != -2)
1182 matrix_->dualExpanded(this, NULL, NULL, 2);
1183 // If necessary - override results
1184 if (givenDjs) {
1185 // restore accurate duals
1186 CoinMemcpyN(dj_, (numberRows_ + numberColumns_), givenDjs);
1187 }
1188 arrayVector->clear();
1189 previousVector->clear();
1190#ifndef SLIM_CLP
1191 } else {
1192 // Nonlinear
1193 objective_->reducedGradient(this, dj_, false);
1194 // get dual_ by moving from reduced costs for slacks
1195 CoinMemcpyN(dj_ + numberColumns_, numberRows_, dual_);
1196 }
1197#endif
1198}
1199/* Given an existing factorization computes and checks
1200 primal and dual solutions. Uses input arrays for variables at
1201 bounds. Returns feasibility states */
1202int ClpSimplex::getSolution ( const double * /*rowActivities*/,
1203 const double * /*columnActivities*/)
1204{
1205 if (!factorization_->status()) {
1206 // put in standard form
1207 createRim(7 + 8 + 16 + 32, false, -1);
1208 if (pivotVariable_[0] < 0)
1209 internalFactorize(0);
1210 // do work
1211 gutsOfSolution ( NULL, NULL);
1212 // release extra memory
1213 deleteRim(0);
1214 }
1215 return factorization_->status();
1216}
1217/* Given an existing factorization computes and checks
1218 primal and dual solutions. Uses current problem arrays for
1219 bounds. Returns feasibility states */
1220int ClpSimplex::getSolution ( )
1221{
1222 double * rowActivities = new double[numberRows_];
1223 double * columnActivities = new double[numberColumns_];
1224 ClpDisjointCopyN ( rowActivityWork_, numberRows_ , rowActivities);
1225 ClpDisjointCopyN ( columnActivityWork_, numberColumns_ , columnActivities);
1226 int status = getSolution( rowActivities, columnActivities);
1227 delete [] rowActivities;
1228 delete [] columnActivities;
1229 return status;
1230}
1231// Factorizes using current basis. This is for external use
1232// Return codes are as from ClpFactorization
1233int ClpSimplex::factorize ()
1234{
1235 // put in standard form
1236 createRim(7 + 8 + 16 + 32, false);
1237 // do work
1238 int status = internalFactorize(-1);
1239 // release extra memory
1240 deleteRim(0);
1241
1242 return status;
1243}
1244// Clean up status
1245void
1246ClpSimplex::cleanStatus()
1247{
1248 int iRow, iColumn;
1249 int numberBasic = 0;
1250 // make row activities correct
1251 memset(rowActivityWork_, 0, numberRows_ * sizeof(double));
1252 times(1.0, columnActivityWork_, rowActivityWork_);
1253 if (!status_)
1254 createStatus();
1255 for (iRow = 0; iRow < numberRows_; iRow++) {
1256 if (getRowStatus(iRow) == basic)
1257 numberBasic++;
1258 else {
1259 setRowStatus(iRow, superBasic);
1260 // but put to bound if close
1261 if (fabs(rowActivityWork_[iRow] - rowLowerWork_[iRow])
1262 <= primalTolerance_) {
1263 rowActivityWork_[iRow] = rowLowerWork_[iRow];
1264 setRowStatus(iRow, atLowerBound);
1265 } else if (fabs(rowActivityWork_[iRow] - rowUpperWork_[iRow])
1266 <= primalTolerance_) {
1267 rowActivityWork_[iRow] = rowUpperWork_[iRow];
1268 setRowStatus(iRow, atUpperBound);
1269 }
1270 }
1271 }
1272 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1273 if (getColumnStatus(iColumn) == basic) {
1274 if (numberBasic == numberRows_) {
1275 // take out of basis
1276 setColumnStatus(iColumn, superBasic);
1277 // but put to bound if close
1278 if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn])
1279 <= primalTolerance_) {
1280 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1281 setColumnStatus(iColumn, atLowerBound);
1282 } else if (fabs(columnActivityWork_[iColumn]
1283 - columnUpperWork_[iColumn])
1284 <= primalTolerance_) {
1285 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1286 setColumnStatus(iColumn, atUpperBound);
1287 }
1288 } else
1289 numberBasic++;
1290 } else {
1291 setColumnStatus(iColumn, superBasic);
1292 // but put to bound if close
1293 if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn])
1294 <= primalTolerance_) {
1295 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1296 setColumnStatus(iColumn, atLowerBound);
1297 } else if (fabs(columnActivityWork_[iColumn]
1298 - columnUpperWork_[iColumn])
1299 <= primalTolerance_) {
1300 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1301 setColumnStatus(iColumn, atUpperBound);
1302 }
1303 }
1304 }
1305}
1306
1307/* Factorizes using current basis.
1308 solveType - 1 iterating, 0 initial, -1 external
1309 - 2 then iterating but can throw out of basis
1310 If 10 added then in primal values pass
1311 Return codes are as from ClpFactorization unless initial factorization
1312 when total number of singularities is returned.
1313 Special case is numberRows_+1 -> all slack basis.
1314*/
1315int ClpSimplex::internalFactorize ( int solveType)
1316{
1317 int iRow, iColumn;
1318 int totalSlacks = numberRows_;
1319 if (!status_)
1320 createStatus();
1321
1322 bool valuesPass = false;
1323 if (solveType >= 10) {
1324 valuesPass = true;
1325 solveType -= 10;
1326 }
1327#ifdef CLP_DEBUG
1328 if (solveType > 0) {
1329 int numberFreeIn = 0, numberFreeOut = 0;
1330 double biggestDj = 0.0;
1331 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1332 switch(getColumnStatus(iColumn)) {
1333
1334 case basic:
1335 if (columnLower_[iColumn] < -largeValue_
1336 && columnUpper_[iColumn] > largeValue_)
1337 numberFreeIn++;
1338 break;
1339 default:
1340 if (columnLower_[iColumn] < -largeValue_
1341 && columnUpper_[iColumn] > largeValue_) {
1342 numberFreeOut++;
1343 biggestDj = CoinMax(fabs(dj_[iColumn]), biggestDj);
1344 }
1345 break;
1346 }
1347 }
1348 if (numberFreeIn + numberFreeOut)
1349 printf("%d in basis, %d out - largest dj %g\n",
1350 numberFreeIn, numberFreeOut, biggestDj);
1351 }
1352#endif
1353 if (solveType <= 0) {
1354 // Make sure everything is clean
1355 for (iRow = 0; iRow < numberRows_; iRow++) {
1356 if(getRowStatus(iRow) == isFixed) {
1357 // double check fixed
1358 if (rowUpperWork_[iRow] > rowLowerWork_[iRow])
1359 setRowStatus(iRow, atLowerBound);
1360 } else if (getRowStatus(iRow) == isFree) {
1361 // may not be free after all
1362 if (rowLowerWork_[iRow] > -largeValue_ || rowUpperWork_[iRow] < largeValue_)
1363 setRowStatus(iRow, superBasic);
1364 }
1365 }
1366 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1367 if(getColumnStatus(iColumn) == isFixed) {
1368 // double check fixed
1369 if (columnUpperWork_[iColumn] > columnLowerWork_[iColumn])
1370 setColumnStatus(iColumn, atLowerBound);
1371 } else if (getColumnStatus(iColumn) == isFree) {
1372 // may not be free after all
1373 if (columnLowerWork_[iColumn] > -largeValue_ || columnUpperWork_[iColumn] < largeValue_)
1374 setColumnStatus(iColumn, superBasic);
1375 }
1376 }
1377 if (!valuesPass) {
1378 // not values pass so set to bounds
1379 bool allSlack = true;
1380 if (status_) {
1381 for (iRow = 0; iRow < numberRows_; iRow++) {
1382 if (getRowStatus(iRow) != basic) {
1383 allSlack = false;
1384 break;
1385 }
1386 }
1387 }
1388 if (!allSlack) {
1389 //#define CLP_INVESTIGATE2
1390#ifdef CLP_INVESTIGATE3
1391 int numberTotal = numberRows_ + numberColumns_;
1392 double * saveSol = valuesPass ?
1393 CoinCopyOfArray(solution_, numberTotal) : NULL;
1394#endif
1395 // set values from warm start (if sensible)
1396 int numberBasic = 0;
1397 for (iRow = 0; iRow < numberRows_; iRow++) {
1398 switch(getRowStatus(iRow)) {
1399
1400 case basic:
1401 numberBasic++;
1402 break;
1403 case atUpperBound:
1404 rowActivityWork_[iRow] = rowUpperWork_[iRow];
1405 if (rowActivityWork_[iRow] > largeValue_) {
1406 if (rowLowerWork_[iRow] > -largeValue_) {
1407 rowActivityWork_[iRow] = rowLowerWork_[iRow];
1408 setRowStatus(iRow, atLowerBound);
1409 } else {
1410 // say free
1411 setRowStatus(iRow, isFree);
1412 rowActivityWork_[iRow] = 0.0;
1413 }
1414 }
1415 break;
1416 case ClpSimplex::isFixed:
1417 case atLowerBound:
1418 rowActivityWork_[iRow] = rowLowerWork_[iRow];
1419 if (rowActivityWork_[iRow] < -largeValue_) {
1420 if (rowUpperWork_[iRow] < largeValue_) {
1421 rowActivityWork_[iRow] = rowUpperWork_[iRow];
1422 setRowStatus(iRow, atUpperBound);
1423 } else {
1424 // say free
1425 setRowStatus(iRow, isFree);
1426 rowActivityWork_[iRow] = 0.0;
1427 }
1428 }
1429 break;
1430 case isFree:
1431 break;
1432 // not really free - fall through to superbasic
1433 case superBasic:
1434 if (rowUpperWork_[iRow] > largeValue_) {
1435 if (rowLowerWork_[iRow] > -largeValue_) {
1436 rowActivityWork_[iRow] = rowLowerWork_[iRow];
1437 setRowStatus(iRow, atLowerBound);
1438 } else {
1439 // say free
1440 setRowStatus(iRow, isFree);
1441 rowActivityWork_[iRow] = 0.0;
1442 }
1443 } else {
1444 if (rowLowerWork_[iRow] > -largeValue_) {
1445 // set to nearest
1446 if (fabs(rowActivityWork_[iRow] - rowLowerWork_[iRow])
1447 < fabs(rowActivityWork_[iRow] - rowLowerWork_[iRow])) {
1448 rowActivityWork_[iRow] = rowLowerWork_[iRow];
1449 setRowStatus(iRow, atLowerBound);
1450 } else {
1451 rowActivityWork_[iRow] = rowUpperWork_[iRow];
1452 setRowStatus(iRow, atUpperBound);
1453 }
1454 } else {
1455 rowActivityWork_[iRow] = rowUpperWork_[iRow];
1456 setRowStatus(iRow, atUpperBound);
1457 }
1458 }
1459 break;
1460 }
1461 }
1462 totalSlacks = numberBasic;
1463
1464 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1465 switch(getColumnStatus(iColumn)) {
1466
1467 case basic:
1468 if (numberBasic == maximumBasic_) {
1469 // take out of basis
1470 if (columnLowerWork_[iColumn] > -largeValue_) {
1471 if (columnActivityWork_[iColumn] - columnLowerWork_[iColumn] <
1472 columnUpperWork_[iColumn] - columnActivityWork_[iColumn]) {
1473 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1474 setColumnStatus(iColumn, atLowerBound);
1475 } else {
1476 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1477 setColumnStatus(iColumn, atUpperBound);
1478 }
1479 } else if (columnUpperWork_[iColumn] < largeValue_) {
1480 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1481 setColumnStatus(iColumn, atUpperBound);
1482 } else {
1483 columnActivityWork_[iColumn] = 0.0;
1484 setColumnStatus(iColumn, isFree);
1485 }
1486 } else {
1487 numberBasic++;
1488 }
1489 break;
1490 case atUpperBound:
1491 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1492 if (columnActivityWork_[iColumn] > largeValue_) {
1493 if (columnLowerWork_[iColumn] < -largeValue_) {
1494 columnActivityWork_[iColumn] = 0.0;
1495 setColumnStatus(iColumn, isFree);
1496 } else {
1497 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1498 setColumnStatus(iColumn, atLowerBound);
1499 }
1500 }
1501 break;
1502 case isFixed:
1503 case atLowerBound:
1504 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1505 if (columnActivityWork_[iColumn] < -largeValue_) {
1506 if (columnUpperWork_[iColumn] > largeValue_) {
1507 columnActivityWork_[iColumn] = 0.0;
1508 setColumnStatus(iColumn, isFree);
1509 } else {
1510 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1511 setColumnStatus(iColumn, atUpperBound);
1512 }
1513 }
1514 break;
1515 case isFree:
1516 break;
1517 // not really free - fall through to superbasic
1518 case superBasic:
1519 if (columnUpperWork_[iColumn] > largeValue_) {
1520 if (columnLowerWork_[iColumn] > -largeValue_) {
1521 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1522 setColumnStatus(iColumn, atLowerBound);
1523 } else {
1524 // say free
1525 setColumnStatus(iColumn, isFree);
1526 columnActivityWork_[iColumn] = 0.0;
1527 }
1528 } else {
1529 if (columnLowerWork_[iColumn] > -largeValue_) {
1530 // set to nearest
1531 if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn])
1532 < fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn])) {
1533 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1534 setColumnStatus(iColumn, atLowerBound);
1535 } else {
1536 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1537 setColumnStatus(iColumn, atUpperBound);
1538 }
1539 } else {
1540 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1541 setColumnStatus(iColumn, atUpperBound);
1542 }
1543 }
1544 break;
1545 }
1546 }
1547#ifdef CLP_INVESTIGATE3
1548 if (saveSol) {
1549 int numberChanged = 0;
1550 double largestChanged = 0.0;
1551 for (int i = 0; i < numberTotal; i++) {
1552 double difference = fabs(solution_[i] - saveSol[i]);
1553 if (difference > 1.0e-7) {
1554 numberChanged++;
1555 if (difference > largestChanged)
1556 largestChanged = difference;
1557 }
1558 }
1559 if (numberChanged)
1560 printf("%d changed, largest %g\n", numberChanged, largestChanged);
1561 delete [] saveSol;
1562 }
1563#endif
1564#if 0
1565 if (numberBasic < numberRows_) {
1566 // add some slacks in case odd warmstart
1567#ifdef CLP_INVESTIGATE
1568 printf("BAD %d basic, %d rows %d slacks\n",
1569 numberBasic, numberRows_, totalSlacks);
1570#endif
1571 int iRow = numberRows_ - 1;
1572 while (numberBasic < numberRows_) {
1573 if (getRowStatus(iRow) != basic) {
1574 setRowStatus(iRow, basic);
1575 numberBasic++;
1576 totalSlacks++;
1577 iRow--;
1578 } else {
1579 break;
1580 }
1581 }
1582 }
1583#endif
1584 } else {
1585 // all slack basis
1586 int numberBasic = 0;
1587 if (!status_) {
1588 createStatus();
1589 }
1590 for (iRow = 0; iRow < numberRows_; iRow++) {
1591 double lower = rowLowerWork_[iRow];
1592 double upper = rowUpperWork_[iRow];
1593 if (lower > -largeValue_ || upper < largeValue_) {
1594 if (fabs(lower) <= fabs(upper)) {
1595 rowActivityWork_[iRow] = lower;
1596 } else {
1597 rowActivityWork_[iRow] = upper;
1598 }
1599 } else {
1600 rowActivityWork_[iRow] = 0.0;
1601 }
1602 setRowStatus(iRow, basic);
1603 numberBasic++;
1604 }
1605 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1606 double lower = columnLowerWork_[iColumn];
1607 double upper = columnUpperWork_[iColumn];
1608 double big_bound = largeValue_;
1609 if (lower > -big_bound || upper < big_bound) {
1610 if ((getColumnStatus(iColumn) == atLowerBound &&
1611 columnActivityWork_[iColumn] == lower) ||
1612 (getColumnStatus(iColumn) == atUpperBound &&
1613 columnActivityWork_[iColumn] == upper)) {
1614 // status looks plausible
1615 } else {
1616 // set to sensible
1617 if (fabs(lower) <= fabs(upper)) {
1618 setColumnStatus(iColumn, atLowerBound);
1619 columnActivityWork_[iColumn] = lower;
1620 } else {
1621 setColumnStatus(iColumn, atUpperBound);
1622 columnActivityWork_[iColumn] = upper;
1623 }
1624 }
1625 } else {
1626 setColumnStatus(iColumn, isFree);
1627 columnActivityWork_[iColumn] = 0.0;
1628 }
1629 }
1630 }
1631 } else {
1632 // values pass has less coding
1633 // make row activities correct and clean basis a bit
1634 cleanStatus();
1635 if (status_) {
1636 int numberBasic = 0;
1637 for (iRow = 0; iRow < numberRows_; iRow++) {
1638 if (getRowStatus(iRow) == basic)
1639 numberBasic++;
1640 }
1641 totalSlacks = numberBasic;
1642#if 0
1643 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1644 if (getColumnStatus(iColumn) == basic)
1645 numberBasic++;
1646 }
1647#endif
1648 } else {
1649 // all slack basis
1650 int numberBasic = 0;
1651 if (!status_) {
1652 createStatus();
1653 }
1654 for (iRow = 0; iRow < numberRows_; iRow++) {
1655 setRowStatus(iRow, basic);
1656 numberBasic++;
1657 }
1658 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1659 setColumnStatus(iColumn, superBasic);
1660 // but put to bound if close
1661 if (fabs(columnActivityWork_[iColumn] - columnLowerWork_[iColumn])
1662 <= primalTolerance_) {
1663 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1664 setColumnStatus(iColumn, atLowerBound);
1665 } else if (fabs(columnActivityWork_[iColumn]
1666 - columnUpperWork_[iColumn])
1667 <= primalTolerance_) {
1668 columnActivityWork_[iColumn] = columnUpperWork_[iColumn];
1669 setColumnStatus(iColumn, atUpperBound);
1670 }
1671 }
1672 }
1673 }
1674 numberRefinements_ = 1;
1675 // set fixed if they are
1676 for (iRow = 0; iRow < numberRows_; iRow++) {
1677 if (getRowStatus(iRow) != basic ) {
1678 if (rowLowerWork_[iRow] == rowUpperWork_[iRow]) {
1679 rowActivityWork_[iRow] = rowLowerWork_[iRow];
1680 setRowStatus(iRow, isFixed);
1681 }
1682 }
1683 }
1684 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1685 if (getColumnStatus(iColumn) != basic ) {
1686 if (columnLowerWork_[iColumn] == columnUpperWork_[iColumn]) {
1687 columnActivityWork_[iColumn] = columnLowerWork_[iColumn];
1688 setColumnStatus(iColumn, isFixed);
1689 }
1690 }
1691 }
1692 }
1693 //for (iRow=0;iRow<numberRows_+numberColumns_;iRow++) {
1694 //if (fabs(solution_[iRow])>1.0e10) {
1695 // printf("large %g at %d - status %d\n",
1696 // solution_[iRow],iRow,status_[iRow]);
1697 //}
1698 //}
1699# ifndef _MSC_VER
1700 // The local static var k is a problem when trying to build a DLL. Since this is
1701 // just for debugging (likely done on *nix), just hide it from Windows
1702 // -- lh, 101016 --
1703 if (0) {
1704 static int k = 0;
1705 printf("start basis\n");
1706 int i;
1707 for (i = 0; i < numberRows_; i++)
1708 printf ("xx %d %d\n", i, pivotVariable_[i]);
1709 for (i = 0; i < numberRows_ + numberColumns_; i++)
1710 if (getColumnStatus(i) == basic)
1711 printf ("yy %d basic\n", i);
1712 if (k > 20)
1713 exit(0);
1714 k++;
1715 }
1716# endif
1717 int status = factorization_->factorize(this, solveType, valuesPass);
1718 if (status) {
1719 handler_->message(CLP_SIMPLEX_BADFACTOR, messages_)
1720 << status
1721 << CoinMessageEol;
1722 return -1;
1723 } else if (!solveType) {
1724 // Initial basis - return number of singularities
1725 int numberSlacks = 0;
1726 for (iRow = 0; iRow < numberRows_; iRow++) {
1727 if (getRowStatus(iRow) == basic)
1728 numberSlacks++;
1729 }
1730 status = CoinMax(numberSlacks - totalSlacks, 0);
1731 // special case if all slack
1732 if (numberSlacks == numberRows_) {
1733 status = numberRows_ + 1;
1734 }
1735 }
1736
1737 // sparse methods
1738 //if (factorization_->sparseThreshold()) {
1739 // get default value
1740 factorization_->sparseThreshold(0);
1741 if (!(moreSpecialOptions_&1024))
1742 factorization_->goSparse();
1743 //}
1744
1745 return status;
1746}
1747/*
1748 This does basis housekeeping and does values for in/out variables.
1749 Can also decide to re-factorize
1750*/
1751int
1752ClpSimplex::housekeeping(double objectiveChange)
1753{
1754 // save value of incoming and outgoing
1755 double oldIn = solution_[sequenceIn_];
1756 double oldOut = solution_[sequenceOut_];
1757 numberIterations_++;
1758 changeMade_++; // something has happened
1759 // incoming variable
1760 if (handler_->logLevel() > 7) {
1761 //if (handler_->detail(CLP_SIMPLEX_HOUSE1,messages_)<100) {
1762 handler_->message(CLP_SIMPLEX_HOUSE1, messages_)
1763 << directionOut_
1764 << directionIn_ << theta_
1765 << dualOut_ << dualIn_ << alpha_
1766 << CoinMessageEol;
1767 if (getStatus(sequenceIn_) == isFree) {
1768 handler_->message(CLP_SIMPLEX_FREEIN, messages_)
1769 << sequenceIn_
1770 << CoinMessageEol;
1771 }
1772 }
1773#if 0
1774 printf("h1 %d %d %g %g %g %g",
1775 directionOut_
1776 , directionIn_, theta_
1777 , dualOut_, dualIn_, alpha_);
1778#endif
1779 // change of incoming
1780 char rowcol[] = {'R', 'C'};
1781 if (pivotRow_ >= 0)
1782 pivotVariable_[pivotRow_] = sequenceIn();
1783 if (upper_[sequenceIn_] > 1.0e20 && lower_[sequenceIn_] < -1.0e20)
1784 progressFlag_ |= 2; // making real progress
1785 solution_[sequenceIn_] = valueIn_;
1786 if (upper_[sequenceOut_] - lower_[sequenceOut_] < 1.0e-12)
1787 progressFlag_ |= 1; // making real progress
1788 if (sequenceIn_ != sequenceOut_) {
1789 if (alphaAccuracy_ > 0.0) {
1790 double value = fabs(alpha_);
1791 if (value > 1.0)
1792 alphaAccuracy_ *= value;
1793 else
1794 alphaAccuracy_ /= value;
1795 }
1796 //assert( getStatus(sequenceOut_)== basic);
1797 setStatus(sequenceIn_, basic);
1798 if (upper_[sequenceOut_] - lower_[sequenceOut_] > 0) {
1799 // As Nonlinear costs may have moved bounds (to more feasible)
1800 // Redo using value
1801 if (fabs(valueOut_ - lower_[sequenceOut_]) < fabs(valueOut_ - upper_[sequenceOut_])) {
1802 // going to lower
1803 setStatus(sequenceOut_, atLowerBound);
1804 oldOut = lower_[sequenceOut_];
1805 } else {
1806 // going to upper
1807 setStatus(sequenceOut_, atUpperBound);
1808 oldOut = upper_[sequenceOut_];
1809 }
1810 } else {
1811 // fixed
1812 setStatus(sequenceOut_, isFixed);
1813 }
1814 solution_[sequenceOut_] = valueOut_;
1815 } else {
1816 //if (objective_->type()<2)
1817 //assert (fabs(theta_)>1.0e-13);
1818 // flip from bound to bound
1819 // As Nonlinear costs may have moved bounds (to more feasible)
1820 // Redo using value
1821 if (fabs(valueIn_ - lower_[sequenceIn_]) < fabs(valueIn_ - upper_[sequenceIn_])) {
1822 // as if from upper bound
1823 setStatus(sequenceIn_, atLowerBound);
1824 } else {
1825 // as if from lower bound
1826 setStatus(sequenceIn_, atUpperBound);
1827 }
1828 }
1829
1830 // Update hidden stuff e.g. effective RHS and gub
1831 int invertNow=matrix_->updatePivot(this, oldIn, oldOut);
1832 objectiveValue_ += objectiveChange / (objectiveScale_ * rhsScale_);
1833 if (handler_->logLevel() > 7) {
1834 //if (handler_->detail(CLP_SIMPLEX_HOUSE2,messages_)<100) {
1835 handler_->message(CLP_SIMPLEX_HOUSE2, messages_)
1836 << numberIterations_ << objectiveValue()
1837 << rowcol[isColumn(sequenceIn_)] << sequenceWithin(sequenceIn_)
1838 << rowcol[isColumn(sequenceOut_)] << sequenceWithin(sequenceOut_);
1839 handler_->printing(algorithm_ < 0) << dualOut_ << theta_;
1840 handler_->printing(algorithm_ > 0) << dualIn_ << theta_;
1841 handler_->message() << CoinMessageEol;
1842 }
1843#if 0
1844 if (numberIterations_ > 10000)
1845 printf(" it %d %g %c%d %c%d\n"
1846 , numberIterations_, objectiveValue()
1847 , rowcol[isColumn(sequenceIn_)], sequenceWithin(sequenceIn_)
1848 , rowcol[isColumn(sequenceOut_)], sequenceWithin(sequenceOut_));
1849#endif
1850 if (trustedUserPointer_ && trustedUserPointer_->typeStruct == 1) {
1851 if (algorithm_ > 0 && integerType_ && !nonLinearCost_->numberInfeasibilities()) {
1852 if (fabs(theta_) > 1.0e-6 || !numberIterations_) {
1853 // For saving solutions
1854 typedef struct {
1855 int numberSolutions;
1856 int maximumSolutions;
1857 int numberColumns;
1858 double ** solution;
1859 int * numberUnsatisfied;
1860 } clpSolution;
1861 clpSolution * solution = reinterpret_cast<clpSolution *> (trustedUserPointer_->data);
1862 if (solution->numberSolutions == solution->maximumSolutions) {
1863 int n = solution->maximumSolutions;
1864 int n2 = (n * 3) / 2 + 10;
1865 solution->maximumSolutions = n2;
1866 double ** temp = new double * [n2];
1867 for (int i = 0; i < n; i++)
1868 temp[i] = solution->solution[i];
1869 delete [] solution->solution;
1870 solution->solution = temp;
1871 int * tempN = new int [n2];
1872 for (int i = 0; i < n; i++)
1873 tempN[i] = solution->numberUnsatisfied[i];
1874 delete [] solution->numberUnsatisfied;
1875 solution->numberUnsatisfied = tempN;
1876 }
1877 assert (numberColumns_ == solution->numberColumns);
1878 double * sol = new double [numberColumns_];
1879 solution->solution[solution->numberSolutions] = sol;
1880 int numberFixed = 0;
1881 int numberUnsat = 0;
1882 int numberSat = 0;
1883 double sumUnsat = 0.0;
1884 double tolerance = 10.0 * primalTolerance_;
1885 double mostAway = 0.0;
1886 for (int i = 0; i < numberColumns_; i++) {
1887 // Save anyway
1888 sol[i] = columnScale_ ? solution_[i] * columnScale_[i] : solution_[i];
1889 // rest is optional
1890 if (upper_[i] > lower_[i]) {
1891 double value = solution_[i];
1892 if (value > lower_[i] + tolerance &&
1893 value < upper_[i] - tolerance && integerType_[i]) {
1894 // may have to modify value if scaled
1895 if (columnScale_)
1896 value *= columnScale_[i];
1897 double closest = floor(value + 0.5);
1898 // problem may be perturbed so relax test
1899 if (fabs(value - closest) > 1.0e-4) {
1900 numberUnsat++;
1901 sumUnsat += fabs(value - closest);
1902 if (mostAway < fabs(value - closest)) {
1903 mostAway = fabs(value - closest);
1904 }
1905 } else {
1906 numberSat++;
1907 }
1908 } else {
1909 numberSat++;
1910 }
1911 } else {
1912 numberFixed++;
1913 }
1914 }
1915 solution->numberUnsatisfied[solution->numberSolutions++] = numberUnsat;
1916 COIN_DETAIL_PRINT(printf("iteration %d, %d unsatisfied (%g,%g), %d fixed, %d satisfied\n",
1917 numberIterations_, numberUnsat, sumUnsat, mostAway, numberFixed, numberSat));
1918 }
1919 }
1920 }
1921 if (hitMaximumIterations())
1922 return 2;
1923#if 1
1924 //if (numberIterations_>14000)
1925 //handler_->setLogLevel(63);
1926 //if (numberIterations_>24000)
1927 //exit(77);
1928 // check for small cycles
1929 int in = sequenceIn_;
1930 int out = sequenceOut_;
1931 matrix_->correctSequence(this, in, out);
1932 int cycle = progress_.cycle(in, out,
1933 directionIn_, directionOut_);
1934 if (cycle > 0 && objective_->type() < 2 && matrix_->type() < 15) {
1935 //if (cycle>0) {
1936 if (handler_->logLevel() >= 63)
1937 printf("Cycle of %d\n", cycle);
1938 // reset
1939 progress_.startCheck();
1940 double random = randomNumberGenerator_.randomDouble();
1941 int extra = static_cast<int> (9.999 * random);
1942 int off[] = {1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
1943 if (factorization_->pivots() > cycle) {
1944 forceFactorization_ = CoinMax(1, cycle - off[extra]);
1945 } else {
1946 /* need to reject something
1947 should be better if don't reject incoming
1948 as it is in basis */
1949 int iSequence;
1950 //if (algorithm_ > 0)
1951 // iSequence = sequenceIn_;
1952 //else
1953 iSequence = sequenceOut_;
1954 char x = isColumn(iSequence) ? 'C' : 'R';
1955 if (handler_->logLevel() >= 63)
1956 handler_->message(CLP_SIMPLEX_FLAG, messages_)
1957 << x << sequenceWithin(iSequence)
1958 << CoinMessageEol;
1959 setFlagged(iSequence);
1960 //printf("flagging %d\n",iSequence);
1961 }
1962 return 1;
1963 }
1964#endif
1965 // only time to re-factorize if one before real time
1966 // this is so user won't be surprised that maximumPivots has exact meaning
1967 int numberPivots = factorization_->pivots();
1968 int maximumPivots = factorization_->maximumPivots();
1969 int numberDense = factorization_->numberDense();
1970 bool dontInvert = ((specialOptions_ & 16384) != 0 && numberIterations_ * 3 >
1971 2 * maximumIterations());
1972 if (numberPivots == maximumPivots ||
1973 maximumPivots < 2) {
1974 // If dense then increase
1975 if (maximumPivots > 100 && numberDense > 1.5 * maximumPivots) {
1976 factorization_->maximumPivots(numberDense);
1977 dualRowPivot_->maximumPivotsChanged();
1978 primalColumnPivot_->maximumPivotsChanged();
1979 // and redo arrays
1980 for (int iRow = 0; iRow < 4; iRow++) {
1981 int length = rowArray_[iRow]->capacity() + numberDense - maximumPivots;
1982 rowArray_[iRow]->reserve(length);
1983 }
1984 }
1985 return 1;
1986 } else if ((factorization_->timeToRefactorize() && !dontInvert)
1987 ||invertNow) {
1988 //printf("ret after %d pivots\n",factorization_->pivots());
1989 return 1;
1990 } else if (forceFactorization_ > 0 &&
1991 factorization_->pivots() == forceFactorization_) {
1992 // relax
1993 forceFactorization_ = (3 + 5 * forceFactorization_) / 4;
1994 if (forceFactorization_ > factorization_->maximumPivots())
1995 forceFactorization_ = -1; //off
1996 return 1;
1997 } else if (numberIterations_ > 1000 + 10 * (numberRows_ + (numberColumns_ >> 2)) && matrix_->type()<15) {
1998 // A bit worried problem may be cycling - lets factorize at random intervals for a short period
1999 int numberTooManyIterations = numberIterations_ - 10 * (numberRows_ + (numberColumns_ >> 2));
2000 double random = randomNumberGenerator_.randomDouble();
2001 int window = numberTooManyIterations%5000;
2002 if (window<2*maximumPivots)
2003 random = 0.2*random+0.8; // randomly re-factorize but not too soon
2004 else
2005 random=1.0; // switch off if not in window of opportunity
2006 int maxNumber = (forceFactorization_ < 0) ? maximumPivots : CoinMin(forceFactorization_, maximumPivots);
2007 if (factorization_->pivots() >= random * maxNumber) {
2008 return 1;
2009 } else if (numberIterations_ > 1000000 + 10 * (numberRows_ + (numberColumns_ >> 2)) &&
2010 numberIterations_ < 1001000 + 10 * (numberRows_ + (numberColumns_ >> 2))) {
2011 return 1;
2012 } else {
2013 // carry on iterating
2014 return 0;
2015 }
2016 } else {
2017 // carry on iterating
2018 return 0;
2019 }
2020}
2021// Copy constructor.
2022ClpSimplex::ClpSimplex(const ClpSimplex &rhs, int scalingMode) :
2023 ClpModel(rhs, scalingMode),
2024 bestPossibleImprovement_(0.0),
2025 zeroTolerance_(1.0e-13),
2026 columnPrimalSequence_(-2),
2027 rowPrimalSequence_(-2),
2028 bestObjectiveValue_(rhs.bestObjectiveValue_),
2029 moreSpecialOptions_(2),
2030 baseIteration_(0),
2031 primalToleranceToGetOptimal_(-1.0),
2032 largeValue_(1.0e15),
2033 largestPrimalError_(0.0),
2034 largestDualError_(0.0),
2035 alphaAccuracy_(-1.0),
2036 dualBound_(1.0e10),
2037 alpha_(0.0),
2038 theta_(0.0),
2039 lowerIn_(0.0),
2040 valueIn_(0.0),
2041 upperIn_(-COIN_DBL_MAX),
2042 dualIn_(0.0),
2043 lowerOut_(-1),
2044 valueOut_(-1),
2045 upperOut_(-1),
2046 dualOut_(-1),
2047 dualTolerance_(1.0e-7),
2048 primalTolerance_(1.0e-7),
2049 sumDualInfeasibilities_(0.0),
2050 sumPrimalInfeasibilities_(0.0),
2051 infeasibilityCost_(1.0e10),
2052 sumOfRelaxedDualInfeasibilities_(0.0),
2053 sumOfRelaxedPrimalInfeasibilities_(0.0),
2054 acceptablePivot_(1.0e-8),
2055 lower_(NULL),
2056 rowLowerWork_(NULL),
2057 columnLowerWork_(NULL),
2058 upper_(NULL),
2059 rowUpperWork_(NULL),
2060 columnUpperWork_(NULL),
2061 cost_(NULL),
2062 rowObjectiveWork_(NULL),
2063 objectiveWork_(NULL),
2064 sequenceIn_(-1),
2065 directionIn_(-1),
2066 sequenceOut_(-1),
2067 directionOut_(-1),
2068 pivotRow_(-1),
2069 lastGoodIteration_(-100),
2070 dj_(NULL),
2071 rowReducedCost_(NULL),
2072 reducedCostWork_(NULL),
2073 solution_(NULL),
2074 rowActivityWork_(NULL),
2075 columnActivityWork_(NULL),
2076 numberDualInfeasibilities_(0),
2077 numberDualInfeasibilitiesWithoutFree_(0),
2078 numberPrimalInfeasibilities_(100),
2079 numberRefinements_(0),
2080 pivotVariable_(NULL),
2081 factorization_(NULL),
2082 savedSolution_(NULL),
2083 numberTimesOptimal_(0),
2084 disasterArea_(NULL),
2085 changeMade_(1),
2086 algorithm_(0),
2087 forceFactorization_(-1),
2088 perturbation_(100),
2089 nonLinearCost_(NULL),
2090 lastBadIteration_(-999999),
2091 lastFlaggedIteration_(-999999),
2092 numberFake_(0),
2093 numberChanged_(0),
2094 progressFlag_(0),
2095 firstFree_(-1),
2096 numberExtraRows_(0),
2097 maximumBasic_(0),
2098 dontFactorizePivots_(0),
2099 incomingInfeasibility_(1.0),
2100 allowedInfeasibility_(10.0),
2101 automaticScale_(0),
2102 maximumPerturbationSize_(0),
2103 perturbationArray_(NULL),
2104 baseModel_(NULL)
2105{
2106 int i;
2107 for (i = 0; i < 6; i++) {
2108 rowArray_[i] = NULL;
2109 columnArray_[i] = NULL;
2110 }
2111 for (i = 0; i < 4; i++) {
2112 spareIntArray_[i] = 0;
2113 spareDoubleArray_[i] = 0.0;
2114 }
2115 saveStatus_ = NULL;
2116 factorization_ = NULL;
2117 dualRowPivot_ = NULL;
2118 primalColumnPivot_ = NULL;
2119 gutsOfDelete(0);
2120 delete nonLinearCost_;
2121 nonLinearCost_ = NULL;
2122 gutsOfCopy(rhs);
2123 solveType_ = 1; // say simplex based life form
2124}
2125// Copy constructor from model
2126ClpSimplex::ClpSimplex(const ClpModel &rhs, int scalingMode) :
2127 ClpModel(rhs, scalingMode),
2128 bestPossibleImprovement_(0.0),
2129 zeroTolerance_(1.0e-13),
2130 columnPrimalSequence_(-2),
2131 rowPrimalSequence_(-2),
2132 bestObjectiveValue_(-COIN_DBL_MAX),
2133 moreSpecialOptions_(2),
2134 baseIteration_(0),
2135 primalToleranceToGetOptimal_(-1.0),
2136 largeValue_(1.0e15),
2137 largestPrimalError_(0.0),
2138 largestDualError_(0.0),
2139 alphaAccuracy_(-1.0),
2140 dualBound_(1.0e10),
2141 alpha_(0.0),
2142 theta_(0.0),
2143 lowerIn_(0.0),
2144 valueIn_(0.0),
2145 upperIn_(-COIN_DBL_MAX),
2146 dualIn_(0.0),
2147 lowerOut_(-1),
2148 valueOut_(-1),
2149 upperOut_(-1),
2150 dualOut_(-1),
2151 dualTolerance_(1.0e-7),
2152 primalTolerance_(1.0e-7),
2153 sumDualInfeasibilities_(0.0),
2154 sumPrimalInfeasibilities_(0.0),
2155 infeasibilityCost_(1.0e10),
2156 sumOfRelaxedDualInfeasibilities_(0.0),
2157 sumOfRelaxedPrimalInfeasibilities_(0.0),
2158 acceptablePivot_(1.0e-8),
2159 lower_(NULL),
2160 rowLowerWork_(NULL),
2161 columnLowerWork_(NULL),
2162 upper_(NULL),
2163 rowUpperWork_(NULL),
2164 columnUpperWork_(NULL),
2165 cost_(NULL),
2166 rowObjectiveWork_(NULL),
2167 objectiveWork_(NULL),
2168 sequenceIn_(-1),
2169 directionIn_(-1),
2170 sequenceOut_(-1),
2171 directionOut_(-1),
2172 pivotRow_(-1),
2173 lastGoodIteration_(-100),
2174 dj_(NULL),
2175 rowReducedCost_(NULL),
2176 reducedCostWork_(NULL),
2177 solution_(NULL),
2178 rowActivityWork_(NULL),
2179 columnActivityWork_(NULL),
2180 numberDualInfeasibilities_(0),
2181 numberDualInfeasibilitiesWithoutFree_(0),
2182 numberPrimalInfeasibilities_(100),
2183 numberRefinements_(0),
2184 pivotVariable_(NULL),
2185 factorization_(NULL),
2186 savedSolution_(NULL),
2187 numberTimesOptimal_(0),
2188 disasterArea_(NULL),
2189 changeMade_(1),
2190 algorithm_(0),
2191 forceFactorization_(-1),
2192 perturbation_(100),
2193 nonLinearCost_(NULL),
2194 lastBadIteration_(-999999),
2195 lastFlaggedIteration_(-999999),
2196 numberFake_(0),
2197 numberChanged_(0),
2198 progressFlag_(0),
2199 firstFree_(-1),
2200 numberExtraRows_(0),
2201 maximumBasic_(0),
2202 dontFactorizePivots_(0),
2203 incomingInfeasibility_(1.0),
2204 allowedInfeasibility_(10.0),
2205 automaticScale_(0),
2206 maximumPerturbationSize_(0),
2207 perturbationArray_(NULL),
2208 baseModel_(NULL)
2209{
2210 int i;
2211 for (i = 0; i < 6; i++) {
2212 rowArray_[i] = NULL;
2213 columnArray_[i] = NULL;
2214 }
2215 for (i = 0; i < 4; i++) {
2216 spareIntArray_[i] = 0;
2217 spareDoubleArray_[i] = 0.0;
2218 }
2219 saveStatus_ = NULL;
2220 // get an empty factorization so we can set tolerances etc
2221 getEmptyFactorization();
2222 // say Steepest pricing
2223 dualRowPivot_ = new ClpDualRowSteepest();
2224 // say Steepest pricing
2225 primalColumnPivot_ = new ClpPrimalColumnSteepest();
2226 solveType_ = 1; // say simplex based life form
2227
2228}
2229// Assignment operator. This copies the data
2230ClpSimplex &
2231ClpSimplex::operator=(const ClpSimplex & rhs)
2232{
2233 if (this != &rhs) {
2234 gutsOfDelete(0);
2235 delete nonLinearCost_;
2236 nonLinearCost_ = NULL;
2237 ClpModel::operator=(rhs);
2238 gutsOfCopy(rhs);
2239 }
2240 return *this;
2241}
2242void
2243ClpSimplex::gutsOfCopy(const ClpSimplex & rhs)
2244{
2245 assert (numberRows_ == rhs.numberRows_);
2246 assert (numberColumns_ == rhs.numberColumns_);
2247 numberExtraRows_ = rhs.numberExtraRows_;
2248 maximumBasic_ = rhs.maximumBasic_;
2249 dontFactorizePivots_ = rhs.dontFactorizePivots_;
2250 int numberRows2 = numberRows_ + numberExtraRows_;
2251 moreSpecialOptions_ = rhs.moreSpecialOptions_;
2252 if ((whatsChanged_ & 1) != 0) {
2253 int numberTotal = numberColumns_ + numberRows2;
2254 if ((specialOptions_ & 65536) != 0 && maximumRows_ >= 0) {
2255 assert (maximumInternalRows_ >= numberRows2);
2256 assert (maximumInternalColumns_ >= numberColumns_);
2257 numberTotal = 2 * (maximumInternalColumns_ + maximumInternalRows_);
2258 }
2259 lower_ = ClpCopyOfArray(rhs.lower_, numberTotal);
2260 rowLowerWork_ = lower_ + numberColumns_;
2261 columnLowerWork_ = lower_;
2262 upper_ = ClpCopyOfArray(rhs.upper_, numberTotal);
2263 rowUpperWork_ = upper_ + numberColumns_;
2264 columnUpperWork_ = upper_;
2265 cost_ = ClpCopyOfArray(rhs.cost_, numberTotal);
2266 objectiveWork_ = cost_;
2267 rowObjectiveWork_ = cost_ + numberColumns_;
2268 dj_ = ClpCopyOfArray(rhs.dj_, numberTotal);
2269 if (dj_) {
2270 reducedCostWork_ = dj_;
2271 rowReducedCost_ = dj_ + numberColumns_;
2272 }
2273 solution_ = ClpCopyOfArray(rhs.solution_, numberTotal);
2274 if (solution_) {
2275 columnActivityWork_ = solution_;
2276 rowActivityWork_ = solution_ + numberColumns_;
2277 }
2278 if (rhs.pivotVariable_) {
2279 pivotVariable_ = new int[numberRows2];
2280 CoinMemcpyN ( rhs.pivotVariable_, numberRows2 , pivotVariable_);
2281 } else {
2282 pivotVariable_ = NULL;
2283 }
2284 savedSolution_ = ClpCopyOfArray(rhs.savedSolution_, numberTotal);
2285 int i;
2286 for (i = 0; i < 6; i++) {
2287 rowArray_[i] = NULL;
2288 if (rhs.rowArray_[i])
2289 rowArray_[i] = new CoinIndexedVector(*rhs.rowArray_[i]);
2290 columnArray_[i] = NULL;
2291 if (rhs.columnArray_[i])
2292 columnArray_[i] = new CoinIndexedVector(*rhs.columnArray_[i]);
2293 }
2294 if (rhs.saveStatus_) {
2295 saveStatus_ = ClpCopyOfArray( rhs.saveStatus_, numberTotal);
2296 }
2297 } else {
2298 lower_ = NULL;
2299 rowLowerWork_ = NULL;
2300 columnLowerWork_ = NULL;
2301 upper_ = NULL;
2302 rowUpperWork_ = NULL;
2303 columnUpperWork_ = NULL;
2304 cost_ = NULL;
2305 objectiveWork_ = NULL;
2306 rowObjectiveWork_ = NULL;
2307 dj_ = NULL;
2308 reducedCostWork_ = NULL;
2309 rowReducedCost_ = NULL;
2310 solution_ = NULL;
2311 columnActivityWork_ = NULL;
2312 rowActivityWork_ = NULL;
2313 pivotVariable_ = NULL;
2314 savedSolution_ = NULL;
2315 int i;
2316 for (i = 0; i < 6; i++) {
2317 rowArray_[i] = NULL;
2318 columnArray_[i] = NULL;
2319 }
2320 saveStatus_ = NULL;
2321 }
2322 if (rhs.factorization_) {
2323 setFactorization(*rhs.factorization_);
2324 } else {
2325 delete factorization_;
2326 factorization_ = NULL;
2327 }
2328 bestPossibleImprovement_ = rhs.bestPossibleImprovement_;
2329 columnPrimalSequence_ = rhs.columnPrimalSequence_;
2330 zeroTolerance_ = rhs.zeroTolerance_;
2331 rowPrimalSequence_ = rhs.rowPrimalSequence_;
2332 bestObjectiveValue_ = rhs.bestObjectiveValue_;
2333 baseIteration_ = rhs.baseIteration_;
2334 primalToleranceToGetOptimal_ = rhs.primalToleranceToGetOptimal_;
2335 largeValue_ = rhs.largeValue_;
2336 largestPrimalError_ = rhs.largestPrimalError_;
2337 largestDualError_ = rhs.largestDualError_;
2338 alphaAccuracy_ = rhs.alphaAccuracy_;
2339 dualBound_ = rhs.dualBound_;
2340 alpha_ = rhs.alpha_;
2341 theta_ = rhs.theta_;
2342 lowerIn_ = rhs.lowerIn_;
2343 valueIn_ = rhs.valueIn_;
2344 upperIn_ = rhs.upperIn_;
2345 dualIn_ = rhs.dualIn_;
2346 sequenceIn_ = rhs.sequenceIn_;
2347 directionIn_ = rhs.directionIn_;
2348 lowerOut_ = rhs.lowerOut_;
2349 valueOut_ = rhs.valueOut_;
2350 upperOut_ = rhs.upperOut_;
2351 dualOut_ = rhs.dualOut_;
2352 sequenceOut_ = rhs.sequenceOut_;
2353 directionOut_ = rhs.directionOut_;
2354 pivotRow_ = rhs.pivotRow_;
2355 lastGoodIteration_ = rhs.lastGoodIteration_;
2356 numberRefinements_ = rhs.numberRefinements_;
2357 dualTolerance_ = rhs.dualTolerance_;
2358 primalTolerance_ = rhs.primalTolerance_;
2359 sumDualInfeasibilities_ = rhs.sumDualInfeasibilities_;
2360 numberDualInfeasibilities_ = rhs.numberDualInfeasibilities_;
2361 numberDualInfeasibilitiesWithoutFree_ =
2362 rhs.numberDualInfeasibilitiesWithoutFree_;
2363 sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_;
2364 numberPrimalInfeasibilities_ = rhs.numberPrimalInfeasibilities_;
2365 dualRowPivot_ = rhs.dualRowPivot_->clone(true);
2366 dualRowPivot_->setModel(this);
2367 primalColumnPivot_ = rhs.primalColumnPivot_->clone(true);
2368 primalColumnPivot_->setModel(this);
2369 numberTimesOptimal_ = rhs.numberTimesOptimal_;
2370 disasterArea_ = NULL;
2371 changeMade_ = rhs.changeMade_;
2372 algorithm_ = rhs.algorithm_;
2373 forceFactorization_ = rhs.forceFactorization_;
2374 perturbation_ = rhs.perturbation_;
2375 infeasibilityCost_ = rhs.infeasibilityCost_;
2376 lastBadIteration_ = rhs.lastBadIteration_;
2377 lastFlaggedIteration_ = rhs.lastFlaggedIteration_;
2378 numberFake_ = rhs.numberFake_;
2379 numberChanged_ = rhs.numberChanged_;
2380 progressFlag_ = rhs.progressFlag_;
2381 firstFree_ = rhs.firstFree_;
2382 incomingInfeasibility_ = rhs.incomingInfeasibility_;
2383 allowedInfeasibility_ = rhs.allowedInfeasibility_;
2384 automaticScale_ = rhs.automaticScale_;
2385 maximumPerturbationSize_ = rhs.maximumPerturbationSize_;
2386 if (maximumPerturbationSize_ && maximumPerturbationSize_ >= 2 * numberColumns_) {
2387 perturbationArray_ = CoinCopyOfArray(rhs.perturbationArray_,
2388 maximumPerturbationSize_);
2389 } else {
2390 maximumPerturbationSize_ = 0;
2391 perturbationArray_ = NULL;
2392 }
2393 if (rhs.baseModel_) {
2394 baseModel_ = new ClpSimplex(*rhs.baseModel_);
2395 } else {
2396 baseModel_ = NULL;
2397 }
2398 progress_ = rhs.progress_;
2399 for (int i = 0; i < 4; i++) {
2400 spareIntArray_[i] = rhs.spareIntArray_[i];
2401 spareDoubleArray_[i] = rhs.spareDoubleArray_[i];
2402 }
2403 sumOfRelaxedDualInfeasibilities_ = rhs.sumOfRelaxedDualInfeasibilities_;
2404 sumOfRelaxedPrimalInfeasibilities_ = rhs.sumOfRelaxedPrimalInfeasibilities_;
2405 acceptablePivot_ = rhs.acceptablePivot_;
2406 if (rhs.nonLinearCost_ != NULL)
2407 nonLinearCost_ = new ClpNonLinearCost(*rhs.nonLinearCost_);
2408 else
2409 nonLinearCost_ = NULL;
2410 solveType_ = rhs.solveType_;
2411}
2412// type == 0 do everything, most + pivot data, 2 factorization data as well
2413void
2414ClpSimplex::gutsOfDelete(int type)
2415{
2416 if (!type || (specialOptions_ & 65536) == 0) {
2417 maximumInternalColumns_ = -1;
2418 maximumInternalRows_ = -1;
2419 delete [] lower_;
2420 lower_ = NULL;
2421 rowLowerWork_ = NULL;
2422 columnLowerWork_ = NULL;
2423 delete [] upper_;
2424 upper_ = NULL;
2425 rowUpperWork_ = NULL;
2426 columnUpperWork_ = NULL;
2427 delete [] cost_;
2428 cost_ = NULL;
2429 objectiveWork_ = NULL;
2430 rowObjectiveWork_ = NULL;
2431 delete [] dj_;
2432 dj_ = NULL;
2433 reducedCostWork_ = NULL;
2434 rowReducedCost_ = NULL;
2435 delete [] solution_;
2436 solution_ = NULL;
2437 rowActivityWork_ = NULL;
2438 columnActivityWork_ = NULL;
2439 delete [] savedSolution_;
2440 savedSolution_ = NULL;
2441 }
2442 if ((specialOptions_ & 2) == 0) {
2443 delete nonLinearCost_;
2444 nonLinearCost_ = NULL;
2445 }
2446 int i;
2447 if ((specialOptions_ & 65536) == 0) {
2448 for (i = 0; i < 6; i++) {
2449 delete rowArray_[i];
2450 rowArray_[i] = NULL;
2451 delete columnArray_[i];
2452 columnArray_[i] = NULL;
2453 }
2454 }
2455 delete [] saveStatus_;
2456 saveStatus_ = NULL;
2457 if (type != 1) {
2458 delete rowCopy_;
2459 rowCopy_ = NULL;
2460 }
2461 if (!type) {
2462 // delete everything
2463 setEmptyFactorization();
2464 delete [] pivotVariable_;
2465 pivotVariable_ = NULL;
2466 delete dualRowPivot_;
2467 dualRowPivot_ = NULL;
2468 delete primalColumnPivot_;
2469 primalColumnPivot_ = NULL;
2470 delete baseModel_;
2471 baseModel_ = NULL;
2472 delete [] perturbationArray_;
2473 perturbationArray_ = NULL;
2474 maximumPerturbationSize_ = 0;
2475 } else {
2476 // delete any size information in methods
2477 if (type > 1) {
2478 //assert (factorization_);
2479 if (factorization_)
2480 factorization_->clearArrays();
2481 delete [] pivotVariable_;
2482 pivotVariable_ = NULL;
2483 }
2484 dualRowPivot_->clearArrays();
2485 primalColumnPivot_->clearArrays();
2486 }
2487}
2488// This sets largest infeasibility and most infeasible
2489void
2490ClpSimplex::checkPrimalSolution(const double * rowActivities,
2491 const double * columnActivities)
2492{
2493 double * solution;
2494 int iRow, iColumn;
2495
2496 objectiveValue_ = 0.0;
2497 // now look at primal solution
2498 solution = rowActivityWork_;
2499 sumPrimalInfeasibilities_ = 0.0;
2500 numberPrimalInfeasibilities_ = 0;
2501 double primalTolerance = primalTolerance_;
2502 double relaxedTolerance = primalTolerance_;
2503 // we can't really trust infeasibilities if there is primal error
2504 double error = CoinMin(1.0e-2, largestPrimalError_);
2505 // allow tolerance at least slightly bigger than standard
2506 relaxedTolerance = relaxedTolerance + error;
2507 sumOfRelaxedPrimalInfeasibilities_ = 0.0;
2508 for (iRow = 0; iRow < numberRows_; iRow++) {
2509 //assert (fabs(solution[iRow])<1.0e15||getRowStatus(iRow) == basic);
2510 double infeasibility = 0.0;
2511 objectiveValue_ += solution[iRow] * rowObjectiveWork_[iRow];
2512 if (solution[iRow] > rowUpperWork_[iRow]) {
2513 infeasibility = solution[iRow] - rowUpperWork_[iRow];
2514 } else if (solution[iRow] < rowLowerWork_[iRow]) {
2515 infeasibility = rowLowerWork_[iRow] - solution[iRow];
2516 }
2517 if (infeasibility > primalTolerance) {
2518 sumPrimalInfeasibilities_ += infeasibility - primalTolerance_;
2519 if (infeasibility > relaxedTolerance)
2520 sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance;
2521 numberPrimalInfeasibilities_ ++;
2522 }
2523 infeasibility = fabs(rowActivities[iRow] - solution[iRow]);
2524 }
2525 // Check any infeasibilities from dynamic rows
2526 matrix_->primalExpanded(this, 2);
2527 solution = columnActivityWork_;
2528 if (!matrix_->rhsOffset(this)) {
2529 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2530 //assert (fabs(solution[iColumn])<1.0e15||getColumnStatus(iColumn) == basic);
2531 double infeasibility = 0.0;
2532 objectiveValue_ += objectiveWork_[iColumn] * solution[iColumn];
2533 if (solution[iColumn] > columnUpperWork_[iColumn]) {
2534 infeasibility = solution[iColumn] - columnUpperWork_[iColumn];
2535 } else if (solution[iColumn] < columnLowerWork_[iColumn]) {
2536 infeasibility = columnLowerWork_[iColumn] - solution[iColumn];
2537 }
2538 if (infeasibility > primalTolerance) {
2539 sumPrimalInfeasibilities_ += infeasibility - primalTolerance_;
2540 if (infeasibility > relaxedTolerance)
2541 sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance;
2542 numberPrimalInfeasibilities_ ++;
2543 }
2544 infeasibility = fabs(columnActivities[iColumn] - solution[iColumn]);
2545 }
2546 } else {
2547 // as we are using effective rhs we only check basics
2548 // But we do need to get objective
2549 objectiveValue_ += innerProduct(objectiveWork_, numberColumns_, solution);
2550 for (int j = 0; j < numberRows_; j++) {
2551 int iColumn = pivotVariable_[j];
2552 //assert (fabs(solution[iColumn])<1.0e15||getColumnStatus(iColumn) == basic);
2553 double infeasibility = 0.0;
2554 if (solution[iColumn] > columnUpperWork_[iColumn]) {
2555 infeasibility = solution[iColumn] - columnUpperWork_[iColumn];
2556 } else if (solution[iColumn] < columnLowerWork_[iColumn]) {
2557 infeasibility = columnLowerWork_[iColumn] - solution[iColumn];
2558 }
2559 if (infeasibility > primalTolerance) {
2560 sumPrimalInfeasibilities_ += infeasibility - primalTolerance_;
2561 if (infeasibility > relaxedTolerance)
2562 sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedTolerance;
2563 numberPrimalInfeasibilities_ ++;
2564 }
2565 infeasibility = fabs(columnActivities[iColumn] - solution[iColumn]);
2566 }
2567 }
2568 objectiveValue_ += objective_->nonlinearOffset();
2569 objectiveValue_ /= (objectiveScale_ * rhsScale_);
2570}
2571void
2572ClpSimplex::checkDualSolution()
2573{
2574
2575 int iRow, iColumn;
2576 sumDualInfeasibilities_ = 0.0;
2577 numberDualInfeasibilities_ = 0;
2578 numberDualInfeasibilitiesWithoutFree_ = 0;
2579 if (matrix_->skipDualCheck() && algorithm_ > 0 && problemStatus_ == -2) {
2580 // pretend we found dual infeasibilities
2581 sumOfRelaxedDualInfeasibilities_ = 1.0;
2582 sumDualInfeasibilities_ = 1.0;
2583 numberDualInfeasibilities_ = 1;
2584 return;
2585 }
2586 int firstFreePrimal = -1;
2587 int firstFreeDual = -1;
2588 int numberSuperBasicWithDj = 0;
2589 bestPossibleImprovement_ = 0.0;
2590 // we can't really trust infeasibilities if there is dual error
2591 double error = CoinMin(1.0e-2, largestDualError_);
2592 // allow tolerance at least slightly bigger than standard
2593 double relaxedTolerance = dualTolerance_ + error;
2594 // allow bigger tolerance for possible improvement
2595 double possTolerance = 5.0 * relaxedTolerance;
2596 sumOfRelaxedDualInfeasibilities_ = 0.0;
2597
2598 // Check any djs from dynamic rows
2599 matrix_->dualExpanded(this, NULL, NULL, 3);
2600 numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilities_;
2601 objectiveValue_ = 0.0;
2602 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2603 objectiveValue_ += objectiveWork_[iColumn] * columnActivityWork_[iColumn];
2604 if (getColumnStatus(iColumn) != basic && !flagged(iColumn)) {
2605 // not basic
2606 double distanceUp = columnUpperWork_[iColumn] -
2607 columnActivityWork_[iColumn];
2608 double distanceDown = columnActivityWork_[iColumn] -
2609 columnLowerWork_[iColumn];
2610 if (distanceUp > primalTolerance_) {
2611 double value = reducedCostWork_[iColumn];
2612 // Check if "free"
2613 if (distanceDown > primalTolerance_) {
2614 if (fabs(value) > 1.0e2 * relaxedTolerance) {
2615 numberSuperBasicWithDj++;
2616 if (firstFreeDual < 0)
2617 firstFreeDual = iColumn;
2618 }
2619 if (firstFreePrimal < 0)
2620 firstFreePrimal = iColumn;
2621 }
2622 // should not be negative
2623 if (value < 0.0) {
2624 value = - value;
2625 if (value > dualTolerance_) {
2626 if (getColumnStatus(iColumn) != isFree) {
2627 numberDualInfeasibilitiesWithoutFree_ ++;
2628 sumDualInfeasibilities_ += value - dualTolerance_;
2629 if (value > possTolerance)
2630 bestPossibleImprovement_ += CoinMin(distanceUp, 1.0e10) * value;
2631 if (value > relaxedTolerance)
2632 sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance;
2633 numberDualInfeasibilities_ ++;
2634 } else {
2635 // free so relax a lot
2636 value *= 0.01;
2637 if (value > dualTolerance_) {
2638 sumDualInfeasibilities_ += value - dualTolerance_;
2639 if (value > possTolerance)
2640 bestPossibleImprovement_ = 1.0e100;
2641 if (value > relaxedTolerance)
2642 sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance;
2643 numberDualInfeasibilities_ ++;
2644 }
2645 }
2646 }
2647 }
2648 }
2649 if (distanceDown > primalTolerance_) {
2650 double value = reducedCostWork_[iColumn];
2651 // should not be positive
2652 if (value > 0.0) {
2653 if (value > dualTolerance_) {
2654 sumDualInfeasibilities_ += value - dualTolerance_;
2655 if (value > possTolerance)
2656 bestPossibleImprovement_ += value * CoinMin(distanceDown, 1.0e10);
2657 if (value > relaxedTolerance)
2658 sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance;
2659 numberDualInfeasibilities_ ++;
2660 if (getColumnStatus(iColumn) != isFree)
2661 numberDualInfeasibilitiesWithoutFree_ ++;
2662 // maybe we can make feasible by increasing tolerance
2663 }
2664 }
2665 }
2666 }
2667 }
2668 for (iRow = 0; iRow < numberRows_; iRow++) {
2669 objectiveValue_ += rowActivityWork_[iRow] * rowObjectiveWork_[iRow];
2670 if (getRowStatus(iRow) != basic && !flagged(iRow + numberColumns_)) {
2671 // not basic
2672 double distanceUp = rowUpperWork_[iRow] - rowActivityWork_[iRow];
2673 double distanceDown = rowActivityWork_[iRow] - rowLowerWork_[iRow];
2674 if (distanceUp > primalTolerance_) {
2675 double value = rowReducedCost_[iRow];
2676 // Check if "free"
2677 if (distanceDown > primalTolerance_) {
2678 if (fabs(value) > 1.0e2 * relaxedTolerance) {
2679 numberSuperBasicWithDj++;
2680 if (firstFreeDual < 0)
2681 firstFreeDual = iRow + numberColumns_;
2682 }
2683 if (firstFreePrimal < 0)
2684 firstFreePrimal = iRow + numberColumns_;
2685 }
2686 // should not be negative
2687 if (value < 0.0) {
2688 value = - value;
2689 if (value > dualTolerance_) {
2690 sumDualInfeasibilities_ += value - dualTolerance_;
2691 if (value > possTolerance)
2692 bestPossibleImprovement_ += value * CoinMin(distanceUp, 1.0e10);
2693 if (value > relaxedTolerance)
2694 sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance;
2695 numberDualInfeasibilities_ ++;
2696 if (getRowStatus(iRow) != isFree)
2697 numberDualInfeasibilitiesWithoutFree_ ++;
2698 }
2699 }
2700 }
2701 if (distanceDown > primalTolerance_) {
2702 double value = rowReducedCost_[iRow];
2703 // should not be positive
2704 if (value > 0.0) {
2705 if (value > dualTolerance_) {
2706 sumDualInfeasibilities_ += value - dualTolerance_;
2707 if (value > possTolerance)
2708 bestPossibleImprovement_ += value * CoinMin(distanceDown, 1.0e10);
2709 if (value > relaxedTolerance)
2710 sumOfRelaxedDualInfeasibilities_ += value - relaxedTolerance;
2711 numberDualInfeasibilities_ ++;
2712 if (getRowStatus(iRow) != isFree)
2713 numberDualInfeasibilitiesWithoutFree_ ++;
2714 // maybe we can make feasible by increasing tolerance
2715 }
2716 }
2717 }
2718 }
2719 }
2720 if (algorithm_ < 0 && firstFreeDual >= 0) {
2721 // dual
2722 firstFree_ = firstFreeDual;
2723 } else if (numberSuperBasicWithDj ||
2724 (progress_.lastIterationNumber(0) <= 0)) {
2725 firstFree_ = firstFreePrimal;
2726 }
2727 objectiveValue_ += objective_->nonlinearOffset();
2728 objectiveValue_ /= (objectiveScale_ * rhsScale_);
2729}
2730/* This sets sum and number of infeasibilities (Dual and Primal) */
2731void
2732ClpSimplex::checkBothSolutions()
2733{
2734 if ((matrix_->skipDualCheck() && algorithm_ > 0 && problemStatus_ == -2) ||
2735 matrix_->rhsOffset(this)) {
2736 // Say may be free or superbasic
2737 moreSpecialOptions_ &= ~8;
2738 // old way
2739 checkPrimalSolution(rowActivityWork_, columnActivityWork_);
2740 checkDualSolution();
2741 return;
2742 }
2743 int iSequence;
2744 assert (dualTolerance_ > 0.0 && dualTolerance_ < 1.0e10);
2745 assert (primalTolerance_ > 0.0 && primalTolerance_ < 1.0e10);
2746 objectiveValue_ = 0.0;
2747 sumPrimalInfeasibilities_ = 0.0;
2748 numberPrimalInfeasibilities_ = 0;
2749 double primalTolerance = primalTolerance_;
2750 double relaxedToleranceP = primalTolerance_;
2751 // we can't really trust infeasibilities if there is primal error
2752 double error = CoinMin(1.0e-2, largestPrimalError_);
2753 // allow tolerance at least slightly bigger than standard
2754 relaxedToleranceP = relaxedToleranceP + error;
2755 sumOfRelaxedPrimalInfeasibilities_ = 0.0;
2756 sumDualInfeasibilities_ = 0.0;
2757 numberDualInfeasibilities_ = 0;
2758 double dualTolerance = dualTolerance_;
2759 double relaxedToleranceD = dualTolerance;
2760 // we can't really trust infeasibilities if there is dual error
2761 error = CoinMin(1.0e-2, largestDualError_);
2762 // allow tolerance at least slightly bigger than standard
2763 relaxedToleranceD = relaxedToleranceD + error;
2764 // allow bigger tolerance for possible improvement
2765 double possTolerance = 5.0 * relaxedToleranceD;
2766 sumOfRelaxedDualInfeasibilities_ = 0.0;
2767 bestPossibleImprovement_ = 0.0;
2768
2769 // Check any infeasibilities from dynamic rows
2770 matrix_->primalExpanded(this, 2);
2771 // Check any djs from dynamic rows
2772 matrix_->dualExpanded(this, NULL, NULL, 3);
2773 int numberDualInfeasibilitiesFree = 0;
2774 int firstFreePrimal = -1;
2775 int firstFreeDual = -1;
2776 int numberSuperBasicWithDj = 0;
2777
2778 int numberTotal = numberRows_ + numberColumns_;
2779 // Say no free or superbasic
2780 moreSpecialOptions_ |= 8;
2781 //#define PRINT_INFEAS
2782#ifdef PRINT_INFEAS
2783 int seqInf[10];
2784#endif
2785 for (iSequence = 0; iSequence < numberTotal; iSequence++) {
2786 double value = solution_[iSequence];
2787#ifdef COIN_DEBUG
2788 if (fabs(value) > 1.0e20)
2789 printf("%d values %g %g %g - status %d\n", iSequence, lower_[iSequence],
2790 solution_[iSequence], upper_[iSequence], status_[iSequence]);
2791#endif
2792 objectiveValue_ += value * cost_[iSequence];
2793 double distanceUp = upper_[iSequence] - value;
2794 double distanceDown = value - lower_[iSequence];
2795 if (distanceUp < -primalTolerance) {
2796 double infeasibility = -distanceUp;
2797 sumPrimalInfeasibilities_ += infeasibility - primalTolerance_;
2798 if (infeasibility > relaxedToleranceP)
2799 sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedToleranceP;
2800#ifdef PRINT_INFEAS
2801 if (numberPrimalInfeasibilities_<10) {
2802 seqInf[numberPrimalInfeasibilities_]=iSequence;
2803 }
2804#endif
2805 numberPrimalInfeasibilities_ ++;
2806 } else if (distanceDown < -primalTolerance) {
2807 double infeasibility = -distanceDown;
2808 sumPrimalInfeasibilities_ += infeasibility - primalTolerance_;
2809 if (infeasibility > relaxedToleranceP)
2810 sumOfRelaxedPrimalInfeasibilities_ += infeasibility - relaxedToleranceP;
2811#ifdef PRINT_INFEAS
2812 if (numberPrimalInfeasibilities_<10) {
2813 seqInf[numberPrimalInfeasibilities_]=iSequence;
2814 }
2815#endif
2816 numberPrimalInfeasibilities_ ++;
2817 } else {
2818 // feasible (so could be free)
2819 if (getStatus(iSequence) != basic && !flagged(iSequence)) {
2820 // not basic
2821 double djValue = dj_[iSequence];
2822 if (distanceDown < primalTolerance) {
2823 if (distanceUp > primalTolerance && djValue < -dualTolerance) {
2824 sumDualInfeasibilities_ -= djValue + dualTolerance;
2825 if (djValue < -possTolerance)
2826 bestPossibleImprovement_ -= distanceUp * djValue;
2827 if (djValue < -relaxedToleranceD)
2828 sumOfRelaxedDualInfeasibilities_ -= djValue + relaxedToleranceD;
2829 numberDualInfeasibilities_ ++;
2830 }
2831 } else if (distanceUp < primalTolerance) {
2832 if (djValue > dualTolerance) {
2833 sumDualInfeasibilities_ += djValue - dualTolerance;
2834 if (djValue > possTolerance)
2835 bestPossibleImprovement_ += distanceDown * djValue;
2836 if (djValue > relaxedToleranceD)
2837 sumOfRelaxedDualInfeasibilities_ += djValue - relaxedToleranceD;
2838 numberDualInfeasibilities_ ++;
2839 }
2840 } else {
2841 // may be free
2842 // Say free or superbasic
2843 moreSpecialOptions_ &= ~8;
2844 djValue *= 0.01;
2845 if (fabs(djValue) > dualTolerance) {
2846 if (getStatus(iSequence) == isFree)
2847 numberDualInfeasibilitiesFree++;
2848 sumDualInfeasibilities_ += fabs(djValue) - dualTolerance;
2849 bestPossibleImprovement_ = 1.0e100;
2850 numberDualInfeasibilities_ ++;
2851 if (fabs(djValue) > relaxedToleranceD) {
2852 sumOfRelaxedDualInfeasibilities_ += value - relaxedToleranceD;
2853 numberSuperBasicWithDj++;
2854 if (firstFreeDual < 0)
2855 firstFreeDual = iSequence;
2856 }
2857 }
2858 if (firstFreePrimal < 0)
2859 firstFreePrimal = iSequence;
2860 }
2861 }
2862 }
2863 }
2864 objectiveValue_ += objective_->nonlinearOffset();
2865 objectiveValue_ /= (objectiveScale_ * rhsScale_);
2866 numberDualInfeasibilitiesWithoutFree_ = numberDualInfeasibilities_ -
2867 numberDualInfeasibilitiesFree;
2868#ifdef PRINT_INFEAS
2869 if (numberPrimalInfeasibilities_<=10) {
2870 printf("---------------start-----------\n");
2871 if (!rowScale_) {
2872 for (int i=0;i<numberPrimalInfeasibilities_;i++) {
2873 int iSeq = seqInf[i];
2874 double infeas;
2875 if (solution_[iSeq]<lower_[iSeq])
2876 infeas = lower_[iSeq]-solution_[iSeq];
2877 else
2878 infeas = solution_[iSeq]-upper_[iSeq];
2879 if (iSeq<numberColumns_) {
2880 printf("INF C%d %.10g <= %.10g <= %.10g - infeas %g\n",
2881 iSeq,lower_[iSeq],solution_[iSeq],upper_[iSeq],infeas);
2882 } else {
2883 printf("INF R%d %.10g <= %.10g <= %.10g - infeas %g\n",
2884 iSeq-numberColumns_,lower_[iSeq],solution_[iSeq],upper_[iSeq],infeas);
2885 }
2886 }
2887 } else {
2888 for (int i=0;i<numberPrimalInfeasibilities_;i++) {
2889 int iSeq = seqInf[i];
2890 double infeas;
2891 if (solution_[iSeq]<lower_[iSeq])
2892 infeas = lower_[iSeq]-solution_[iSeq];
2893 else
2894 infeas = solution_[iSeq]-upper_[iSeq];
2895 double unscaled = infeas;
2896 if (iSeq<numberColumns_) {
2897 unscaled *= columnScale_[iSeq];
2898 printf("INF C%d %.10g <= %.10g <= %.10g - infeas %g - unscaled %g\n",
2899 iSeq,lower_[iSeq],solution_[iSeq],upper_[iSeq],infeas,unscaled);
2900 } else {
2901 unscaled /= rowScale_[iSeq-numberColumns_];
2902 printf("INF R%d %.10g <= %.10g <= %.10g - infeas %g - unscaled %g\n",
2903 iSeq-numberColumns_,lower_[iSeq],solution_[iSeq],upper_[iSeq],infeas,unscaled);
2904 }
2905 }
2906 }
2907 }
2908#endif
2909 if (algorithm_ < 0 && firstFreeDual >= 0) {
2910 // dual
2911 firstFree_ = firstFreeDual;
2912 } else if (numberSuperBasicWithDj ||
2913 (progress_.lastIterationNumber(0) <= 0)) {
2914 firstFree_ = firstFreePrimal;
2915 }
2916}
2917/* Adds multiple of a column into an array */
2918void
2919ClpSimplex::add(double * array,
2920 int sequence, double multiplier) const
2921{
2922 if (sequence >= numberColumns_ && sequence < numberColumns_ + numberRows_) {
2923 //slack
2924 array [sequence-numberColumns_] -= multiplier;
2925 } else {
2926 // column
2927 matrix_->add(this, array, sequence, multiplier);
2928 }
2929}
2930/*
2931 Unpacks one column of the matrix into indexed array
2932*/
2933void
2934ClpSimplex::unpack(CoinIndexedVector * rowArray) const
2935{
2936 rowArray->clear();
2937 if (sequenceIn_ >= numberColumns_ && sequenceIn_ < numberColumns_ + numberRows_) {
2938 //slack
2939 rowArray->insert(sequenceIn_ - numberColumns_, -1.0);
2940 } else {
2941 // column
2942 matrix_->unpack(this, rowArray, sequenceIn_);
2943 }
2944}
2945void
2946ClpSimplex::unpack(CoinIndexedVector * rowArray, int sequence) const
2947{
2948 rowArray->clear();
2949 if (sequence >= numberColumns_ && sequence < numberColumns_ + numberRows_) {
2950 //slack
2951 rowArray->insert(sequence - numberColumns_, -1.0);
2952 } else {
2953 // column
2954 matrix_->unpack(this, rowArray, sequence);
2955 }
2956}
2957/*
2958 Unpacks one column of the matrix into indexed array
2959*/
2960void
2961ClpSimplex::unpackPacked(CoinIndexedVector * rowArray)
2962{
2963 rowArray->clear();
2964 if (sequenceIn_ >= numberColumns_ && sequenceIn_ < numberColumns_ + numberRows_) {
2965 //slack
2966 int * index = rowArray->getIndices();
2967 double * array = rowArray->denseVector();
2968 array[0] = -1.0;
2969 index[0] = sequenceIn_ - numberColumns_;
2970 rowArray->setNumElements(1);
2971 rowArray->setPackedMode(true);
2972 } else {
2973 // column
2974 matrix_->unpackPacked(this, rowArray, sequenceIn_);
2975 }
2976}
2977void
2978ClpSimplex::unpackPacked(CoinIndexedVector * rowArray, int sequence)
2979{
2980 rowArray->clear();
2981 if (sequence >= numberColumns_ && sequence < numberColumns_ + numberRows_) {
2982 //slack
2983 int * index = rowArray->getIndices();
2984 double * array = rowArray->denseVector();
2985 array[0] = -1.0;
2986 index[0] = sequence - numberColumns_;
2987 rowArray->setNumElements(1);
2988 rowArray->setPackedMode(true);
2989 } else {
2990 // column
2991 matrix_->unpackPacked(this, rowArray, sequence);
2992 }
2993}
2994//static int x_gaps[4]={0,0,0,0};
2995//static int scale_times[]={0,0,0,0};
2996bool
2997ClpSimplex::createRim(int what, bool makeRowCopy, int startFinishOptions)
2998{
2999 bool goodMatrix = true;
3000 int saveLevel = handler_->logLevel();
3001 spareIntArray_[0] = 0;
3002 if (!matrix_->canGetRowCopy())
3003 makeRowCopy = false; // switch off row copy if can't produce
3004 // Arrays will be there and correct size unless what is 63
3005 bool newArrays = (what == 63);
3006 // We may be restarting with same size
3007 bool keepPivots = false;
3008 if (startFinishOptions == -1) {
3009 startFinishOptions = 0;
3010 keepPivots = true;
3011 }
3012 bool oldMatrix = ((startFinishOptions & 4) != 0 && (whatsChanged_ & 1) != 0);
3013 if (what == 63) {
3014 pivotRow_ = -1;
3015 if (!status_)
3016 createStatus();
3017 if (oldMatrix)
3018 newArrays = false;
3019 if (problemStatus_ == 10) {
3020 handler_->setLogLevel(0); // switch off messages
3021 if (rowArray_[0]) {
3022 // stuff is still there
3023 oldMatrix = true;
3024 newArrays = false;
3025 keepPivots = true;
3026 for (int iRow = 0; iRow < 4; iRow++) {
3027 rowArray_[iRow]->clear();
3028 }
3029 for (int iColumn = 0; iColumn < 2; iColumn++) {
3030 columnArray_[iColumn]->clear();
3031 }
3032 }
3033 } else if (factorization_) {
3034 // match up factorization messages
3035 if (handler_->logLevel() < 3)
3036 factorization_->messageLevel(0);
3037 else
3038 factorization_->messageLevel(CoinMax(3, factorization_->messageLevel()));
3039 /* Faster to keep pivots rather than re-scan matrix. Matrix may have changed
3040 i.e. oldMatrix false but okay as long as same number rows and status array exists
3041 */
3042 if ((startFinishOptions & 2) != 0 && factorization_->numberRows() == numberRows_ && status_)
3043 keepPivots = true;
3044 }
3045 numberExtraRows_ = matrix_->generalExpanded(this, 2, maximumBasic_);
3046 if (numberExtraRows_ && newArrays) {
3047 // make sure status array large enough
3048 assert (status_);
3049 int numberOld = numberRows_ + numberColumns_;
3050 int numberNew = numberRows_ + numberColumns_ + numberExtraRows_;
3051 unsigned char * newStatus = new unsigned char [numberNew];
3052 memset(newStatus + numberOld, 0, numberExtraRows_);
3053 CoinMemcpyN(status_, numberOld, newStatus);
3054 delete [] status_;
3055 status_ = newStatus;
3056 }
3057 }
3058 int numberRows2 = numberRows_ + numberExtraRows_;
3059 int numberTotal = numberRows2 + numberColumns_;
3060 if ((specialOptions_ & 65536) != 0) {
3061 assert (!numberExtraRows_);
3062 if (!cost_ || numberRows2 > maximumInternalRows_ ||
3063 numberColumns_ > maximumInternalColumns_) {
3064 newArrays = true;
3065 keepPivots = false;
3066 COIN_DETAIL_PRINT(printf("createrim a %d rows, %d maximum rows %d maxinternal\n",
3067 numberRows_, maximumRows_, maximumInternalRows_));
3068 int oldMaximumRows = maximumInternalRows_;
3069 int oldMaximumColumns = maximumInternalColumns_;
3070 if (cost_) {
3071 if (numberRows2 > maximumInternalRows_)
3072 maximumInternalRows_ = numberRows2;
3073 if (numberColumns_ > maximumInternalColumns_)
3074 maximumInternalColumns_ = numberColumns_;
3075 } else {
3076 maximumInternalRows_ = numberRows2;
3077 maximumInternalColumns_ = numberColumns_;
3078 }
3079 assert(maximumInternalRows_ == maximumRows_);
3080 assert(maximumInternalColumns_ == maximumColumns_);
3081 COIN_DETAIL_PRINT(printf("createrim b %d rows, %d maximum rows, %d maxinternal\n",
3082 numberRows_, maximumRows_, maximumInternalRows_));
3083 int numberTotal2 = (maximumInternalRows_ + maximumInternalColumns_) * 2;
3084 delete [] cost_;
3085 cost_ = new double[numberTotal2];
3086 delete [] lower_;
3087 delete [] upper_;
3088 lower_ = new double[numberTotal2];
3089 upper_ = new double[numberTotal2];
3090 delete [] dj_;
3091 dj_ = new double[numberTotal2];
3092 delete [] solution_;
3093 solution_ = new double[numberTotal2];
3094 // ***** should be non NULL but seems to be too much
3095 //printf("resize %d savedRowScale %x\n",maximumRows_,savedRowScale_);
3096 if (savedRowScale_) {
3097 assert (oldMaximumRows > 0);
3098 double * temp;
3099 temp = new double [4*maximumRows_];
3100 CoinFillN(temp, 4 * maximumRows_, 1.0);
3101 CoinMemcpyN(savedRowScale_, numberRows_, temp);
3102 CoinMemcpyN(savedRowScale_ + oldMaximumRows, numberRows_, temp + maximumRows_);
3103 CoinMemcpyN(savedRowScale_ + 2 * oldMaximumRows, numberRows_, temp + 2 * maximumRows_);
3104 CoinMemcpyN(savedRowScale_ + 3 * oldMaximumRows, numberRows_, temp + 3 * maximumRows_);
3105 delete [] savedRowScale_;
3106 savedRowScale_ = temp;
3107 temp = new double [4*maximumColumns_];
3108 CoinFillN(temp, 4 * maximumColumns_, 1.0);
3109 CoinMemcpyN(savedColumnScale_, numberColumns_, temp);
3110 CoinMemcpyN(savedColumnScale_ + oldMaximumColumns, numberColumns_, temp + maximumColumns_);
3111 CoinMemcpyN(savedColumnScale_ + 2 * oldMaximumColumns, numberColumns_, temp + 2 * maximumColumns_);
3112 CoinMemcpyN(savedColumnScale_ + 3 * oldMaximumColumns, numberColumns_, temp + 3 * maximumColumns_);
3113 delete [] savedColumnScale_;
3114 savedColumnScale_ = temp;
3115 }
3116 }
3117 }
3118 int i;
3119 bool doSanityCheck = true;
3120 if (what == 63) {
3121 // We may want to switch stuff off for speed
3122 if ((specialOptions_ & 256) != 0)
3123 makeRowCopy = false; // no row copy
3124 if ((specialOptions_ & 128) != 0)
3125 doSanityCheck = false; // no sanity check
3126 //check matrix
3127 if (!matrix_)
3128 matrix_ = new ClpPackedMatrix();
3129 int checkType = (doSanityCheck) ? 15 : 14;
3130 if (oldMatrix)
3131 checkType = 14;
3132 bool inCbcOrOther = (specialOptions_ & 0x03000000) != 0;
3133 if (inCbcOrOther)
3134 checkType -= 4; // don't check for duplicates
3135 if (!matrix_->allElementsInRange(this, smallElement_, 1.0e20, checkType)) {
3136 problemStatus_ = 4;
3137 secondaryStatus_ = 8;
3138 //goodMatrix= false;
3139 return false;
3140 }
3141 bool rowCopyIsScaled;
3142 if (makeRowCopy) {
3143 if(!oldMatrix || !rowCopy_) {
3144 delete rowCopy_;
3145 // may return NULL if can't give row copy
3146 rowCopy_ = matrix_->reverseOrderedCopy();
3147 rowCopyIsScaled = false;
3148 } else {
3149 rowCopyIsScaled = true;
3150 }
3151 }
3152#if 0
3153 if (what == 63) {
3154 int k = rowScale_ ? 1 : 0;
3155 if (oldMatrix)
3156 k += 2;
3157 scale_times[k]++;
3158 if ((scale_times[0] + scale_times[1] + scale_times[2] + scale_times[3]) % 1000 == 0)
3159 printf("scale counts %d %d %d %d\n",
3160 scale_times[0], scale_times[1], scale_times[2], scale_times[3]);
3161 }
3162#endif
3163 // do scaling if needed
3164 if (!oldMatrix && scalingFlag_ < 0) {
3165 if (scalingFlag_ < 0 && rowScale_) {
3166 //if (handler_->logLevel()>0)
3167 printf("How did we get scalingFlag_ %d and non NULL rowScale_? - switching off scaling\n",
3168 scalingFlag_);
3169 scalingFlag_ = 0;
3170 }
3171 delete [] rowScale_;
3172 delete [] columnScale_;
3173 rowScale_ = NULL;
3174 columnScale_ = NULL;
3175 }
3176 inverseRowScale_ = NULL;
3177 inverseColumnScale_ = NULL;
3178 if (scalingFlag_ > 0 && !rowScale_) {
3179 if ((specialOptions_ & 65536) != 0) {
3180 assert (!rowScale_);
3181 rowScale_ = savedRowScale_;
3182 columnScale_ = savedColumnScale_;
3183 // put back original
3184 if (savedRowScale_) {
3185 inverseRowScale_ = savedRowScale_ + maximumInternalRows_;
3186 inverseColumnScale_ = savedColumnScale_ + maximumInternalColumns_;
3187 CoinMemcpyN(savedRowScale_ + 2 * maximumInternalRows_,
3188 numberRows2, savedRowScale_);
3189 CoinMemcpyN(savedRowScale_ + 3 * maximumInternalRows_,
3190 numberRows2, inverseRowScale_);
3191 CoinMemcpyN(savedColumnScale_ + 2 * maximumColumns_,
3192 numberColumns_, savedColumnScale_);
3193 CoinMemcpyN(savedColumnScale_ + 3 * maximumColumns_,
3194 numberColumns_, inverseColumnScale_);
3195 }
3196 }
3197 if (matrix_->scale(this))
3198 scalingFlag_ = -scalingFlag_; // not scaled after all
3199 if (rowScale_ && automaticScale_) {
3200 // try automatic scaling
3201 double smallestObj = 1.0e100;
3202 double largestObj = 0.0;
3203 double largestRhs = 0.0;
3204 const double * obj = objective();
3205 for (i = 0; i < numberColumns_; i++) {
3206 double value = fabs(obj[i]);
3207 value *= columnScale_[i];
3208 if (value && columnLower_[i] != columnUpper_[i]) {
3209 smallestObj = CoinMin(smallestObj, value);
3210 largestObj = CoinMax(largestObj, value);
3211 }
3212 if (columnLower_[i] > 0.0 || columnUpper_[i] < 0.0) {
3213 double scale = 1.0 * inverseColumnScale_[i];
3214 //printf("%d %g %g %g %g\n",i,scale,lower_[i],upper_[i],largestRhs);
3215 if (columnLower_[i] > 0)
3216 largestRhs = CoinMax(largestRhs, columnLower_[i] * scale);
3217 if (columnUpper_[i] < 0.0)
3218 largestRhs = CoinMax(largestRhs, -columnUpper_[i] * scale);
3219 }
3220 }
3221 for (i = 0; i < numberRows_; i++) {
3222 if (rowLower_[i] > 0.0 || rowUpper_[i] < 0.0) {
3223 double scale = rowScale_[i];
3224 //printf("%d %g %g %g %g\n",i,scale,lower_[i],upper_[i],largestRhs);
3225 if (rowLower_[i] > 0)
3226 largestRhs = CoinMax(largestRhs, rowLower_[i] * scale);
3227 if (rowUpper_[i] < 0.0)
3228 largestRhs = CoinMax(largestRhs, -rowUpper_[i] * scale);
3229 }
3230 }
3231 COIN_DETAIL_PRINT(printf("small obj %g, large %g - rhs %g\n", smallestObj, largestObj, largestRhs));
3232 bool scalingDone = false;
3233 // look at element range
3234 double smallestNegative;
3235 double largestNegative;
3236 double smallestPositive;
3237 double largestPositive;
3238 matrix_->rangeOfElements(smallestNegative, largestNegative,
3239 smallestPositive, largestPositive);
3240 smallestPositive = CoinMin(fabs(smallestNegative), smallestPositive);
3241 largestPositive = CoinMax(fabs(largestNegative), largestPositive);
3242 if (largestObj) {
3243 double ratio = largestObj / smallestObj;
3244 double scale = 1.0;
3245 if (ratio < 1.0e8) {
3246 // reasonable
3247 if (smallestObj < 1.0e-4) {
3248 // may as well scale up
3249 scalingDone = true;
3250 scale = 1.0e-3 / smallestObj;
3251 } else if (largestObj < 1.0e6 || (algorithm_ > 0 && largestObj < 1.0e-4 * infeasibilityCost_)) {
3252 //done=true;
3253 } else {
3254 scalingDone = true;
3255 if (algorithm_ < 0) {
3256 scale = 1.0e6 / largestObj;
3257 } else {
3258 scale = CoinMax(1.0e6, 1.0e-4 * infeasibilityCost_) / largestObj;
3259 }
3260 }
3261 } else if (ratio < 1.0e12) {
3262 // not so good
3263 if (smallestObj < 1.0e-7) {
3264 // may as well scale up
3265 scalingDone = true;
3266 scale = 1.0e-6 / smallestObj;
3267 } else if (largestObj < 1.0e7 || (algorithm_ > 0 && largestObj < 1.0e-3 * infeasibilityCost_)) {
3268 //done=true;
3269 } else {
3270 scalingDone = true;
3271 if (algorithm_ < 0) {
3272 scale = 1.0e7 / largestObj;
3273 } else {
3274 scale = CoinMax(1.0e7, 1.0e-3 * infeasibilityCost_) / largestObj;
3275 }
3276 }
3277 } else {
3278 // Really nasty problem
3279 if (smallestObj < 1.0e-8) {
3280 // may as well scale up
3281 scalingDone = true;
3282 scale = 1.0e-7 / smallestObj;
3283 largestObj *= scale;
3284 }
3285 if (largestObj < 1.0e7 || (algorithm_ > 0 && largestObj < 1.0e-3 * infeasibilityCost_)) {
3286 //done=true;
3287 } else {
3288 scalingDone = true;
3289 if (algorithm_ < 0) {
3290 scale = 1.0e7 / largestObj;
3291 } else {
3292 scale = CoinMax(1.0e7, 1.0e-3 * infeasibilityCost_) / largestObj;
3293 }
3294 }
3295 }
3296 objectiveScale_ = scale;
3297 }
3298 if (largestRhs > 1.0e12) {
3299 scalingDone = true;
3300 rhsScale_ = 1.0e9 / largestRhs;
3301 } else if (largestPositive > 1.0e-14 * smallestPositive && largestRhs > 1.0e6) {
3302 scalingDone = true;
3303 rhsScale_ = 1.0e6 / largestRhs;
3304 } else {
3305 rhsScale_ = 1.0;
3306 }
3307 if (scalingDone) {
3308 handler_->message(CLP_RIM_SCALE, messages_)
3309 << objectiveScale_ << rhsScale_
3310 << CoinMessageEol;
3311 }
3312 }
3313 } else if (makeRowCopy && scalingFlag_ > 0 && !rowCopyIsScaled) {
3314 matrix_->scaleRowCopy(this);
3315 }
3316 if (rowScale_ && !savedRowScale_) {
3317 inverseRowScale_ = rowScale_ + numberRows2;
3318 inverseColumnScale_ = columnScale_ + numberColumns_;
3319 }
3320 // See if we can try for faster row copy
3321 if (makeRowCopy && !oldMatrix) {
3322 ClpPackedMatrix* clpMatrix =
3323 dynamic_cast< ClpPackedMatrix*>(matrix_);
3324 if (clpMatrix && numberThreads_)
3325 clpMatrix->specialRowCopy(this, rowCopy_);
3326 if (clpMatrix)
3327 clpMatrix->specialColumnCopy(this);
3328 }
3329 }
3330 if (what == 63) {
3331#if 0
3332 {
3333 x_gaps[0]++;
3334 ClpPackedMatrix* clpMatrix =
3335 dynamic_cast< ClpPackedMatrix*>(matrix_);
3336 if (clpMatrix) {
3337 if (!clpMatrix->getPackedMatrix()->hasGaps())
3338 x_gaps[1]++;
3339 if ((clpMatrix->flags() & 2) == 0)
3340 x_gaps[3]++;
3341 } else {
3342 x_gaps[2]++;
3343 }
3344 if ((x_gaps[0] % 1000) == 0)
3345 printf("create %d times, no gaps %d times - not clp %d times - flagged %d\n",
3346 x_gaps[0], x_gaps[1], x_gaps[2], x_gaps[3]);
3347 }
3348#endif
3349 if (newArrays && (specialOptions_ & 65536) == 0) {
3350 delete [] cost_;
3351 cost_ = new double[2*numberTotal];
3352 delete [] lower_;
3353 delete [] upper_;
3354 lower_ = new double[numberTotal];
3355 upper_ = new double[numberTotal];
3356 delete [] dj_;
3357 dj_ = new double[numberTotal];
3358 delete [] solution_;
3359 solution_ = new double[numberTotal];
3360 }
3361 reducedCostWork_ = dj_;
3362 rowReducedCost_ = dj_ + numberColumns_;
3363 columnActivityWork_ = solution_;
3364 rowActivityWork_ = solution_ + numberColumns_;
3365 objectiveWork_ = cost_;
3366 rowObjectiveWork_ = cost_ + numberColumns_;
3367 rowLowerWork_ = lower_ + numberColumns_;
3368 columnLowerWork_ = lower_;
3369 rowUpperWork_ = upper_ + numberColumns_;
3370 columnUpperWork_ = upper_;
3371 }
3372 if ((what & 4) != 0) {
3373 double direction = optimizationDirection_ * objectiveScale_;
3374 const double * obj = objective();
3375 const double * rowScale = rowScale_;
3376 const double * columnScale = columnScale_;
3377 // and also scale by scale factors
3378 if (rowScale) {
3379 if (rowObjective_) {
3380 for (i = 0; i < numberRows_; i++)
3381 rowObjectiveWork_[i] = rowObjective_[i] * direction / rowScale[i];
3382 } else {
3383 memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double));
3384 }
3385 // If scaled then do all columns later in one loop
3386 if (what != 63) {
3387 for (i = 0; i < numberColumns_; i++) {
3388 CoinAssert(fabs(obj[i]) < 1.0e25);
3389 objectiveWork_[i] = obj[i] * direction * columnScale[i];
3390 }
3391 }
3392 } else {
3393 if (rowObjective_) {
3394 for (i = 0; i < numberRows_; i++)
3395 rowObjectiveWork_[i] = rowObjective_[i] * direction;
3396 } else {
3397 memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double));
3398 }
3399 for (i = 0; i < numberColumns_; i++) {
3400 CoinAssert(fabs(obj[i]) < 1.0e25);
3401 objectiveWork_[i] = obj[i] * direction;
3402 }
3403 }
3404 }
3405 if ((what & 1) != 0) {
3406 const double * rowScale = rowScale_;
3407 // clean up any mismatches on infinity
3408 // and fix any variables with tiny gaps
3409 double primalTolerance = dblParam_[ClpPrimalTolerance];
3410 if(rowScale) {
3411 // If scaled then do all columns later in one loop
3412 if (what != 63) {
3413 const double * inverseScale = inverseColumnScale_;
3414 for (i = 0; i < numberColumns_; i++) {
3415 double multiplier = rhsScale_ * inverseScale[i];
3416 double lowerValue = columnLower_[i];
3417 double upperValue = columnUpper_[i];
3418 if (lowerValue > -1.0e20) {
3419 columnLowerWork_[i] = lowerValue * multiplier;
3420 if (upperValue >= 1.0e20) {
3421 columnUpperWork_[i] = COIN_DBL_MAX;
3422 } else {
3423 columnUpperWork_[i] = upperValue * multiplier;
3424 if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) {
3425 if (columnLowerWork_[i] >= 0.0) {
3426 columnUpperWork_[i] = columnLowerWork_[i];
3427 } else if (columnUpperWork_[i] <= 0.0) {
3428 columnLowerWork_[i] = columnUpperWork_[i];
3429 } else {
3430 columnUpperWork_[i] = 0.0;
3431 columnLowerWork_[i] = 0.0;
3432 }
3433 }
3434 }
3435 } else if (upperValue < 1.0e20) {
3436 columnLowerWork_[i] = -COIN_DBL_MAX;
3437 columnUpperWork_[i] = upperValue * multiplier;
3438 } else {
3439 // free
3440 columnLowerWork_[i] = -COIN_DBL_MAX;
3441 columnUpperWork_[i] = COIN_DBL_MAX;
3442 }
3443 }
3444 }
3445 for (i = 0; i < numberRows_; i++) {
3446 double multiplier = rhsScale_ * rowScale[i];
3447 double lowerValue = rowLower_[i];
3448 double upperValue = rowUpper_[i];
3449 if (lowerValue > -1.0e20) {
3450 rowLowerWork_[i] = lowerValue * multiplier;
3451 if (upperValue >= 1.0e20) {
3452 rowUpperWork_[i] = COIN_DBL_MAX;
3453 } else {
3454 rowUpperWork_[i] = upperValue * multiplier;
3455 if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) {
3456 if (rowLowerWork_[i] >= 0.0) {
3457 rowUpperWork_[i] = rowLowerWork_[i];
3458 } else if (rowUpperWork_[i] <= 0.0) {
3459 rowLowerWork_[i] = rowUpperWork_[i];
3460 } else {
3461 rowUpperWork_[i] = 0.0;
3462 rowLowerWork_[i] = 0.0;
3463 }
3464 }
3465 }
3466 } else if (upperValue < 1.0e20) {
3467 rowLowerWork_[i] = -COIN_DBL_MAX;
3468 rowUpperWork_[i] = upperValue * multiplier;
3469 } else {
3470 // free
3471 rowLowerWork_[i] = -COIN_DBL_MAX;
3472 rowUpperWork_[i] = COIN_DBL_MAX;
3473 }
3474 }
3475 } else if (rhsScale_ != 1.0) {
3476 for (i = 0; i < numberColumns_; i++) {
3477 double lowerValue = columnLower_[i];
3478 double upperValue = columnUpper_[i];
3479 if (lowerValue > -1.0e20) {
3480 columnLowerWork_[i] = lowerValue * rhsScale_;
3481 if (upperValue >= 1.0e20) {
3482 columnUpperWork_[i] = COIN_DBL_MAX;
3483 } else {
3484 columnUpperWork_[i] = upperValue * rhsScale_;
3485 if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) {
3486 if (columnLowerWork_[i] >= 0.0) {
3487 columnUpperWork_[i] = columnLowerWork_[i];
3488 } else if (columnUpperWork_[i] <= 0.0) {
3489 columnLowerWork_[i] = columnUpperWork_[i];
3490 } else {
3491 columnUpperWork_[i] = 0.0;
3492 columnLowerWork_[i] = 0.0;
3493 }
3494 }
3495 }
3496 } else if (upperValue < 1.0e20) {
3497 columnLowerWork_[i] = -COIN_DBL_MAX;
3498 columnUpperWork_[i] = upperValue * rhsScale_;
3499 } else {
3500 // free
3501 columnLowerWork_[i] = -COIN_DBL_MAX;
3502 columnUpperWork_[i] = COIN_DBL_MAX;
3503 }
3504 }
3505 for (i = 0; i < numberRows_; i++) {
3506 double lowerValue = rowLower_[i];
3507 double upperValue = rowUpper_[i];
3508 if (lowerValue > -1.0e20) {
3509 rowLowerWork_[i] = lowerValue * rhsScale_;
3510 if (upperValue >= 1.0e20) {
3511 rowUpperWork_[i] = COIN_DBL_MAX;
3512 } else {
3513 rowUpperWork_[i] = upperValue * rhsScale_;
3514 if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) {
3515 if (rowLowerWork_[i] >= 0.0) {
3516 rowUpperWork_[i] = rowLowerWork_[i];
3517 } else if (rowUpperWork_[i] <= 0.0) {
3518 rowLowerWork_[i] = rowUpperWork_[i];
3519 } else {
3520 rowUpperWork_[i] = 0.0;
3521 rowLowerWork_[i] = 0.0;
3522 }
3523 }
3524 }
3525 } else if (upperValue < 1.0e20) {
3526 rowLowerWork_[i] = -COIN_DBL_MAX;
3527 rowUpperWork_[i] = upperValue * rhsScale_;
3528 } else {
3529 // free
3530 rowLowerWork_[i] = -COIN_DBL_MAX;
3531 rowUpperWork_[i] = COIN_DBL_MAX;
3532 }
3533 }
3534 } else {
3535 for (i = 0; i < numberColumns_; i++) {
3536 double lowerValue = columnLower_[i];
3537 double upperValue = columnUpper_[i];
3538 if (lowerValue > -1.0e20) {
3539 columnLowerWork_[i] = lowerValue;
3540 if (upperValue >= 1.0e20) {
3541 columnUpperWork_[i] = COIN_DBL_MAX;
3542 } else {
3543 columnUpperWork_[i] = upperValue;
3544 if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) {
3545 if (columnLowerWork_[i] >= 0.0) {
3546 columnUpperWork_[i] = columnLowerWork_[i];
3547 } else if (columnUpperWork_[i] <= 0.0) {
3548 columnLowerWork_[i] = columnUpperWork_[i];
3549 } else {
3550 columnUpperWork_[i] = 0.0;
3551 columnLowerWork_[i] = 0.0;
3552 }
3553 }
3554 }
3555 } else if (upperValue < 1.0e20) {
3556 columnLowerWork_[i] = -COIN_DBL_MAX;
3557 columnUpperWork_[i] = upperValue;
3558 } else {
3559 // free
3560 columnLowerWork_[i] = -COIN_DBL_MAX;
3561 columnUpperWork_[i] = COIN_DBL_MAX;
3562 }
3563 }
3564 for (i = 0; i < numberRows_; i++) {
3565 double lowerValue = rowLower_[i];
3566 double upperValue = rowUpper_[i];
3567 if (lowerValue > -1.0e20) {
3568 rowLowerWork_[i] = lowerValue;
3569 if (upperValue >= 1.0e20) {
3570 rowUpperWork_[i] = COIN_DBL_MAX;
3571 } else {
3572 rowUpperWork_[i] = upperValue;
3573 if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) {
3574 if (rowLowerWork_[i] >= 0.0) {
3575 rowUpperWork_[i] = rowLowerWork_[i];
3576 } else if (rowUpperWork_[i] <= 0.0) {
3577 rowLowerWork_[i] = rowUpperWork_[i];
3578 } else {
3579 rowUpperWork_[i] = 0.0;
3580 rowLowerWork_[i] = 0.0;
3581 }
3582 }
3583 }
3584 } else if (upperValue < 1.0e20) {
3585 rowLowerWork_[i] = -COIN_DBL_MAX;
3586 rowUpperWork_[i] = upperValue;
3587 } else {
3588 // free
3589 rowLowerWork_[i] = -COIN_DBL_MAX;
3590 rowUpperWork_[i] = COIN_DBL_MAX;
3591 }
3592 }
3593 }
3594 }
3595 if (what == 63) {
3596 // move information to work arrays
3597 double direction = optimizationDirection_;
3598 // direction is actually scale out not scale in
3599 if (direction)
3600 direction = 1.0 / direction;
3601 if (direction != 1.0) {
3602 // reverse all dual signs
3603 for (i = 0; i < numberColumns_; i++)
3604 reducedCost_[i] *= direction;
3605 for (i = 0; i < numberRows_; i++)
3606 dual_[i] *= direction;
3607 }
3608 for (i = 0; i < numberRows_ + numberColumns_; i++) {
3609 setFakeBound(i, noFake);
3610 }
3611 if (rowScale_) {
3612 const double * obj = objective();
3613 double direction = optimizationDirection_ * objectiveScale_;
3614 // clean up any mismatches on infinity
3615 // and fix any variables with tiny gaps
3616 double primalTolerance = dblParam_[ClpPrimalTolerance];
3617 // on entry
3618 const double * inverseScale = inverseColumnScale_;
3619 for (i = 0; i < numberColumns_; i++) {
3620 CoinAssert(fabs(obj[i]) < 1.0e25);
3621 double scaleFactor = columnScale_[i];
3622 double multiplier = rhsScale_ * inverseScale[i];
3623 scaleFactor *= direction;
3624 objectiveWork_[i] = obj[i] * scaleFactor;
3625 reducedCostWork_[i] = reducedCost_[i] * scaleFactor;
3626 double lowerValue = columnLower_[i];
3627 double upperValue = columnUpper_[i];
3628 if (lowerValue > -1.0e20) {
3629 columnLowerWork_[i] = lowerValue * multiplier;
3630 if (upperValue >= 1.0e20) {
3631 columnUpperWork_[i] = COIN_DBL_MAX;
3632 } else {
3633 columnUpperWork_[i] = upperValue * multiplier;
3634 if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) {
3635 if (columnLowerWork_[i] >= 0.0) {
3636 columnUpperWork_[i] = columnLowerWork_[i];
3637 } else if (columnUpperWork_[i] <= 0.0) {
3638 columnLowerWork_[i] = columnUpperWork_[i];
3639 } else {
3640 columnUpperWork_[i] = 0.0;
3641 columnLowerWork_[i] = 0.0;
3642 }
3643 }
3644 }
3645 } else if (upperValue < 1.0e20) {
3646 columnLowerWork_[i] = -COIN_DBL_MAX;
3647 columnUpperWork_[i] = upperValue * multiplier;
3648 } else {
3649 // free
3650 columnLowerWork_[i] = -COIN_DBL_MAX;
3651 columnUpperWork_[i] = COIN_DBL_MAX;
3652 }
3653 double value = columnActivity_[i] * multiplier;
3654 if (fabs(value) > 1.0e20) {
3655 //printf("bad value of %g for column %d\n",value,i);
3656 setColumnStatus(i, superBasic);
3657 if (columnUpperWork_[i] < 0.0) {
3658 value = columnUpperWork_[i];
3659 } else if (columnLowerWork_[i] > 0.0) {
3660 value = columnLowerWork_[i];
3661 } else {
3662 value = 0.0;
3663 }
3664 }
3665 columnActivityWork_[i] = value;
3666 }
3667 inverseScale = inverseRowScale_;
3668 for (i = 0; i < numberRows_; i++) {
3669 dual_[i] *= inverseScale[i];
3670 dual_[i] *= objectiveScale_;
3671 rowReducedCost_[i] = dual_[i];
3672 double multiplier = rhsScale_ * rowScale_[i];
3673 double value = rowActivity_[i] * multiplier;
3674 if (fabs(value) > 1.0e20) {
3675 //printf("bad value of %g for row %d\n",value,i);
3676 setRowStatus(i, superBasic);
3677 if (rowUpperWork_[i] < 0.0) {
3678 value = rowUpperWork_[i];
3679 } else if (rowLowerWork_[i] > 0.0) {
3680 value = rowLowerWork_[i];
3681 } else {
3682 value = 0.0;
3683 }
3684 }
3685 rowActivityWork_[i] = value;
3686 }
3687 } else if (objectiveScale_ != 1.0 || rhsScale_ != 1.0) {
3688 // on entry
3689 for (i = 0; i < numberColumns_; i++) {
3690 double value = columnActivity_[i];
3691 value *= rhsScale_;
3692 if (fabs(value) > 1.0e20) {
3693 //printf("bad value of %g for column %d\n",value,i);
3694 setColumnStatus(i, superBasic);
3695 if (columnUpperWork_[i] < 0.0) {
3696 value = columnUpperWork_[i];
3697 } else if (columnLowerWork_[i] > 0.0) {
3698 value = columnLowerWork_[i];
3699 } else {
3700 value = 0.0;
3701 }
3702 }
3703 columnActivityWork_[i] = value;
3704 reducedCostWork_[i] = reducedCost_[i] * objectiveScale_;
3705 }
3706 for (i = 0; i < numberRows_; i++) {
3707 double value = rowActivity_[i];
3708 value *= rhsScale_;
3709 if (fabs(value) > 1.0e20) {
3710 //printf("bad value of %g for row %d\n",value,i);
3711 setRowStatus(i, superBasic);
3712 if (rowUpperWork_[i] < 0.0) {
3713 value = rowUpperWork_[i];
3714 } else if (rowLowerWork_[i] > 0.0) {
3715 value = rowLowerWork_[i];
3716 } else {
3717 value = 0.0;
3718 }
3719 }
3720 rowActivityWork_[i] = value;
3721 dual_[i] *= objectiveScale_;
3722 rowReducedCost_[i] = dual_[i];
3723 }
3724 } else {
3725 // on entry
3726 for (i = 0; i < numberColumns_; i++) {
3727 double value = columnActivity_[i];
3728 if (fabs(value) > 1.0e20) {
3729 //printf("bad value of %g for column %d\n",value,i);
3730 setColumnStatus(i, superBasic);
3731 if (columnUpperWork_[i] < 0.0) {
3732 value = columnUpperWork_[i];
3733 } else if (columnLowerWork_[i] > 0.0) {
3734 value = columnLowerWork_[i];
3735 } else {
3736 value = 0.0;
3737 }
3738 }
3739 columnActivityWork_[i] = value;
3740 reducedCostWork_[i] = reducedCost_[i];
3741 }
3742 for (i = 0; i < numberRows_; i++) {
3743 double value = rowActivity_[i];
3744 if (fabs(value) > 1.0e20) {
3745 //printf("bad value of %g for row %d\n",value,i);
3746 setRowStatus(i, superBasic);
3747 if (rowUpperWork_[i] < 0.0) {
3748 value = rowUpperWork_[i];
3749 } else if (rowLowerWork_[i] > 0.0) {
3750 value = rowLowerWork_[i];
3751 } else {
3752 value = 0.0;
3753 }
3754 }
3755 rowActivityWork_[i] = value;
3756 rowReducedCost_[i] = dual_[i];
3757 }
3758 }
3759 }
3760
3761 if (what == 63 && doSanityCheck) {
3762 // check rim of problem okay
3763 if (!sanityCheck())
3764 goodMatrix = false;
3765 }
3766 // we need to treat matrix as if each element by rowScaleIn and columnScaleout??
3767 // maybe we need to move scales to SimplexModel for factorization?
3768 if ((what == 63 && !pivotVariable_) || (newArrays && !keepPivots)) {
3769 delete [] pivotVariable_;
3770 pivotVariable_ = new int[numberRows2];
3771 for (int i = 0; i < numberRows2; i++)
3772 pivotVariable_[i] = -1;
3773 } else if (what == 63 && !keepPivots) {
3774 // just reset
3775 for (int i = 0; i < numberRows2; i++)
3776 pivotVariable_[i] = -1;
3777 } else if (what == 63) {
3778 // check pivots
3779 for (int i = 0; i < numberRows2; i++) {
3780 int iSequence = pivotVariable_[i];
3781 if (iSequence < numberRows_ + numberColumns_ &&
3782 getStatus(iSequence) != basic) {
3783 keepPivots = false;
3784 break;
3785 }
3786 }
3787 if (!keepPivots) {
3788 // reset
3789 for (int i = 0; i < numberRows2; i++)
3790 pivotVariable_[i] = -1;
3791 } else {
3792 // clean
3793 for (int i = 0; i < numberColumns_ + numberRows_; i++) {
3794 Status status = getStatus(i);
3795 if (status != basic) {
3796 if (upper_[i] == lower_[i]) {
3797 setStatus(i, isFixed);
3798 solution_[i] = lower_[i];
3799 } else if (status == atLowerBound) {
3800 if (lower_[i] > -1.0e20) {
3801 solution_[i] = lower_[i];
3802 } else {
3803 //printf("seq %d at lower of %g\n",i,lower_[i]);
3804 if (upper_[i] < 1.0e20) {
3805 solution_[i] = upper_[i];
3806 setStatus(i, atUpperBound);
3807 } else {
3808 setStatus(i, isFree);
3809 }
3810 }
3811 } else if (status == atUpperBound) {
3812 if (upper_[i] < 1.0e20) {
3813 solution_[i] = upper_[i];
3814 } else {
3815 //printf("seq %d at upper of %g\n",i,upper_[i]);
3816 if (lower_[i] > -1.0e20) {
3817 solution_[i] = lower_[i];
3818 setStatus(i, atLowerBound);
3819 } else {
3820 setStatus(i, isFree);
3821 }
3822 }
3823 } else if (status == isFixed && upper_[i] > lower_[i]) {
3824 // was fixed - not now
3825 if (solution_[i] <= lower_[i]) {
3826 setStatus(i, atLowerBound);
3827 } else if (solution_[i] >= upper_[i]) {
3828 setStatus(i, atUpperBound);
3829 } else {
3830 setStatus(i, superBasic);
3831 }
3832 }
3833 }
3834 }
3835 }
3836 }
3837
3838 if (what == 63) {
3839 if (newArrays) {
3840 // get some arrays
3841 int iRow, iColumn;
3842 // these are "indexed" arrays so we always know where nonzeros are
3843 /**********************************************************
3844 rowArray_[3] is long enough for rows+columns
3845 rowArray_[1] is long enough for max(rows,columns)
3846 *********************************************************/
3847 for (iRow = 0; iRow < 4; iRow++) {
3848 int length = numberRows2 + factorization_->maximumPivots();
3849 if (iRow == 3 || objective_->type() > 1)
3850 length += numberColumns_;
3851 else if (iRow == 1)
3852 length = CoinMax(length, numberColumns_);
3853 if ((specialOptions_ & 65536) == 0 || !rowArray_[iRow]) {
3854 delete rowArray_[iRow];
3855 rowArray_[iRow] = new CoinIndexedVector();
3856 }
3857 rowArray_[iRow]->reserve(length);
3858 }
3859
3860 for (iColumn = 0; iColumn < 2; iColumn++) {
3861 if ((specialOptions_ & 65536) == 0 || !columnArray_[iColumn]) {
3862 delete columnArray_[iColumn];
3863 columnArray_[iColumn] = new CoinIndexedVector();
3864 }
3865 if (!iColumn)
3866 columnArray_[iColumn]->reserve(numberColumns_);
3867 else
3868 columnArray_[iColumn]->reserve(CoinMax(numberRows2, numberColumns_));
3869 }
3870 } else {
3871 int iRow, iColumn;
3872 for (iRow = 0; iRow < 4; iRow++) {
3873 int length = numberRows2 + factorization_->maximumPivots();
3874 if (iRow == 3 || objective_->type() > 1)
3875 length += numberColumns_;
3876 if(rowArray_[iRow]->capacity() >= length) {
3877 rowArray_[iRow]->clear();
3878 } else {
3879 // model size or maxinv changed
3880 rowArray_[iRow]->reserve(length);
3881 }
3882#ifndef NDEBUG
3883 rowArray_[iRow]->checkClear();
3884#endif
3885 }
3886
3887 for (iColumn = 0; iColumn < 2; iColumn++) {
3888 int length = numberColumns_;
3889 if (iColumn)
3890 length = CoinMax(numberRows2, numberColumns_);
3891 if(columnArray_[iColumn]->capacity() >= length) {
3892 columnArray_[iColumn]->clear();
3893 } else {
3894 // model size or maxinv changed
3895 columnArray_[iColumn]->reserve(length);
3896 }
3897#ifndef NDEBUG
3898 columnArray_[iColumn]->checkClear();
3899#endif
3900 }
3901 }
3902 }
3903 if (problemStatus_ == 10) {
3904 problemStatus_ = -1;
3905 handler_->setLogLevel(saveLevel); // switch back messages
3906 }
3907 if ((what & 5) != 0)
3908 matrix_->generalExpanded(this, 9, what); // update costs and bounds if necessary
3909 if (goodMatrix && (specialOptions_ & 65536) != 0) {
3910 int save = maximumColumns_ + maximumRows_;
3911 CoinMemcpyN(cost_, numberTotal, cost_ + save);
3912 CoinMemcpyN(lower_, numberTotal, lower_ + save);
3913 CoinMemcpyN(upper_, numberTotal, upper_ + save);
3914 CoinMemcpyN(dj_, numberTotal, dj_ + save);
3915 CoinMemcpyN(solution_, numberTotal, solution_ + save);
3916 if (rowScale_ && !savedRowScale_) {
3917 double * temp;
3918 temp = new double [4*maximumRows_];
3919 CoinFillN(temp, 4 * maximumRows_, 1.0);
3920 CoinMemcpyN(rowScale_, numberRows2, temp);
3921 CoinMemcpyN(rowScale_ + numberRows2, numberRows2, temp + maximumRows_);
3922 CoinMemcpyN(rowScale_, numberRows2, temp + 2 * maximumRows_);
3923 CoinMemcpyN(rowScale_ + numberRows2, numberRows2, temp + 3 * maximumRows_);
3924 delete [] rowScale_;
3925 savedRowScale_ = temp;
3926 rowScale_ = savedRowScale_;
3927 inverseRowScale_ = savedRowScale_ + maximumInternalRows_;
3928 temp = new double [4*maximumColumns_];
3929 CoinFillN(temp, 4 * maximumColumns_, 1.0);
3930 CoinMemcpyN(columnScale_, numberColumns_, temp);
3931 CoinMemcpyN(columnScale_ + numberColumns_, numberColumns_, temp + maximumColumns_);
3932 CoinMemcpyN(columnScale_, numberColumns_, temp + 2 * maximumColumns_);
3933 CoinMemcpyN(columnScale_ + numberColumns_, numberColumns_, temp + 3 * maximumColumns_);
3934 delete [] columnScale_;
3935 savedColumnScale_ = temp;
3936 columnScale_ = savedColumnScale_;
3937 inverseColumnScale_ = savedColumnScale_ + maximumInternalColumns_;
3938 }
3939 }
3940 return goodMatrix;
3941}
3942// Does rows and columns
3943void
3944ClpSimplex::createRim1(bool initial)
3945{
3946 int i;
3947 int numberRows2 = numberRows_ + numberExtraRows_;
3948 int numberTotal = numberRows2 + numberColumns_;
3949 if ((specialOptions_ & 65536) != 0 && true) {
3950 assert (!initial);
3951 int save = maximumColumns_ + maximumRows_;
3952 CoinMemcpyN(lower_ + save, numberTotal, lower_);
3953 CoinMemcpyN(upper_ + save, numberTotal, upper_);
3954 return;
3955 }
3956 const double * rowScale = rowScale_;
3957 // clean up any mismatches on infinity
3958 // and fix any variables with tiny gaps
3959 double primalTolerance = dblParam_[ClpPrimalTolerance];
3960 if(rowScale) {
3961 // If scaled then do all columns later in one loop
3962 if (!initial) {
3963 const double * inverseScale = inverseColumnScale_;
3964 for (i = 0; i < numberColumns_; i++) {
3965 double multiplier = rhsScale_ * inverseScale[i];
3966 double lowerValue = columnLower_[i];
3967 double upperValue = columnUpper_[i];
3968 if (lowerValue > -1.0e20) {
3969 columnLowerWork_[i] = lowerValue * multiplier;
3970 if (upperValue >= 1.0e20) {
3971 columnUpperWork_[i] = COIN_DBL_MAX;
3972 } else {
3973 columnUpperWork_[i] = upperValue * multiplier;
3974 if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) {
3975 if (columnLowerWork_[i] >= 0.0) {
3976 columnUpperWork_[i] = columnLowerWork_[i];
3977 } else if (columnUpperWork_[i] <= 0.0) {
3978 columnLowerWork_[i] = columnUpperWork_[i];
3979 } else {
3980 columnUpperWork_[i] = 0.0;
3981 columnLowerWork_[i] = 0.0;
3982 }
3983 }
3984 }
3985 } else if (upperValue < 1.0e20) {
3986 columnLowerWork_[i] = -COIN_DBL_MAX;
3987 columnUpperWork_[i] = upperValue * multiplier;
3988 } else {
3989 // free
3990 columnLowerWork_[i] = -COIN_DBL_MAX;
3991 columnUpperWork_[i] = COIN_DBL_MAX;
3992 }
3993 }
3994 }
3995 for (i = 0; i < numberRows_; i++) {
3996 double multiplier = rhsScale_ * rowScale[i];
3997 double lowerValue = rowLower_[i];
3998 double upperValue = rowUpper_[i];
3999 if (lowerValue > -1.0e20) {
4000 rowLowerWork_[i] = lowerValue * multiplier;
4001 if (upperValue >= 1.0e20) {
4002 rowUpperWork_[i] = COIN_DBL_MAX;
4003 } else {
4004 rowUpperWork_[i] = upperValue * multiplier;
4005 if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) {
4006 if (rowLowerWork_[i] >= 0.0) {
4007 rowUpperWork_[i] = rowLowerWork_[i];
4008 } else if (rowUpperWork_[i] <= 0.0) {
4009 rowLowerWork_[i] = rowUpperWork_[i];
4010 } else {
4011 rowUpperWork_[i] = 0.0;
4012 rowLowerWork_[i] = 0.0;
4013 }
4014 }
4015 }
4016 } else if (upperValue < 1.0e20) {
4017 rowLowerWork_[i] = -COIN_DBL_MAX;
4018 rowUpperWork_[i] = upperValue * multiplier;
4019 } else {
4020 // free
4021 rowLowerWork_[i] = -COIN_DBL_MAX;
4022 rowUpperWork_[i] = COIN_DBL_MAX;
4023 }
4024 }
4025 } else if (rhsScale_ != 1.0) {
4026 for (i = 0; i < numberColumns_; i++) {
4027 double lowerValue = columnLower_[i];
4028 double upperValue = columnUpper_[i];
4029 if (lowerValue > -1.0e20) {
4030 columnLowerWork_[i] = lowerValue * rhsScale_;
4031 if (upperValue >= 1.0e20) {
4032 columnUpperWork_[i] = COIN_DBL_MAX;
4033 } else {
4034 columnUpperWork_[i] = upperValue * rhsScale_;
4035 if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) {
4036 if (columnLowerWork_[i] >= 0.0) {
4037 columnUpperWork_[i] = columnLowerWork_[i];
4038 } else if (columnUpperWork_[i] <= 0.0) {
4039 columnLowerWork_[i] = columnUpperWork_[i];
4040 } else {
4041 columnUpperWork_[i] = 0.0;
4042 columnLowerWork_[i] = 0.0;
4043 }
4044 }
4045 }
4046 } else if (upperValue < 1.0e20) {
4047 columnLowerWork_[i] = -COIN_DBL_MAX;
4048 columnUpperWork_[i] = upperValue * rhsScale_;
4049 } else {
4050 // free
4051 columnLowerWork_[i] = -COIN_DBL_MAX;
4052 columnUpperWork_[i] = COIN_DBL_MAX;
4053 }
4054 }
4055 for (i = 0; i < numberRows_; i++) {
4056 double lowerValue = rowLower_[i];
4057 double upperValue = rowUpper_[i];
4058 if (lowerValue > -1.0e20) {
4059 rowLowerWork_[i] = lowerValue * rhsScale_;
4060 if (upperValue >= 1.0e20) {
4061 rowUpperWork_[i] = COIN_DBL_MAX;
4062 } else {
4063 rowUpperWork_[i] = upperValue * rhsScale_;
4064 if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) {
4065 if (rowLowerWork_[i] >= 0.0) {
4066 rowUpperWork_[i] = rowLowerWork_[i];
4067 } else if (rowUpperWork_[i] <= 0.0) {
4068 rowLowerWork_[i] = rowUpperWork_[i];
4069 } else {
4070 rowUpperWork_[i] = 0.0;
4071 rowLowerWork_[i] = 0.0;
4072 }
4073 }
4074 }
4075 } else if (upperValue < 1.0e20) {
4076 rowLowerWork_[i] = -COIN_DBL_MAX;
4077 rowUpperWork_[i] = upperValue * rhsScale_;
4078 } else {
4079 // free
4080 rowLowerWork_[i] = -COIN_DBL_MAX;
4081 rowUpperWork_[i] = COIN_DBL_MAX;
4082 }
4083 }
4084 } else {
4085 for (i = 0; i < numberColumns_; i++) {
4086 double lowerValue = columnLower_[i];
4087 double upperValue = columnUpper_[i];
4088 if (lowerValue > -1.0e20) {
4089 columnLowerWork_[i] = lowerValue;
4090 if (upperValue >= 1.0e20) {
4091 columnUpperWork_[i] = COIN_DBL_MAX;
4092 } else {
4093 columnUpperWork_[i] = upperValue;
4094 if (fabs(columnUpperWork_[i] - columnLowerWork_[i]) <= primalTolerance) {
4095 if (columnLowerWork_[i] >= 0.0) {
4096 columnUpperWork_[i] = columnLowerWork_[i];
4097 } else if (columnUpperWork_[i] <= 0.0) {
4098 columnLowerWork_[i] = columnUpperWork_[i];
4099 } else {
4100 columnUpperWork_[i] = 0.0;
4101 columnLowerWork_[i] = 0.0;
4102 }
4103 }
4104 }
4105 } else if (upperValue < 1.0e20) {
4106 columnLowerWork_[i] = -COIN_DBL_MAX;
4107 columnUpperWork_[i] = upperValue;
4108 } else {
4109 // free
4110 columnLowerWork_[i] = -COIN_DBL_MAX;
4111 columnUpperWork_[i] = COIN_DBL_MAX;
4112 }
4113 }
4114 for (i = 0; i < numberRows_; i++) {
4115 double lowerValue = rowLower_[i];
4116 double upperValue = rowUpper_[i];
4117 if (lowerValue > -1.0e20) {
4118 rowLowerWork_[i] = lowerValue;
4119 if (upperValue >= 1.0e20) {
4120 rowUpperWork_[i] = COIN_DBL_MAX;
4121 } else {
4122 rowUpperWork_[i] = upperValue;
4123 if (fabs(rowUpperWork_[i] - rowLowerWork_[i]) <= primalTolerance) {
4124 if (rowLowerWork_[i] >= 0.0) {
4125 rowUpperWork_[i] = rowLowerWork_[i];
4126 } else if (rowUpperWork_[i] <= 0.0) {
4127 rowLowerWork_[i] = rowUpperWork_[i];
4128 } else {
4129 rowUpperWork_[i] = 0.0;
4130 rowLowerWork_[i] = 0.0;
4131 }
4132 }
4133 }
4134 } else if (upperValue < 1.0e20) {
4135 rowLowerWork_[i] = -COIN_DBL_MAX;
4136 rowUpperWork_[i] = upperValue;
4137 } else {
4138 // free
4139 rowLowerWork_[i] = -COIN_DBL_MAX;
4140 rowUpperWork_[i] = COIN_DBL_MAX;
4141 }
4142 }
4143 }
4144#ifndef NDEBUG
4145 if ((specialOptions_ & 65536) != 0 && false) {
4146 assert (!initial);
4147 int save = maximumColumns_ + maximumRows_;
4148 for (int i = 0; i < numberTotal; i++) {
4149 assert (fabs(lower_[i] - lower_[i+save]) < 1.0e-5);
4150 assert (fabs(upper_[i] - upper_[i+save]) < 1.0e-5);
4151 }
4152 }
4153#endif
4154}
4155// Does objective
4156void
4157ClpSimplex::createRim4(bool initial)
4158{
4159 int i;
4160 int numberRows2 = numberRows_ + numberExtraRows_;
4161 int numberTotal = numberRows2 + numberColumns_;
4162 if ((specialOptions_ & 65536) != 0 && true) {
4163 assert (!initial);
4164 int save = maximumColumns_ + maximumRows_;
4165 CoinMemcpyN(cost_ + save, numberTotal, cost_);
4166 return;
4167 }
4168 double direction = optimizationDirection_ * objectiveScale_;
4169 const double * obj = objective();
4170 const double * rowScale = rowScale_;
4171 const double * columnScale = columnScale_;
4172 // and also scale by scale factors
4173 if (rowScale) {
4174 if (rowObjective_) {
4175 for (i = 0; i < numberRows_; i++)
4176 rowObjectiveWork_[i] = rowObjective_[i] * direction / rowScale[i];
4177 } else {
4178 memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double));
4179 }
4180 // If scaled then do all columns later in one loop
4181 if (!initial) {
4182 for (i = 0; i < numberColumns_; i++) {
4183 CoinAssert(fabs(obj[i]) < 1.0e25);
4184 objectiveWork_[i] = obj[i] * direction * columnScale[i];
4185 }
4186 }
4187 } else {
4188 if (rowObjective_) {
4189 for (i = 0; i < numberRows_; i++)
4190 rowObjectiveWork_[i] = rowObjective_[i] * direction;
4191 } else {
4192 memset(rowObjectiveWork_, 0, numberRows_ * sizeof(double));
4193 }
4194 for (i = 0; i < numberColumns_; i++) {
4195 CoinAssert(fabs(obj[i]) < 1.0e25);
4196 objectiveWork_[i] = obj[i] * direction;
4197 }
4198 }
4199}
4200// Does rows and columns and objective
4201void
4202ClpSimplex::createRim5(bool initial)
4203{
4204 createRim4(initial);
4205 createRim1(initial);
4206}
4207void
4208ClpSimplex::deleteRim(int getRidOfFactorizationData)
4209{
4210 // Just possible empty problem
4211 int numberRows = numberRows_;
4212 int numberColumns = numberColumns_;
4213 if (!numberRows || !numberColumns) {
4214 numberRows = 0;
4215 if (objective_->type() < 2)
4216 numberColumns = 0;
4217 }
4218 int i;
4219 if (problemStatus_ != 1 && problemStatus_ != 2) {
4220 delete [] ray_;
4221 ray_ = NULL;
4222 }
4223 // set upperOut_ to furthest away from bound so can use in dual for dualBound_
4224 upperOut_ = 1.0;
4225#if 0
4226 {
4227 int nBad = 0;
4228 for (i = 0; i < numberColumns; i++) {
4229 if (lower_[i] == upper_[i] && getColumnStatus(i) == basic)
4230 nBad++;
4231 }
4232 if (nBad)
4233 printf("yy %d basic fixed\n", nBad);
4234 }
4235#endif
4236 // ray may be null if in branch and bound
4237 if (rowScale_) {
4238 // Collect infeasibilities
4239 int numberPrimalScaled = 0;
4240 int numberPrimalUnscaled = 0;
4241 int numberDualScaled = 0;
4242 int numberDualUnscaled = 0;
4243 double scaleC = 1.0 / objectiveScale_;
4244 double scaleR = 1.0 / rhsScale_;
4245 const double * inverseScale = inverseColumnScale_;
4246 for (i = 0; i < numberColumns; i++) {
4247 double scaleFactor = columnScale_[i];
4248 double valueScaled = columnActivityWork_[i];
4249 double lowerScaled = columnLowerWork_[i];
4250 double upperScaled = columnUpperWork_[i];
4251 if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) {
4252 if (valueScaled < lowerScaled - primalTolerance_ ||
4253 valueScaled > upperScaled + primalTolerance_)
4254 numberPrimalScaled++;
4255 else
4256 upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled));
4257 }
4258 columnActivity_[i] = valueScaled * scaleFactor * scaleR;
4259 double value = columnActivity_[i];
4260 if (value < columnLower_[i] - primalTolerance_)
4261 numberPrimalUnscaled++;
4262 else if (value > columnUpper_[i] + primalTolerance_)
4263 numberPrimalUnscaled++;
4264 double valueScaledDual = reducedCostWork_[i];
4265 if (valueScaled > columnLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_)
4266 numberDualScaled++;
4267 if (valueScaled < columnUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_)
4268 numberDualScaled++;
4269 reducedCost_[i] = (valueScaledDual * scaleC) * inverseScale[i];
4270 double valueDual = reducedCost_[i];
4271 if (value > columnLower_[i] + primalTolerance_ && valueDual > dualTolerance_)
4272 numberDualUnscaled++;
4273 if (value < columnUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_)
4274 numberDualUnscaled++;
4275 }
4276 inverseScale = inverseRowScale_;
4277 for (i = 0; i < numberRows; i++) {
4278 double scaleFactor = rowScale_[i];
4279 double valueScaled = rowActivityWork_[i];
4280 double lowerScaled = rowLowerWork_[i];
4281 double upperScaled = rowUpperWork_[i];
4282 if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) {
4283 if (valueScaled < lowerScaled - primalTolerance_ ||
4284 valueScaled > upperScaled + primalTolerance_)
4285 numberPrimalScaled++;
4286 else
4287 upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled));
4288 }
4289 rowActivity_[i] = (valueScaled * scaleR) * inverseScale[i];
4290 double value = rowActivity_[i];
4291 if (value < rowLower_[i] - primalTolerance_)
4292 numberPrimalUnscaled++;
4293 else if (value > rowUpper_[i] + primalTolerance_)
4294 numberPrimalUnscaled++;
4295 double valueScaledDual = dual_[i] + rowObjectiveWork_[i];
4296 if (valueScaled > rowLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_)
4297 numberDualScaled++;
4298 if (valueScaled < rowUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_)
4299 numberDualScaled++;
4300 dual_[i] *= scaleFactor * scaleC;
4301 double valueDual = dual_[i];
4302 if (rowObjective_)
4303 valueDual += rowObjective_[i];
4304 if (value > rowLower_[i] + primalTolerance_ && valueDual > dualTolerance_)
4305 numberDualUnscaled++;
4306 if (value < rowUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_)
4307 numberDualUnscaled++;
4308 }
4309 if (!problemStatus_ && !secondaryStatus_) {
4310 // See if we need to set secondary status
4311 if (numberPrimalUnscaled) {
4312 if (numberDualUnscaled)
4313 secondaryStatus_ = 4;
4314 else
4315 secondaryStatus_ = 2;
4316 } else {
4317 if (numberDualUnscaled)
4318 secondaryStatus_ = 3;
4319 }
4320 }
4321 if (problemStatus_ == 2) {
4322 for (i = 0; i < numberColumns; i++) {
4323 ray_[i] *= columnScale_[i];
4324 }
4325 } else if (problemStatus_ == 1 && ray_) {
4326 for (i = 0; i < numberRows; i++) {
4327 ray_[i] *= rowScale_[i];
4328 }
4329 }
4330 } else if (rhsScale_ != 1.0 || objectiveScale_ != 1.0) {
4331 // Collect infeasibilities
4332 int numberPrimalScaled = 0;
4333 int numberPrimalUnscaled = 0;
4334 int numberDualScaled = 0;
4335 int numberDualUnscaled = 0;
4336 double scaleC = 1.0 / objectiveScale_;
4337 double scaleR = 1.0 / rhsScale_;
4338 for (i = 0; i < numberColumns; i++) {
4339 double valueScaled = columnActivityWork_[i];
4340 double lowerScaled = columnLowerWork_[i];
4341 double upperScaled = columnUpperWork_[i];
4342 if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) {
4343 if (valueScaled < lowerScaled - primalTolerance_ ||
4344 valueScaled > upperScaled + primalTolerance_)
4345 numberPrimalScaled++;
4346 else
4347 upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled));
4348 }
4349 columnActivity_[i] = valueScaled * scaleR;
4350 double value = columnActivity_[i];
4351 if (value < columnLower_[i] - primalTolerance_)
4352 numberPrimalUnscaled++;
4353 else if (value > columnUpper_[i] + primalTolerance_)
4354 numberPrimalUnscaled++;
4355 double valueScaledDual = reducedCostWork_[i];
4356 if (valueScaled > columnLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_)
4357 numberDualScaled++;
4358 if (valueScaled < columnUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_)
4359 numberDualScaled++;
4360 reducedCost_[i] = valueScaledDual * scaleC;
4361 double valueDual = reducedCost_[i];
4362 if (value > columnLower_[i] + primalTolerance_ && valueDual > dualTolerance_)
4363 numberDualUnscaled++;
4364 if (value < columnUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_)
4365 numberDualUnscaled++;
4366 }
4367 for (i = 0; i < numberRows; i++) {
4368 double valueScaled = rowActivityWork_[i];
4369 double lowerScaled = rowLowerWork_[i];
4370 double upperScaled = rowUpperWork_[i];
4371 if (lowerScaled > -1.0e20 || upperScaled < 1.0e20) {
4372 if (valueScaled < lowerScaled - primalTolerance_ ||
4373 valueScaled > upperScaled + primalTolerance_)
4374 numberPrimalScaled++;
4375 else
4376 upperOut_ = CoinMax(upperOut_, CoinMin(valueScaled - lowerScaled, upperScaled - valueScaled));
4377 }
4378 rowActivity_[i] = valueScaled * scaleR;
4379 double value = rowActivity_[i];
4380 if (value < rowLower_[i] - primalTolerance_)
4381 numberPrimalUnscaled++;
4382 else if (value > rowUpper_[i] + primalTolerance_)
4383 numberPrimalUnscaled++;
4384 double valueScaledDual = dual_[i] + rowObjectiveWork_[i];
4385 if (valueScaled > rowLowerWork_[i] + primalTolerance_ && valueScaledDual > dualTolerance_)
4386 numberDualScaled++;
4387 if (valueScaled < rowUpperWork_[i] - primalTolerance_ && valueScaledDual < -dualTolerance_)
4388 numberDualScaled++;
4389 dual_[i] *= scaleC;
4390 double valueDual = dual_[i];
4391 if (rowObjective_)
4392 valueDual += rowObjective_[i];
4393 if (value > rowLower_[i] + primalTolerance_ && valueDual > dualTolerance_)
4394 numberDualUnscaled++;
4395 if (value < rowUpper_[i] - primalTolerance_ && valueDual < -dualTolerance_)
4396 numberDualUnscaled++;
4397 }
4398 if (!problemStatus_ && !secondaryStatus_) {
4399 // See if we need to set secondary status
4400 if (numberPrimalUnscaled) {
4401 if (numberDualUnscaled)
4402 secondaryStatus_ = 4;
4403 else
4404 secondaryStatus_ = 2;
4405 } else {
4406 if (numberDualUnscaled)
4407 secondaryStatus_ = 3;
4408 }
4409 }
4410 } else {
4411 if (columnActivityWork_) {
4412 for (i = 0; i < numberColumns; i++) {
4413 double value = columnActivityWork_[i];
4414 double lower = columnLowerWork_[i];
4415 double upper = columnUpperWork_[i];
4416 if (lower > -1.0e20 || upper < 1.0e20) {
4417 if (value > lower && value < upper)
4418 upperOut_ = CoinMax(upperOut_, CoinMin(value - lower, upper - value));
4419 }
4420 columnActivity_[i] = columnActivityWork_[i];
4421 reducedCost_[i] = reducedCostWork_[i];
4422 }
4423 for (i = 0; i < numberRows; i++) {
4424 double value = rowActivityWork_[i];
4425 double lower = rowLowerWork_[i];
4426 double upper = rowUpperWork_[i];
4427 if (lower > -1.0e20 || upper < 1.0e20) {
4428 if (value > lower && value < upper)
4429 upperOut_ = CoinMax(upperOut_, CoinMin(value - lower, upper - value));
4430 }
4431 rowActivity_[i] = rowActivityWork_[i];
4432 }
4433 }
4434 }
4435 // switch off scalefactor if auto
4436 if (automaticScale_) {
4437 rhsScale_ = 1.0;
4438 objectiveScale_ = 1.0;
4439 }
4440 if (optimizationDirection_ != 1.0) {
4441 // and modify all dual signs
4442 for (i = 0; i < numberColumns; i++)
4443 reducedCost_[i] *= optimizationDirection_;
4444 for (i = 0; i < numberRows; i++)
4445 dual_[i] *= optimizationDirection_;
4446 }
4447 // scaling may have been turned off
4448 scalingFlag_ = abs(scalingFlag_);
4449 if(getRidOfFactorizationData > 0) {
4450 gutsOfDelete(getRidOfFactorizationData + 1);
4451 } else {
4452 // at least get rid of nonLinearCost_
4453 delete nonLinearCost_;
4454 nonLinearCost_ = NULL;
4455 }
4456 if (!rowObjective_ && problemStatus_ == 0 && objective_->type() == 1 &&
4457 numberRows && numberColumns) {
4458 // Redo objective value
4459 double objectiveValue = 0.0;
4460 const double * cost = objective();
4461 for (int i = 0; i < numberColumns; i++) {
4462 double value = columnActivity_[i];
4463 objectiveValue += value * cost[i];
4464 }
4465 //if (fabs(objectiveValue_ -objectiveValue*optimizationDirection())>1.0e-5)
4466 //printf("old obj %g new %g\n",objectiveValue_, objectiveValue*optimizationDirection());
4467 objectiveValue_ = objectiveValue * optimizationDirection();
4468 }
4469 // get rid of data
4470 matrix_->generalExpanded(this, 13, scalingFlag_);
4471}
4472void
4473ClpSimplex::setDualBound(double value)
4474{
4475 if (value > 0.0)
4476 dualBound_ = value;
4477}
4478void
4479ClpSimplex::setInfeasibilityCost(double value)
4480{
4481 if (value > 0.0)
4482 infeasibilityCost_ = value;
4483}
4484void ClpSimplex::setNumberRefinements( int value)
4485{
4486 if (value >= 0 && value < 10)
4487 numberRefinements_ = value;
4488}
4489// Sets row pivot choice algorithm in dual
4490void
4491ClpSimplex::setDualRowPivotAlgorithm(ClpDualRowPivot & choice)
4492{
4493 delete dualRowPivot_;
4494 dualRowPivot_ = choice.clone(true);
4495 dualRowPivot_->setModel(this);
4496}
4497// Sets row pivot choice algorithm in dual
4498void
4499ClpSimplex::setPrimalColumnPivotAlgorithm(ClpPrimalColumnPivot & choice)
4500{
4501 delete primalColumnPivot_;
4502 primalColumnPivot_ = choice.clone(true);
4503 primalColumnPivot_->setModel(this);
4504}
4505void
4506ClpSimplex::setFactorization( ClpFactorization & factorization)
4507{
4508 if (factorization_)
4509 factorization_->setFactorization(factorization);
4510 else
4511 factorization_ = new ClpFactorization(factorization,
4512 numberRows_);
4513}
4514
4515// Swaps factorization
4516ClpFactorization *
4517ClpSimplex::swapFactorization( ClpFactorization * factorization)
4518{
4519 ClpFactorization * swap = factorization_;
4520 factorization_ = factorization;
4521 return swap;
4522}
4523// Copies in factorization to existing one
4524void
4525ClpSimplex::copyFactorization( ClpFactorization & factorization)
4526{
4527 *factorization_ = factorization;
4528}
4529/* Perturbation:
4530 -50 to +50 - perturb by this power of ten (-6 sounds good)
4531 100 - auto perturb if takes too long (1.0e-6 largest nonzero)
4532 101 - we are perturbed
4533 102 - don't try perturbing again
4534 default is 100
4535*/
4536void
4537ClpSimplex::setPerturbation(int value)
4538{
4539 if(value <= 100 && value >= -1000) {
4540 perturbation_ = value;
4541 }
4542}
4543// Sparsity on or off
4544bool
4545ClpSimplex::sparseFactorization() const
4546{
4547 return factorization_->sparseThreshold() != 0;
4548}
4549void
4550ClpSimplex::setSparseFactorization(bool value)
4551{
4552 if (value) {
4553 if (!factorization_->sparseThreshold())
4554 factorization_->goSparse();
4555 } else {
4556 factorization_->sparseThreshold(0);
4557 }
4558}
4559void checkCorrect(ClpSimplex * /*model*/, int iRow,
4560 const double * element, const int * rowStart, const int * rowLength,
4561 const int * column,
4562 const double * columnLower_, const double * columnUpper_,
4563 int /*infiniteUpperC*/,
4564 int /*infiniteLowerC*/,
4565 double &maximumUpC,
4566 double &maximumDownC)
4567{
4568 int infiniteUpper = 0;
4569 int infiniteLower = 0;
4570 double maximumUp = 0.0;
4571 double maximumDown = 0.0;
4572 CoinBigIndex rStart = rowStart[iRow];
4573 CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow];
4574 CoinBigIndex j;
4575 double large = 1.0e15;
4576 int iColumn;
4577 // Compute possible lower and upper ranges
4578
4579 for (j = rStart; j < rEnd; ++j) {
4580 double value = element[j];
4581 iColumn = column[j];
4582 if (value > 0.0) {
4583 if (columnUpper_[iColumn] >= large) {
4584 ++infiniteUpper;
4585 } else {
4586 maximumUp += columnUpper_[iColumn] * value;
4587 }
4588 if (columnLower_[iColumn] <= -large) {
4589 ++infiniteLower;
4590 } else {
4591 maximumDown += columnLower_[iColumn] * value;
4592 }
4593 } else if (value < 0.0) {
4594 if (columnUpper_[iColumn] >= large) {
4595 ++infiniteLower;
4596 } else {
4597 maximumDown += columnUpper_[iColumn] * value;
4598 }
4599 if (columnLower_[iColumn] <= -large) {
4600 ++infiniteUpper;
4601 } else {
4602 maximumUp += columnLower_[iColumn] * value;
4603 }
4604 }
4605 }
4606 //assert (infiniteLowerC==infiniteLower);
4607 //assert (infiniteUpperC==infiniteUpper);
4608 if (fabs(maximumUp - maximumUpC) > 1.0e-12 * CoinMax(fabs(maximumUp), fabs(maximumUpC)))
4609 COIN_DETAIL_PRINT(printf("row %d comp up %g, true up %g\n", iRow,
4610 maximumUpC, maximumUp));
4611 if (fabs(maximumDown - maximumDownC) > 1.0e-12 * CoinMax(fabs(maximumDown), fabs(maximumDownC)))
4612 COIN_DETAIL_PRINT(printf("row %d comp down %g, true down %g\n", iRow,
4613 maximumDownC, maximumDown));
4614 maximumUpC = maximumUp;
4615 maximumDownC = maximumDown;
4616}
4617
4618/* Tightens primal bounds to make dual faster. Unless
4619 fixed, bounds are slightly looser than they could be.
4620 This is to make dual go faster and is probably not needed
4621 with a presolve. Returns non-zero if problem infeasible
4622
4623 Fudge for branch and bound - put bounds on columns of factor *
4624 largest value (at continuous) - should improve stability
4625 in branch and bound on infeasible branches (0.0 is off)
4626*/
4627int
4628ClpSimplex::tightenPrimalBounds(double factor, int doTight, bool tightIntegers)
4629{
4630
4631 // Get a row copy in standard format
4632 CoinPackedMatrix copy;
4633 copy.setExtraGap(0.0);
4634 copy.setExtraMajor(0.0);
4635 copy.reverseOrderedCopyOf(*matrix());
4636 // Matrix may have been created so get rid of it
4637 matrix_->releasePackedMatrix();
4638 // get matrix data pointers
4639 const int * column = copy.getIndices();
4640 const CoinBigIndex * rowStart = copy.getVectorStarts();
4641 const int * rowLength = copy.getVectorLengths();
4642 const double * element = copy.getElements();
4643 int numberChanged = 1, iPass = 0;
4644 double large = largeValue(); // treat bounds > this as infinite
4645#ifndef NDEBUG
4646 double large2 = 1.0e10 * large;
4647#endif
4648 int numberInfeasible = 0;
4649 int totalTightened = 0;
4650
4651 double tolerance = primalTolerance();
4652
4653
4654 // Save column bounds
4655 double * saveLower = new double [numberColumns_];
4656 CoinMemcpyN(columnLower_, numberColumns_, saveLower);
4657 double * saveUpper = new double [numberColumns_];
4658 CoinMemcpyN(columnUpper_, numberColumns_, saveUpper);
4659
4660 int iRow, iColumn;
4661 // If wanted compute a reasonable dualBound_
4662 if (factor == COIN_DBL_MAX) {
4663 factor = 0.0;
4664 if (dualBound_ == 1.0e10) {
4665 // get largest scaled away from bound
4666 double largest = 1.0e-12;
4667 double largestScaled = 1.0e-12;
4668 int iRow;
4669 for (iRow = 0; iRow < numberRows_; iRow++) {
4670 double value = rowActivity_[iRow];
4671 double above = value - rowLower_[iRow];
4672 double below = rowUpper_[iRow] - value;
4673 if (above < 1.0e12) {
4674 largest = CoinMax(largest, above);
4675 }
4676 if (below < 1.0e12) {
4677 largest = CoinMax(largest, below);
4678 }
4679 if (rowScale_) {
4680 double multiplier = rowScale_[iRow];
4681 above *= multiplier;
4682 below *= multiplier;
4683 }
4684 if (above < 1.0e12) {
4685 largestScaled = CoinMax(largestScaled, above);
4686 }
4687 if (below < 1.0e12) {
4688 largestScaled = CoinMax(largestScaled, below);
4689 }
4690 }
4691
4692 int iColumn;
4693 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4694 double value = columnActivity_[iColumn];
4695 double above = value - columnLower_[iColumn];
4696 double below = columnUpper_[iColumn] - value;
4697 if (above < 1.0e12) {
4698 largest = CoinMax(largest, above);
4699 }
4700 if (below < 1.0e12) {
4701 largest = CoinMax(largest, below);
4702 }
4703 if (columnScale_) {
4704 double multiplier = 1.0 / columnScale_[iColumn];
4705 above *= multiplier;
4706 below *= multiplier;
4707 }
4708 if (above < 1.0e12) {
4709 largestScaled = CoinMax(largestScaled, above);
4710 }
4711 if (below < 1.0e12) {
4712 largestScaled = CoinMax(largestScaled, below);
4713 }
4714 }
4715 std::cout << "Largest (scaled) away from bound " << largestScaled
4716 << " unscaled " << largest << std::endl;
4717 dualBound_ = CoinMax(1.0001e7, CoinMin(100.0 * largest, 1.00001e10));
4718 }
4719 }
4720
4721 // If wanted - tighten column bounds using solution
4722 if (factor) {
4723 double largest = 0.0;
4724 if (factor > 0.0) {
4725 assert (factor > 1.0);
4726 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4727 if (columnUpper_[iColumn] - columnLower_[iColumn] > tolerance) {
4728 largest = CoinMax(largest, fabs(columnActivity_[iColumn]));
4729 }
4730 }
4731 largest *= factor;
4732 } else {
4733 // absolute
4734 largest = - factor;
4735 }
4736 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4737 if (columnUpper_[iColumn] - columnLower_[iColumn] > tolerance) {
4738 columnUpper_[iColumn] = CoinMin(columnUpper_[iColumn], largest);
4739 columnLower_[iColumn] = CoinMax(columnLower_[iColumn], -largest);
4740 }
4741 }
4742 }
4743#define MAXPASS 10
4744
4745 // Loop round seeing if we can tighten bounds
4746 // Would be faster to have a stack of possible rows
4747 // and we put altered rows back on stack
4748 int numberCheck = -1;
4749 while(numberChanged > numberCheck) {
4750
4751 numberChanged = 0; // Bounds tightened this pass
4752
4753 if (iPass == MAXPASS) break;
4754 iPass++;
4755
4756 for (iRow = 0; iRow < numberRows_; iRow++) {
4757
4758 if (rowLower_[iRow] > -large || rowUpper_[iRow] < large) {
4759
4760 // possible row
4761 int infiniteUpper = 0;
4762 int infiniteLower = 0;
4763 double maximumUp = 0.0;
4764 double maximumDown = 0.0;
4765 double newBound;
4766 CoinBigIndex rStart = rowStart[iRow];
4767 CoinBigIndex rEnd = rowStart[iRow] + rowLength[iRow];
4768 CoinBigIndex j;
4769 // Compute possible lower and upper ranges
4770
4771 for (j = rStart; j < rEnd; ++j) {
4772 double value = element[j];
4773 iColumn = column[j];
4774 if (value > 0.0) {
4775 if (columnUpper_[iColumn] >= large) {
4776 ++infiniteUpper;
4777 } else {
4778 maximumUp += columnUpper_[iColumn] * value;
4779 }
4780 if (columnLower_[iColumn] <= -large) {
4781 ++infiniteLower;
4782 } else {
4783 maximumDown += columnLower_[iColumn] * value;
4784 }
4785 } else if (value < 0.0) {
4786 if (columnUpper_[iColumn] >= large) {
4787 ++infiniteLower;
4788 } else {
4789 maximumDown += columnUpper_[iColumn] * value;
4790 }
4791 if (columnLower_[iColumn] <= -large) {
4792 ++infiniteUpper;
4793 } else {
4794 maximumUp += columnLower_[iColumn] * value;
4795 }
4796 }
4797 }
4798 // Build in a margin of error
4799 maximumUp += 1.0e-8 * fabs(maximumUp);
4800 maximumDown -= 1.0e-8 * fabs(maximumDown);
4801 double maxUp = maximumUp + infiniteUpper * 1.0e31;
4802 double maxDown = maximumDown - infiniteLower * 1.0e31;
4803 if (maxUp <= rowUpper_[iRow] + tolerance &&
4804 maxDown >= rowLower_[iRow] - tolerance) {
4805
4806 // Row is redundant - make totally free
4807 // NO - can't do this for postsolve
4808 // rowLower_[iRow]=-COIN_DBL_MAX;
4809 // rowUpper_[iRow]=COIN_DBL_MAX;
4810 //printf("Redundant row in presolveX %d\n",iRow);
4811
4812 } else {
4813 if (maxUp < rowLower_[iRow] - 100.0 * tolerance ||
4814 maxDown > rowUpper_[iRow] + 100.0 * tolerance) {
4815 // problem is infeasible - exit at once
4816 numberInfeasible++;
4817 break;
4818 }
4819 double lower = rowLower_[iRow];
4820 double upper = rowUpper_[iRow];
4821 for (j = rStart; j < rEnd; ++j) {
4822 double value = element[j];
4823 iColumn = column[j];
4824 double nowLower = columnLower_[iColumn];
4825 double nowUpper = columnUpper_[iColumn];
4826 if (value > 0.0) {
4827 // positive value
4828 if (lower > -large) {
4829 if (!infiniteUpper) {
4830 assert(nowUpper < large2);
4831 newBound = nowUpper +
4832 (lower - maximumUp) / value;
4833 // relax if original was large
4834 if (fabs(maximumUp) > 1.0e8)
4835 newBound -= 1.0e-12 * fabs(maximumUp);
4836 } else if (infiniteUpper == 1 && nowUpper > large) {
4837 newBound = (lower - maximumUp) / value;
4838 // relax if original was large
4839 if (fabs(maximumUp) > 1.0e8)
4840 newBound -= 1.0e-12 * fabs(maximumUp);
4841 } else {
4842 newBound = -COIN_DBL_MAX;
4843 }
4844 if (newBound > nowLower + 1.0e-12 && newBound > -large) {
4845 // Tighten the lower bound
4846 numberChanged++;
4847 // check infeasible (relaxed)
4848 if (nowUpper < newBound) {
4849 if (nowUpper - newBound <
4850 -100.0 * tolerance)
4851 numberInfeasible++;
4852 else
4853 newBound = nowUpper;
4854 }
4855 columnLower_[iColumn] = newBound;
4856 // adjust
4857 double now;
4858 if (nowLower < -large) {
4859 now = 0.0;
4860 infiniteLower--;
4861 } else {
4862 now = nowLower;
4863 }
4864 maximumDown += (newBound - now) * value;
4865 nowLower = newBound;
4866#ifdef DEBUG
4867 checkCorrect(this, iRow,
4868 element, rowStart, rowLength,
4869 column,
4870 columnLower_, columnUpper_,
4871 infiniteUpper,
4872 infiniteLower,
4873 maximumUp,
4874 maximumDown);
4875#endif
4876 }
4877 }
4878 if (upper < large) {
4879 if (!infiniteLower) {
4880 assert(nowLower > - large2);
4881 newBound = nowLower +
4882 (upper - maximumDown) / value;
4883 // relax if original was large
4884 if (fabs(maximumDown) > 1.0e8)
4885 newBound += 1.0e-12 * fabs(maximumDown);
4886 } else if (infiniteLower == 1 && nowLower < -large) {
4887 newBound = (upper - maximumDown) / value;
4888 // relax if original was large
4889 if (fabs(maximumDown) > 1.0e8)
4890 newBound += 1.0e-12 * fabs(maximumDown);
4891 } else {
4892 newBound = COIN_DBL_MAX;
4893 }
4894 if (newBound < nowUpper - 1.0e-12 && newBound < large) {
4895 // Tighten the upper bound
4896 numberChanged++;
4897 // check infeasible (relaxed)
4898 if (nowLower > newBound) {
4899 if (newBound - nowLower <
4900 -100.0 * tolerance)
4901 numberInfeasible++;
4902 else
4903 newBound = nowLower;
4904 }
4905 columnUpper_[iColumn] = newBound;
4906 // adjust
4907 double now;
4908 if (nowUpper > large) {
4909 now = 0.0;
4910 infiniteUpper--;
4911 } else {
4912 now = nowUpper;
4913 }
4914 maximumUp += (newBound - now) * value;
4915 nowUpper = newBound;
4916#ifdef DEBUG
4917 checkCorrect(this, iRow,
4918 element, rowStart, rowLength,
4919 column,
4920 columnLower_, columnUpper_,
4921 infiniteUpper,
4922 infiniteLower,
4923 maximumUp,
4924 maximumDown);
4925#endif
4926 }
4927 }
4928 } else {
4929 // negative value
4930 if (lower > -large) {
4931 if (!infiniteUpper) {
4932 assert(nowLower < large2);
4933 newBound = nowLower +
4934 (lower - maximumUp) / value;
4935 // relax if original was large
4936 if (fabs(maximumUp) > 1.0e8)
4937 newBound += 1.0e-12 * fabs(maximumUp);
4938 } else if (infiniteUpper == 1 && nowLower < -large) {
4939 newBound = (lower - maximumUp) / value;
4940 // relax if original was large
4941 if (fabs(maximumUp) > 1.0e8)
4942 newBound += 1.0e-12 * fabs(maximumUp);
4943 } else {
4944 newBound = COIN_DBL_MAX;
4945 }
4946 if (newBound < nowUpper - 1.0e-12 && newBound < large) {
4947 // Tighten the upper bound
4948 numberChanged++;
4949 // check infeasible (relaxed)
4950 if (nowLower > newBound) {
4951 if (newBound - nowLower <
4952 -100.0 * tolerance)
4953 numberInfeasible++;
4954 else
4955 newBound = nowLower;
4956 }
4957 columnUpper_[iColumn] = newBound;
4958 // adjust
4959 double now;
4960 if (nowUpper > large) {
4961 now = 0.0;
4962 infiniteLower--;
4963 } else {
4964 now = nowUpper;
4965 }
4966 maximumDown += (newBound - now) * value;
4967 nowUpper = newBound;
4968#ifdef DEBUG
4969 checkCorrect(this, iRow,
4970 element, rowStart, rowLength,
4971 column,
4972 columnLower_, columnUpper_,
4973 infiniteUpper,
4974 infiniteLower,
4975 maximumUp,
4976 maximumDown);
4977#endif
4978 }
4979 }
4980 if (upper < large) {
4981 if (!infiniteLower) {
4982 assert(nowUpper < large2);
4983 newBound = nowUpper +
4984 (upper - maximumDown) / value;
4985 // relax if original was large
4986 if (fabs(maximumDown) > 1.0e8)
4987 newBound -= 1.0e-12 * fabs(maximumDown);
4988 } else if (infiniteLower == 1 && nowUpper > large) {
4989 newBound = (upper - maximumDown) / value;
4990 // relax if original was large
4991 if (fabs(maximumDown) > 1.0e8)
4992 newBound -= 1.0e-12 * fabs(maximumDown);
4993 } else {
4994 newBound = -COIN_DBL_MAX;
4995 }
4996 if (newBound > nowLower + 1.0e-12 && newBound > -large) {
4997 // Tighten the lower bound
4998 numberChanged++;
4999 // check infeasible (relaxed)
5000 if (nowUpper < newBound) {
5001 if (nowUpper - newBound <
5002 -100.0 * tolerance)
5003 numberInfeasible++;
5004 else
5005 newBound = nowUpper;
5006 }
5007 columnLower_[iColumn] = newBound;
5008 // adjust
5009 double now;
5010 if (nowLower < -large) {
5011 now = 0.0;
5012 infiniteUpper--;
5013 } else {
5014 now = nowLower;
5015 }
5016 maximumUp += (newBound - now) * value;
5017 nowLower = newBound;
5018#ifdef DEBUG
5019 checkCorrect(this, iRow,
5020 element, rowStart, rowLength,
5021 column,
5022 columnLower_, columnUpper_,
5023 infiniteUpper,
5024 infiniteLower,
5025 maximumUp,
5026 maximumDown);
5027#endif
5028 }
5029 }
5030 }
5031 }
5032 }
5033 }
5034 }
5035 totalTightened += numberChanged;
5036 if (iPass == 1)
5037 numberCheck = numberChanged >> 4;
5038 if (numberInfeasible) break;
5039 }
5040 if (!numberInfeasible) {
5041 handler_->message(CLP_SIMPLEX_BOUNDTIGHTEN, messages_)
5042 << totalTightened
5043 << CoinMessageEol;
5044 // Set bounds slightly loose
5045 double useTolerance = 1.0e-3;
5046 if (doTight > 0) {
5047 if (doTight > 10) {
5048 useTolerance = 0.0;
5049 } else {
5050 while (doTight) {
5051 useTolerance *= 0.1;
5052 doTight--;
5053 }
5054 }
5055 }
5056 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
5057 if (saveUpper[iColumn] > saveLower[iColumn] + useTolerance) {
5058 // Make large bounds stay infinite
5059 if (saveUpper[iColumn] > 1.0e30 && columnUpper_[iColumn] > 1.0e10) {
5060 columnUpper_[iColumn] = COIN_DBL_MAX;
5061 }
5062 if (saveLower[iColumn] < -1.0e30 && columnLower_[iColumn] < -1.0e10) {
5063 columnLower_[iColumn] = -COIN_DBL_MAX;
5064 }
5065#ifdef KEEP_GOING_IF_FIXED
5066 double multiplier = 5.0e-3 * floor(100.0 * randomNumberGenerator_.randomDouble()) + 1.0;
5067 multiplier *= 100.0;
5068#else
5069 double multiplier = 100.0;
5070#endif
5071 if (columnUpper_[iColumn] - columnLower_[iColumn] < useTolerance + 1.0e-8) {
5072 // relax enough so will have correct dj
5073#if 1
5074 columnLower_[iColumn] = CoinMax(saveLower[iColumn],
5075 columnLower_[iColumn] - multiplier * useTolerance);
5076 columnUpper_[iColumn] = CoinMin(saveUpper[iColumn],
5077 columnUpper_[iColumn] + multiplier * useTolerance);
5078#else
5079 if (fabs(columnUpper_[iColumn]) < fabs(columnLower_[iColumn])) {
5080 if (columnUpper_[iColumn] - multiplier * useTolerance > saveLower[iColumn]) {
5081 columnLower_[iColumn] = columnUpper_[iColumn] - multiplier * useTolerance;
5082 } else {
5083 columnLower_[iColumn] = saveLower[iColumn];
5084 columnUpper_[iColumn] = CoinMin(saveUpper[iColumn],
5085 saveLower[iColumn] + multiplier * useTolerance);
5086 }
5087 } else {
5088 if (columnLower_[iColumn] + multiplier * useTolerance < saveUpper[iColumn]) {
5089 columnUpper_[iColumn] = columnLower_[iColumn] + multiplier * useTolerance;
5090 } else {
5091 columnUpper_[iColumn] = saveUpper[iColumn];
5092 columnLower_[iColumn] = CoinMax(saveLower[iColumn],
5093 saveUpper[iColumn] - multiplier * useTolerance);
5094 }
5095 }
5096#endif
5097 } else {
5098 if (columnUpper_[iColumn] < saveUpper[iColumn]) {
5099 // relax a bit
5100 columnUpper_[iColumn] = CoinMin(columnUpper_[iColumn] + multiplier * useTolerance,
5101 saveUpper[iColumn]);
5102 }
5103 if (columnLower_[iColumn] > saveLower[iColumn]) {
5104 // relax a bit
5105 columnLower_[iColumn] = CoinMax(columnLower_[iColumn] - multiplier * useTolerance,
5106 saveLower[iColumn]);
5107 }
5108 }
5109 }
5110 }
5111 if (tightIntegers && integerType_) {
5112 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
5113 if (integerType_[iColumn]) {
5114 double value;
5115 value = floor(columnLower_[iColumn] + 0.5);
5116 if (fabs(value - columnLower_[iColumn]) > primalTolerance_)
5117 value = ceil(columnLower_[iColumn]);
5118 columnLower_[iColumn] = value;
5119 value = floor(columnUpper_[iColumn] + 0.5);
5120 if (fabs(value - columnUpper_[iColumn]) > primalTolerance_)
5121 value = floor(columnUpper_[iColumn]);
5122 columnUpper_[iColumn] = value;
5123 if (columnLower_[iColumn] > columnUpper_[iColumn])
5124 numberInfeasible++;
5125 }
5126 }
5127 if (numberInfeasible) {
5128 handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_)
5129 << numberInfeasible
5130 << CoinMessageEol;
5131 // restore column bounds
5132 CoinMemcpyN(saveLower, numberColumns_, columnLower_);
5133 CoinMemcpyN(saveUpper, numberColumns_, columnUpper_);
5134 }
5135 }
5136 } else {
5137 handler_->message(CLP_SIMPLEX_INFEASIBILITIES, messages_)
5138 << numberInfeasible
5139 << CoinMessageEol;
5140 // restore column bounds
5141 CoinMemcpyN(saveLower, numberColumns_, columnLower_);
5142 CoinMemcpyN(saveUpper, numberColumns_, columnUpper_);
5143 }
5144 delete [] saveLower;
5145 delete [] saveUpper;
5146 return (numberInfeasible);
5147}
5148//#define SAVE_AND_RESTORE
5149// dual
5150#include "ClpSimplexDual.hpp"
5151#include "ClpSimplexPrimal.hpp"
5152#ifndef SAVE_AND_RESTORE
5153int ClpSimplex::dual (int ifValuesPass , int startFinishOptions)
5154#else
5155int ClpSimplex::dual (int ifValuesPass , int startFinishOptions)
5156{
5157 // May be empty problem
5158 if (numberRows_ && numberColumns_) {
5159 // Save on file for debug
5160 int returnCode;
5161 returnCode = saveModel("debug.sav");
5162 if (returnCode) {
5163 printf("** Unable to save model to debug.sav\n");
5164 abort();
5165 }
5166 ClpSimplex temp;
5167 returnCode = temp.restoreModel("debug.sav");
5168 if (returnCode) {
5169 printf("** Unable to restore model from debug.sav\n");
5170 abort();
5171 }
5172 temp.setLogLevel(handler_->logLevel());
5173 // Now do dual
5174 returnCode = temp.dualDebug(ifValuesPass, startFinishOptions);
5175 // Move status and solution back
5176 int numberTotal = numberRows_ + numberColumns_;
5177 CoinMemcpyN(temp.statusArray(), numberTotal, status_);
5178 CoinMemcpyN(temp.primalColumnSolution(), numberColumns_, columnActivity_);
5179 CoinMemcpyN(temp.primalRowSolution(), numberRows_, rowActivity_);
5180 CoinMemcpyN(temp.dualColumnSolution(), numberColumns_, reducedCost_);
5181 CoinMemcpyN(temp.dualRowSolution(), numberRows_, dual_);
5182 problemStatus_ = temp.problemStatus_;
5183 setObjectiveValue(temp.objectiveValue());
5184 setSumDualInfeasibilities(temp.sumDualInfeasibilities());
5185 setNumberDualInfeasibilities(temp.numberDualInfeasibilities());
5186 setSumPrimalInfeasibilities(temp.sumPrimalInfeasibilities());
5187 setNumberPrimalInfeasibilities(temp.numberPrimalInfeasibilities());
5188 setNumberIterations(temp.numberIterations());
5189 onStopped(); // set secondary status if stopped
5190 return returnCode;
5191 } else {
5192 // empty
5193 return dualDebug(ifValuesPass, startFinishOptions);
5194 }
5195}
5196int ClpSimplex::dualDebug (int ifValuesPass , int startFinishOptions)
5197#endif
5198{
5199 //double savedPivotTolerance = factorization_->pivotTolerance();
5200 int saveQuadraticActivated = 0;
5201 if (objective_) {
5202 saveQuadraticActivated = objective_->activated();
5203 objective_->setActivated(0);
5204 } else {
5205 // create dummy stuff
5206 assert (!numberColumns_);
5207 if (!numberRows_)
5208 problemStatus_ = 0; // say optimal
5209 return 0;
5210 }
5211 ClpObjective * saveObjective = objective_;
5212 CoinAssert (ifValuesPass >= 0 && ifValuesPass < 3);
5213 /* Note use of "down casting". The only class the user sees is ClpSimplex.
5214 Classes ClpSimplexDual, ClpSimplexPrimal, (ClpSimplexNonlinear)
5215 and ClpSimplexOther all exist and inherit from ClpSimplex but have no
5216 additional data and have no destructor or (non-default) constructor.
5217
5218 This is to stop classes becoming too unwieldy and so I (JJF) can use e.g. "perturb"
5219 in primal and dual.
5220
5221 As far as I can see this is perfectly safe.
5222 */
5223#ifdef COIN_DEVELOP
5224 //#define EXPENSIVE
5225#endif
5226#ifdef EXPENSIVE
5227 static int dualCount = 0;
5228 static int dualCheckCount = -1;
5229 dualCount++;
5230 if (dualCount == dualCheckCount) {
5231 printf("Bad dual coming up\n");
5232 }
5233 ClpSimplex saveModel = *this;
5234#endif
5235 int returnCode = static_cast<ClpSimplexDual *> (this)->dual(ifValuesPass, startFinishOptions);
5236#ifdef EXPENSIVE
5237 if (problemStatus_ == 1) {
5238 saveModel.allSlackBasis(true);
5239 static_cast<ClpSimplexDual *> (&saveModel)->dual(0, 0);
5240 if (saveModel.problemStatus_ == 0) {
5241 if (saveModel.objectiveValue() < dblParam_[0] - 1.0e-8 * (1.0 + fabs(dblParam_[0]))) {
5242 if (objectiveValue() < dblParam_[0] - 1.0e-6 * (1.0 + fabs(dblParam_[0]))) {
5243 printf("BAD dual - objs %g ,savemodel %g cutoff %g at count %d\n",
5244 objectiveValue(), saveModel.objectiveValue(), dblParam_[0], dualCount);
5245 saveModel = *this;
5246 saveModel.setLogLevel(63);
5247 static_cast<ClpSimplexDual *> (&saveModel)->dual(0, 0);
5248 // flatten solution and try again
5249 int iRow, iColumn;
5250 for (iRow = 0; iRow < numberRows_; iRow++) {
5251 if (getRowStatus(iRow) != basic) {
5252 setRowStatus(iRow, superBasic);
5253 // but put to bound if close
5254 if (fabs(rowActivity_[iRow] - rowLower_[iRow])
5255 <= primalTolerance_) {
5256 rowActivity_[iRow] = rowLower_[iRow];
5257 setRowStatus(iRow, atLowerBound);
5258 } else if (fabs(rowActivity_[iRow] - rowUpper_[iRow])
5259 <= primalTolerance_) {
5260 rowActivity_[iRow] = rowUpper_[iRow];
5261 setRowStatus(iRow, atUpperBound);
5262 }
5263 }
5264 }
5265 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
5266 if (getColumnStatus(iColumn) != basic) {
5267 setColumnStatus(iColumn, superBasic);
5268 // but put to bound if close
5269 if (fabs(columnActivity_[iColumn] - columnLower_[iColumn])
5270 <= primalTolerance_) {
5271 columnActivity_[iColumn] = columnLower_[iColumn];
5272 setColumnStatus(iColumn, atLowerBound);
5273 } else if (fabs(columnActivity_[iColumn]
5274 - columnUpper_[iColumn])
5275 <= primalTolerance_) {
5276 columnActivity_[iColumn] = columnUpper_[iColumn];
5277 setColumnStatus(iColumn, atUpperBound);
5278 }
5279 }
5280 }
5281 static_cast<ClpSimplexPrimal *> (&saveModel)->primal(0, 0);
5282 } else {
5283 printf("bad? dual - objs %g ,savemodel %g cutoff %g at count %d\n",
5284 objectiveValue(), saveModel.objectiveValue(), dblParam_[0], dualCount);
5285 }
5286 if (dualCount > dualCheckCount && dualCheckCount >= 0)
5287 abort();
5288 }
5289 }
5290 }
5291#endif
5292 //int lastAlgorithm = -1;
5293 if ((specialOptions_ & 2048) != 0 && problemStatus_ == 10 && !numberPrimalInfeasibilities_
5294 && sumDualInfeasibilities_ < 1000.0 * dualTolerance_ && perturbation_ >= 100)
5295 problemStatus_ = 0; // ignore
5296 if (problemStatus_ == 10) {
5297 //printf("Cleaning up with primal\n");
5298#ifdef COIN_DEVELOP
5299 int saveNumberIterations = numberIterations_;
5300#endif
5301 //lastAlgorithm=1;
5302 int savePerturbation = perturbation_;
5303 int saveLog = handler_->logLevel();
5304 //handler_->setLogLevel(63);
5305 perturbation_ = 100;
5306 bool denseFactorization = initialDenseFactorization();
5307 // It will be safe to allow dense
5308 setInitialDenseFactorization(true);
5309 // Allow for catastrophe
5310 int saveMax = intParam_[ClpMaxNumIteration];
5311 if (numberIterations_) {
5312 // normal
5313 if (intParam_[ClpMaxNumIteration] > 100000 + numberIterations_)
5314 intParam_[ClpMaxNumIteration]
5315 = numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_;
5316 } else {
5317 // Not normal allow more
5318 baseIteration_ += 2 * (numberRows_ + numberColumns_);
5319 }
5320 // check which algorithms allowed
5321 int dummy;
5322 ClpPackedMatrix * ordinary =
5323 dynamic_cast< ClpPackedMatrix*>(matrix_);
5324 if (problemStatus_ == 10 && saveObjective == objective_ &&
5325 ordinary)
5326 startFinishOptions |= 2;
5327 baseIteration_ = numberIterations_;
5328 // Say second call
5329 moreSpecialOptions_ |= 256;
5330 if ((matrix_->generalExpanded(this, 4, dummy) & 1) != 0)
5331 returnCode = static_cast<ClpSimplexPrimal *> (this)->primal(1, startFinishOptions);
5332 else
5333 returnCode = static_cast<ClpSimplexDual *> (this)->dual(0, startFinishOptions);
5334 // Say not second call
5335 moreSpecialOptions_ &= ~256;
5336 baseIteration_ = 0;
5337 if (saveObjective != objective_) {
5338 // We changed objective to see if infeasible
5339 delete objective_;
5340 objective_ = saveObjective;
5341 if (!problemStatus_) {
5342 // carry on
5343 returnCode = static_cast<ClpSimplexPrimal *> (this)->primal(1, startFinishOptions);
5344 }
5345 }
5346 if (problemStatus_ == 3 && numberIterations_ < saveMax) {
5347#ifdef COIN_DEVELOP
5348 if (handler_->logLevel() > 0)
5349 printf("looks like trouble - too many iterations in clean up - trying again\n");
5350#endif
5351 // flatten solution and try again
5352 int iRow, iColumn;
5353 for (iRow = 0; iRow < numberRows_; iRow++) {
5354 if (getRowStatus(iRow) != basic) {
5355 setRowStatus(iRow, superBasic);
5356 // but put to bound if close
5357 if (fabs(rowActivity_[iRow] - rowLower_[iRow])
5358 <= primalTolerance_) {
5359 rowActivity_[iRow] = rowLower_[iRow];
5360 setRowStatus(iRow, atLowerBound);
5361 } else if (fabs(rowActivity_[iRow] - rowUpper_[iRow])
5362 <= primalTolerance_) {
5363 rowActivity_[iRow] = rowUpper_[iRow];
5364 setRowStatus(iRow, atUpperBound);
5365 }
5366 }
5367 }
5368 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
5369 if (getColumnStatus(iColumn) != basic) {
5370 setColumnStatus(iColumn, superBasic);
5371 // but put to bound if close
5372 if (fabs(columnActivity_[iColumn] - columnLower_[iColumn])
5373 <= primalTolerance_) {
5374 columnActivity_[iColumn] = columnLower_[iColumn];
5375 setColumnStatus(iColumn, atLowerBound);
5376 } else if (fabs(columnActivity_[iColumn]
5377 - columnUpper_[iColumn])
5378 <= primalTolerance_) {
5379 columnActivity_[iColumn] = columnUpper_[iColumn];
5380 setColumnStatus(iColumn, atUpperBound);
5381 }
5382 }
5383 }
5384 problemStatus_ = -1;
5385 intParam_[ClpMaxNumIteration] = CoinMin(numberIterations_ + 1000 +
5386 2 * numberRows_ + numberColumns_, saveMax);
5387 perturbation_ = savePerturbation;
5388 baseIteration_ = numberIterations_;
5389 // Say second call
5390 moreSpecialOptions_ |= 256;
5391 returnCode = static_cast<ClpSimplexPrimal *> (this)->primal(0, startFinishOptions);
5392 // Say not second call
5393 moreSpecialOptions_ &= ~256;
5394 baseIteration_ = 0;
5395 computeObjectiveValue();
5396 // can't rely on djs either
5397 memset(reducedCost_, 0, numberColumns_ * sizeof(double));
5398#ifdef COIN_DEVELOP
5399 if (problemStatus_ == 3 && numberIterations_ < saveMax &&
5400 handler_->logLevel() > 0)
5401 printf("looks like real trouble - too many iterations in second clean up - giving up\n");
5402#endif
5403 }
5404 intParam_[ClpMaxNumIteration] = saveMax;
5405
5406 setInitialDenseFactorization(denseFactorization);
5407 perturbation_ = savePerturbation;
5408 if (problemStatus_ == 10) {
5409 if (!numberPrimalInfeasibilities_)
5410 problemStatus_ = 0;
5411 else
5412 problemStatus_ = 4;
5413 }
5414 handler_->setLogLevel(saveLog);
5415#ifdef COIN_DEVELOP
5416 if (numberIterations_ > 200)
5417 printf("after primal status %d - %d iterations (save %d)\n",
5418 problemStatus_, numberIterations_, saveNumberIterations);
5419#endif
5420 }
5421 objective_->setActivated(saveQuadraticActivated);
5422 //factorization_->pivotTolerance(savedPivotTolerance);
5423 onStopped(); // set secondary status if stopped
5424 //if (problemStatus_==1&&lastAlgorithm==1)
5425 //returnCode=10; // so will do primal after postsolve
5426 if (!problemStatus_) {
5427 //assert (!numberPrimalInfeasibilities_);
5428 //if (returnCode!=10)
5429 //assert (!numberDualInfeasibilities_);
5430 }
5431 return returnCode;
5432}
5433// primal
5434int ClpSimplex::primal (int ifValuesPass , int startFinishOptions)
5435{
5436 //double savedPivotTolerance = factorization_->pivotTolerance();
5437#ifndef SLIM_CLP
5438 // See if nonlinear
5439 if (objective_->type() > 1 && objective_->activated())
5440 return reducedGradient();
5441#endif
5442 CoinAssert ((ifValuesPass >= 0 && ifValuesPass < 3) ||
5443 (ifValuesPass >= 12 && ifValuesPass < 100) ||
5444 (ifValuesPass >= 112 && ifValuesPass < 200));
5445 if (ifValuesPass >= 12) {
5446 int numberProblems = (ifValuesPass - 10) % 100;
5447 ifValuesPass = (ifValuesPass < 100) ? 1 : 2;
5448 // Go parallel to do solve
5449 // Only if all slack basis
5450 int i;
5451 for ( i = 0; i < numberColumns_; i++) {
5452 if (getColumnStatus(i) == basic)
5453 break;
5454 }
5455 if (i == numberColumns_) {
5456 // try if vaguely feasible
5457 CoinZeroN(rowActivity_, numberRows_);
5458 const int * row = matrix_->getIndices();
5459 const CoinBigIndex * columnStart = matrix_->getVectorStarts();
5460 const int * columnLength = matrix_->getVectorLengths();
5461 const double * element = matrix_->getElements();
5462 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
5463 CoinBigIndex j;
5464 double value = columnActivity_[iColumn];
5465 if (value) {
5466 CoinBigIndex start = columnStart[iColumn];
5467 CoinBigIndex end = start + columnLength[iColumn];
5468 for (j = start; j < end; j++) {
5469 int iRow = row[j];
5470 rowActivity_[iRow] += value * element[j];
5471 }
5472 }
5473 }
5474 checkSolutionInternal();
5475 if (sumPrimalInfeasibilities_ * sqrt(static_cast<double>(numberRows_)) < 1.0) {
5476 // Could do better if can decompose
5477 // correction to get feasible
5478 double scaleFactor = 1.0 / numberProblems;
5479 double * correction = new double [numberRows_];
5480 for (int iRow = 0; iRow < numberRows_; iRow++) {
5481 double value = rowActivity_[iRow];
5482 if (value > rowUpper_[iRow])
5483 value = rowUpper_[iRow] - value;
5484 else if (value < rowLower_[iRow])
5485 value = rowLower_[iRow] - value;
5486 else
5487 value = 0.0;
5488 correction[iRow] = value * scaleFactor;
5489 }
5490 int numberColumns = (numberColumns_ + numberProblems - 1) / numberProblems;
5491 int * whichRows = new int [numberRows_];
5492 for (int i = 0; i < numberRows_; i++)
5493 whichRows[i] = i;
5494 int * whichColumns = new int [numberColumns_];
5495 ClpSimplex ** model = new ClpSimplex * [numberProblems];
5496 int startColumn = 0;
5497 double * saveLower = CoinCopyOfArray(rowLower_, numberRows_);
5498 double * saveUpper = CoinCopyOfArray(rowUpper_, numberRows_);
5499 for (int i = 0; i < numberProblems; i++) {
5500 int endColumn = CoinMin(startColumn + numberColumns, numberColumns_);
5501 CoinZeroN(rowActivity_, numberRows_);
5502 for (int iColumn = startColumn; iColumn < endColumn; iColumn++) {
5503 whichColumns[iColumn-startColumn] = iColumn;
5504 CoinBigIndex j;
5505 double value = columnActivity_[iColumn];
5506 if (value) {
5507 CoinBigIndex start = columnStart[iColumn];
5508 CoinBigIndex end = start + columnLength[iColumn];
5509 for (j = start; j < end; j++) {
5510 int iRow = row[j];
5511 rowActivity_[iRow] += value * element[j];
5512 }
5513 }
5514 }
5515 // adjust rhs
5516 for (int iRow = 0; iRow < numberRows_; iRow++) {
5517 double value = rowActivity_[iRow] + correction[iRow];
5518 if (saveUpper[iRow] < 1.0e30)
5519 rowUpper_[iRow] = value;
5520 if (saveLower[iRow] > -1.0e30)
5521 rowLower_[iRow] = value;
5522 }
5523 model[i] = new ClpSimplex(this, numberRows_, whichRows,
5524 endColumn - startColumn, whichColumns);
5525 //#define FEB_TRY
5526#ifdef FEB_TRY
5527 model[i]->setPerturbation(perturbation_);
5528#endif
5529 startColumn = endColumn;
5530 }
5531 memcpy(rowLower_, saveLower, numberRows_ * sizeof(double));
5532 memcpy(rowUpper_, saveUpper, numberRows_ * sizeof(double));
5533 delete [] saveLower;
5534 delete [] saveUpper;
5535 delete [] correction;
5536 // solve (in parallel)
5537 for (int i = 0; i < numberProblems; i++) {
5538 model[i]->primal(1/*ifValuesPass*/);
5539 }
5540 startColumn = 0;
5541 int numberBasic = 0;
5542 // use whichRows as counter
5543 for (int iRow = 0; iRow < numberRows_; iRow++) {
5544 int startValue = 0;
5545 if (rowUpper_[iRow] > rowLower_[iRow])
5546 startValue++;
5547 if (rowUpper_[iRow] > 1.0e30)
5548 startValue++;
5549 if (rowLower_[iRow] < -1.0e30)
5550 startValue++;
5551 whichRows[iRow] = 1000 * startValue;
5552 }
5553 for (int i = 0; i < numberProblems; i++) {
5554 int endColumn = CoinMin(startColumn + numberColumns, numberColumns_);
5555 ClpSimplex * simplex = model[i];
5556 const double * solution = simplex->columnActivity_;
5557 for (int iColumn = startColumn; iColumn < endColumn; iColumn++) {
5558 columnActivity_[iColumn] = solution[iColumn-startColumn];
5559 Status status = simplex->getColumnStatus(iColumn - startColumn);
5560 setColumnStatus(iColumn, status);
5561 if (status == basic)
5562 numberBasic++;
5563 }
5564 for (int iRow = 0; iRow < numberRows_; iRow++) {
5565 if (simplex->getRowStatus(iRow) == basic)
5566 whichRows[iRow]++;
5567 }
5568 delete model[i];
5569 startColumn = endColumn;
5570 }
5571 delete [] model;
5572 for (int iRow = 0; iRow < numberRows_; iRow++)
5573 setRowStatus(iRow, superBasic);
5574 CoinZeroN(rowActivity_, numberRows_);
5575 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
5576 CoinBigIndex j;
5577 double value = columnActivity_[iColumn];
5578 if (value) {
5579 CoinBigIndex start = columnStart[iColumn];
5580 CoinBigIndex end = start + columnLength[iColumn];
5581 for (j = start; j < end; j++) {
5582 int iRow = row[j];
5583 rowActivity_[iRow] += value * element[j];
5584 }
5585 }
5586 }
5587 checkSolutionInternal();
5588 if (numberBasic < numberRows_) {
5589 int * order = new int [numberRows_];
5590 for (int iRow = 0; iRow < numberRows_; iRow++) {
5591 setRowStatus(iRow, superBasic);
5592 int nTimes = whichRows[iRow] % 1000;
5593 if (nTimes)
5594 nTimes += whichRows[iRow] / 500;
5595 whichRows[iRow] = -nTimes;
5596 order[iRow] = iRow;
5597 }
5598 CoinSort_2(whichRows, whichRows + numberRows_, order);
5599 int nPut = numberRows_ - numberBasic;
5600 for (int i = 0; i < nPut; i++) {
5601 int iRow = order[i];
5602 setRowStatus(iRow, basic);
5603 }
5604 delete [] order;
5605 } else if (numberBasic > numberRows_) {
5606 double * away = new double [numberBasic];
5607 numberBasic = 0;
5608 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
5609 if (getColumnStatus(iColumn) == basic) {
5610 double value = columnActivity_[iColumn];
5611 value = CoinMin(value - columnLower_[iColumn],
5612 columnUpper_[iColumn] - value);
5613 away[numberBasic] = value;
5614 whichColumns[numberBasic++] = iColumn;
5615 }
5616 }
5617 CoinSort_2(away, away + numberBasic, whichColumns);
5618 int nPut = numberBasic - numberRows_;
5619 for (int i = 0; i < nPut; i++) {
5620 int iColumn = whichColumns[i];
5621 double value = columnActivity_[iColumn];
5622 if (value - columnLower_[iColumn] <
5623 columnUpper_[iColumn] - value)
5624 setColumnStatus(iColumn, atLowerBound);
5625 else
5626 setColumnStatus(iColumn, atUpperBound);
5627 }
5628 delete [] away;
5629 }
5630 delete [] whichColumns;
5631 delete [] whichRows;
5632 }
5633 }
5634 }
5635 //firstFree_=-1;
5636 /* Note use of "down casting". The only class the user sees is ClpSimplex.
5637 Classes ClpSimplexDual, ClpSimplexPrimal, (ClpSimplexNonlinear)
5638 and ClpSimplexOther all exist and inherit from ClpSimplex but have no
5639 additional data and have no destructor or (non-default) constructor.
5640
5641 This is to stop classes becoming too unwieldy and so I (JJF) can use e.g. "perturb"
5642 in primal and dual.
5643
5644 As far as I can see this is perfectly safe.
5645 */
5646 int returnCode = static_cast<ClpSimplexPrimal *> (this)->primal(ifValuesPass, startFinishOptions);
5647 //int lastAlgorithm=1;
5648 if (problemStatus_ == 10) {
5649 //lastAlgorithm=-1;
5650 //printf("Cleaning up with dual\n");
5651 int savePerturbation = perturbation_;
5652 perturbation_ = 100;
5653 bool denseFactorization = initialDenseFactorization();
5654 // It will be safe to allow dense
5655 setInitialDenseFactorization(true);
5656 // check which algorithms allowed
5657 int dummy;
5658 baseIteration_ = numberIterations_;
5659 // Say second call
5660 moreSpecialOptions_ |= 256;
5661 if ((matrix_->generalExpanded(this, 4, dummy) & 2) != 0 && (specialOptions_ & 8192) == 0) {
5662 double saveBound = dualBound_;
5663 // upperOut_ has largest away from bound
5664 dualBound_ = CoinMin(CoinMax(2.0 * upperOut_, 1.0e8), dualBound_);
5665 returnCode = static_cast<ClpSimplexDual *> (this)->dual(0, startFinishOptions);
5666 dualBound_ = saveBound;
5667 } else {
5668 returnCode = static_cast<ClpSimplexPrimal *> (this)->primal(0, startFinishOptions);
5669 }
5670 // Say not second call
5671 moreSpecialOptions_ &= ~256;
5672 baseIteration_ = 0;
5673 setInitialDenseFactorization(denseFactorization);
5674 perturbation_ = savePerturbation;
5675 if (problemStatus_ == 10) {
5676 if (!numberPrimalInfeasibilities_) {
5677 problemStatus_ = 0;
5678 numberDualInfeasibilities_ = 0;
5679 } else {
5680 problemStatus_ = 4;
5681 }
5682 }
5683 }
5684 //factorization_->pivotTolerance(savedPivotTolerance);
5685 onStopped(); // set secondary status if stopped
5686 //if (problemStatus_==1&&lastAlgorithm==1)
5687 //returnCode=10; // so will do primal after postsolve
5688 return returnCode;
5689}
5690#ifndef SLIM_CLP
5691#include "ClpQuadraticObjective.hpp"
5692/* Dual ranging.
5693 This computes increase/decrease in cost for each given variable and corresponding
5694 sequence numbers which would change basis. Sequence numbers are 0..numberColumns
5695 and numberColumns.. for artificials/slacks.
5696 For non-basic variables the sequence number will be that of the non-basic variables.
5697
5698 Up to user to provide correct length arrays.
5699
5700 Returns non-zero if infeasible unbounded etc
5701*/
5702#include "ClpSimplexOther.hpp"
5703int ClpSimplex::dualRanging(int numberCheck, const int * which,
5704 double * costIncrease, int * sequenceIncrease,
5705 double * costDecrease, int * sequenceDecrease,
5706 double * valueIncrease, double * valueDecrease)
5707{
5708 int savePerturbation = perturbation_;
5709 perturbation_ = 100;
5710 /*int returnCode =*/ static_cast<ClpSimplexPrimal *> (this)->primal(0, 1);
5711 if (problemStatus_ == 10) {
5712 //printf("Cleaning up with dual\n");
5713 bool denseFactorization = initialDenseFactorization();
5714 // It will be safe to allow dense
5715 setInitialDenseFactorization(true);
5716 // check which algorithms allowed
5717 int dummy;
5718 if ((matrix_->generalExpanded(this, 4, dummy) & 2) != 0) {
5719 // upperOut_ has largest away from bound
5720 double saveBound = dualBound_;
5721 if (upperOut_ > 0.0)
5722 dualBound_ = 2.0 * upperOut_;
5723 /*returnCode =*/ static_cast<ClpSimplexDual *> (this)->dual(0, 1);
5724 dualBound_ = saveBound;
5725 } else {
5726 /*returnCode =*/ static_cast<ClpSimplexPrimal *> (this)->primal(0, 1);
5727 }
5728 setInitialDenseFactorization(denseFactorization);
5729 if (problemStatus_ == 10)
5730 problemStatus_ = 0;
5731 }
5732 perturbation_ = savePerturbation;
5733 if (problemStatus_ || secondaryStatus_ == 6) {
5734 finish(); // get rid of arrays
5735 return 1; // odd status
5736 }
5737 static_cast<ClpSimplexOther *> (this)->dualRanging(numberCheck, which,
5738 costIncrease, sequenceIncrease,
5739 costDecrease, sequenceDecrease,
5740 valueIncrease, valueDecrease);
5741 finish(); // get rid of arrays
5742 return 0;
5743}
5744/* Primal ranging.
5745 This computes increase/decrease in value for each given variable and corresponding
5746 sequence numbers which would change basis. Sequence numbers are 0..numberColumns
5747 and numberColumns.. for artificials/slacks.
5748 For basic variables the sequence number will be that of the basic variables.
5749
5750 Up to user to providen correct length arrays.
5751
5752 Returns non-zero if infeasible unbounded etc
5753*/
5754int ClpSimplex::primalRanging(int numberCheck, const int * which,
5755 double * valueIncrease, int * sequenceIncrease,
5756 double * valueDecrease, int * sequenceDecrease)
5757{
5758 int savePerturbation = perturbation_;
5759 perturbation_ = 100;
5760 /*int returnCode =*/ static_cast<ClpSimplexPrimal *> (this)->primal(0, 1);
5761 if (problemStatus_ == 10) {
5762 //printf("Cleaning up with dual\n");
5763 bool denseFactorization = initialDenseFactorization();
5764 // It will be safe to allow dense
5765 setInitialDenseFactorization(true);
5766 // check which algorithms allowed
5767 int dummy;
5768 if ((matrix_->generalExpanded(this, 4, dummy) & 2) != 0) {
5769 // upperOut_ has largest away from bound
5770 double saveBound = dualBound_;
5771 if (upperOut_ > 0.0)
5772 dualBound_ = 2.0 * upperOut_;
5773 /*returnCode =*/ static_cast<ClpSimplexDual *> (this)->dual(0, 1);
5774 dualBound_ = saveBound;
5775 } else {
5776 /*returnCode =*/ static_cast<ClpSimplexPrimal *> (this)->primal(0, 1);
5777 }
5778 setInitialDenseFactorization(denseFactorization);
5779 if (problemStatus_ == 10)
5780 problemStatus_ = 0;
5781 }
5782 perturbation_ = savePerturbation;
5783 if (problemStatus_ || secondaryStatus_ == 6) {
5784 finish(); // get rid of arrays
5785 return 1; // odd status
5786 }
5787 static_cast<ClpSimplexOther *> (this)->primalRanging(numberCheck, which,
5788 valueIncrease, sequenceIncrease,
5789 valueDecrease, sequenceDecrease);
5790 finish(); // get rid of arrays
5791 return 0;
5792}
5793/* Write the basis in MPS format to the specified file.
5794 If writeValues true writes values of structurals
5795 (and adds VALUES to end of NAME card)
5796
5797 Row and column names may be null.
5798 formatType is
5799 <ul>
5800 <li> 0 - normal
5801 <li> 1 - extra accuracy
5802 <li> 2 - IEEE hex (later)
5803 </ul>
5804
5805 Returns non-zero on I/O error
5806*/
5807int
5808ClpSimplex::writeBasis(const char *filename,
5809 bool writeValues,
5810 int formatType) const
5811{
5812 return static_cast<const ClpSimplexOther *> (this)->writeBasis(filename, writeValues,
5813 formatType);
5814}
5815// Read a basis from the given filename
5816int
5817ClpSimplex::readBasis(const char *filename)
5818{
5819 return static_cast<ClpSimplexOther *> (this)->readBasis(filename);
5820}
5821#include "ClpSimplexNonlinear.hpp"
5822/* Solves nonlinear problem using SLP - may be used as crash
5823 for other algorithms when number of iterations small
5824*/
5825int
5826ClpSimplex::nonlinearSLP(int numberPasses, double deltaTolerance)
5827{
5828 return static_cast<ClpSimplexNonlinear *> (this)->primalSLP(numberPasses, deltaTolerance);
5829}
5830/* Solves problem with nonlinear constraints using SLP - may be used as crash
5831 for other algorithms when number of iterations small.
5832 Also exits if all problematical variables are changing
5833 less than deltaTolerance
5834*/
5835int
5836ClpSimplex::nonlinearSLP(int numberConstraints, ClpConstraint ** constraints,
5837 int numberPasses, double deltaTolerance)
5838{
5839 return static_cast<ClpSimplexNonlinear *> (this)->primalSLP(numberConstraints, constraints, numberPasses, deltaTolerance);
5840}
5841// Solves non-linear using reduced gradient
5842int ClpSimplex::reducedGradient(int phase)
5843{
5844 if (objective_->type() < 2 || !objective_->activated()) {
5845 // no quadratic part
5846 return primal(0);
5847 }
5848 // get feasible
5849 if ((this->status() < 0 || numberPrimalInfeasibilities()) && phase == 0) {
5850 objective_->setActivated(0);
5851 double saveDirection = optimizationDirection();
5852 setOptimizationDirection(0.0);
5853 primal(1);
5854 setOptimizationDirection(saveDirection);
5855 objective_->setActivated(1);
5856 // still infeasible
5857 if (numberPrimalInfeasibilities())
5858 return 0;
5859 }
5860 // Now enter method
5861 int returnCode = static_cast<ClpSimplexNonlinear *> (this)->primal();
5862 return returnCode;
5863}
5864#include "ClpPredictorCorrector.hpp"
5865#include "ClpCholeskyBase.hpp"
5866// Preference is WSSMP, UFL (just ordering), MUMPS, TAUCS then base
5867#include "ClpCholeskyWssmp.hpp"
5868#include "ClpCholeskyWssmpKKT.hpp"
5869#include "ClpCholeskyUfl.hpp"
5870#include "ClpCholeskyMumps.hpp"
5871#if TAUCS_BARRIER
5872#include "ClpCholeskyTaucs.hpp"
5873#endif
5874#include "ClpPresolve.hpp"
5875/* Solves using barrier (assumes you have good cholesky factor code).
5876 Does crossover to simplex if asked*/
5877int
5878ClpSimplex::barrier(bool crossover)
5879{
5880 ClpSimplex * model2 = this;
5881 int savePerturbation = perturbation_;
5882 ClpInterior barrier;
5883 barrier.borrowModel(*model2);
5884 // See if quadratic objective
5885 ClpQuadraticObjective * quadraticObj = NULL;
5886 if (objective_->type() == 2)
5887 quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
5888 // If Quadratic we need KKT
5889 bool doKKT = (quadraticObj != NULL);
5890 // Preference is WSSMP, UFL, MUMPS, TAUCS then base
5891#ifdef WSSMP_BARRIER
5892 if (!doKKT) {
5893 ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp(CoinMax(100, model2->numberRows() / 10));
5894 barrier.setCholesky(cholesky);
5895 } else {
5896 //ClpCholeskyWssmp * cholesky = new ClpCholeskyWssmp();
5897 ClpCholeskyWssmpKKT * cholesky = new ClpCholeskyWssmpKKT(CoinMax(100, model2->numberRows() / 10));
5898 barrier.setCholesky(cholesky);
5899 }
5900#elif defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD)
5901 if (!doKKT) {
5902 ClpCholeskyUfl * cholesky = new ClpCholeskyUfl();
5903 barrier.setCholesky(cholesky);
5904 } else {
5905 ClpCholeskyBase * cholesky = new ClpCholeskyBase();
5906 // not yetClpCholeskyUfl * cholesky = new ClpCholeskyUfl();
5907 cholesky->setKKT(true);
5908 barrier.setCholesky(cholesky);
5909 }
5910#elif TAUCS_BARRIER
5911 assert (!doKKT);
5912 ClpCholeskyTaucs * cholesky = new ClpCholeskyTaucs();
5913 barrier.setCholesky(cholesky);
5914#elifdef COIN_HAS_MUMPS
5915 if (!doKKT) {
5916 ClpCholeskyMumps * cholesky = new ClpCholeskyMumps();
5917 barrier.setCholesky(cholesky);
5918 } else {
5919 printf("***** Unable to do Mumps with KKT\n");
5920 ClpCholeskyBase * cholesky = new ClpCholeskyBase();
5921 cholesky->setKKT(true);
5922 barrier.setCholesky(cholesky);
5923 }
5924#else
5925 if (!doKKT) {
5926 ClpCholeskyBase * cholesky = new ClpCholeskyBase();
5927 barrier.setCholesky(cholesky);
5928 } else {
5929 ClpCholeskyBase * cholesky = new ClpCholeskyBase();
5930 cholesky->setKKT(true);
5931 barrier.setCholesky(cholesky);
5932 }
5933#endif
5934 barrier.setDiagonalPerturbation(1.0e-14);
5935 int numberRows = model2->numberRows();
5936 int numberColumns = model2->numberColumns();
5937 int saveMaxIts = model2->maximumIterations();
5938 if (saveMaxIts < 1000) {
5939 barrier.setMaximumBarrierIterations(saveMaxIts);
5940 model2->setMaximumIterations(1000000);
5941 }
5942 barrier.primalDual();
5943 int barrierStatus = barrier.status();
5944 double gap = static_cast<double>(barrier.complementarityGap());
5945 // get which variables are fixed
5946 double * saveLower = NULL;
5947 double * saveUpper = NULL;
5948 ClpPresolve pinfo2;
5949 ClpSimplex * saveModel2 = NULL;
5950 int numberFixed = barrier.numberFixed();
5951 if (numberFixed * 20 > barrier.numberRows() && numberFixed > 5000 && crossover && 0) {
5952 // may as well do presolve
5953 int numberRows = barrier.numberRows();
5954 int numberColumns = barrier.numberColumns();
5955 int numberTotal = numberRows + numberColumns;
5956 saveLower = new double [numberTotal];
5957 saveUpper = new double [numberTotal];
5958 CoinMemcpyN(barrier.columnLower(), numberColumns, saveLower);
5959 CoinMemcpyN(barrier.rowLower(), numberRows, saveLower + numberColumns);
5960 CoinMemcpyN(barrier.columnUpper(), numberColumns, saveUpper);
5961 CoinMemcpyN(barrier.rowUpper(), numberRows, saveUpper + numberColumns);
5962 barrier.fixFixed();
5963 saveModel2 = model2;
5964 }
5965 barrier.returnModel(*model2);
5966 double * rowPrimal = new double [numberRows];
5967 double * columnPrimal = new double [numberColumns];
5968 double * rowDual = new double [numberRows];
5969 double * columnDual = new double [numberColumns];
5970 // move solutions other way
5971 CoinMemcpyN(model2->primalRowSolution(),
5972 numberRows, rowPrimal);
5973 CoinMemcpyN(model2->dualRowSolution(),
5974 numberRows, rowDual);
5975 CoinMemcpyN(model2->primalColumnSolution(),
5976 numberColumns, columnPrimal);
5977 CoinMemcpyN(model2->dualColumnSolution(),
5978 numberColumns, columnDual);
5979 if (saveModel2) {
5980 // do presolve
5981 model2 = pinfo2.presolvedModel(*model2, 1.0e-8,
5982 false, 5, true);
5983 }
5984 if (barrierStatus < 4 && crossover) {
5985 // make sure no status left
5986 model2->createStatus();
5987 // solve
5988 model2->setPerturbation(100);
5989 // throw some into basis
5990 {
5991 int numberRows = model2->numberRows();
5992 int numberColumns = model2->numberColumns();
5993 double * dsort = new double[numberColumns];
5994 int * sort = new int[numberColumns];
5995 int n = 0;
5996 const double * columnLower = model2->columnLower();
5997 const double * columnUpper = model2->columnUpper();
5998 const double * primalSolution = model2->primalColumnSolution();
5999 double tolerance = 10.0 * primalTolerance_;
6000 int i;
6001 for ( i = 0; i < numberRows; i++)
6002 model2->setRowStatus(i, superBasic);
6003 for ( i = 0; i < numberColumns; i++) {
6004 double distance = CoinMin(columnUpper[i] - primalSolution[i],
6005 primalSolution[i] - columnLower[i]);
6006 if (distance > tolerance) {
6007 dsort[n] = -distance;
6008 sort[n++] = i;
6009 model2->setStatus(i, superBasic);
6010 } else if (distance > primalTolerance_) {
6011 model2->setStatus(i, superBasic);
6012 } else if (primalSolution[i] <= columnLower[i] + primalTolerance_) {
6013 model2->setStatus(i, atLowerBound);
6014 } else {
6015 model2->setStatus(i, atUpperBound);
6016 }
6017 }
6018 CoinSort_2(dsort, dsort + n, sort);
6019 n = CoinMin(numberRows, n);
6020 for ( i = 0; i < n; i++) {
6021 int iColumn = sort[i];
6022 model2->setStatus(iColumn, basic);
6023 }
6024 delete [] sort;
6025 delete [] dsort;
6026 }
6027 if (gap < 1.0e-3 * (static_cast<double> (numberRows + numberColumns))) {
6028 int numberRows = model2->numberRows();
6029 int numberColumns = model2->numberColumns();
6030 // just primal values pass
6031 double saveScale = model2->objectiveScale();
6032 model2->setObjectiveScale(1.0e-3);
6033 model2->primal(2);
6034 model2->setObjectiveScale(saveScale);
6035 // save primal solution and copy back dual
6036 CoinMemcpyN(model2->primalRowSolution(),
6037 numberRows, rowPrimal);
6038 CoinMemcpyN(rowDual,
6039 numberRows, model2->dualRowSolution());
6040 CoinMemcpyN(model2->primalColumnSolution(),
6041 numberColumns, columnPrimal);
6042 CoinMemcpyN(columnDual,
6043 numberColumns, model2->dualColumnSolution());
6044 //model2->primal(1);
6045 // clean up reduced costs and flag variables
6046 {
6047 double * dj = model2->dualColumnSolution();
6048 double * cost = model2->objective();
6049 double * saveCost = new double[numberColumns];
6050 CoinMemcpyN(cost, numberColumns, saveCost);
6051 double * saveLower = new double[numberColumns];
6052 double * lower = model2->columnLower();
6053 CoinMemcpyN(lower, numberColumns, saveLower);
6054 double * saveUpper = new double[numberColumns];
6055 double * upper = model2->columnUpper();
6056 CoinMemcpyN(upper, numberColumns, saveUpper);
6057 int i;
6058 double tolerance = 10.0 * dualTolerance_;
6059 for ( i = 0; i < numberColumns; i++) {
6060 if (model2->getStatus(i) == basic) {
6061 dj[i] = 0.0;
6062 } else if (model2->getStatus(i) == atLowerBound) {
6063 if (optimizationDirection_ * dj[i] < tolerance) {
6064 if (optimizationDirection_ * dj[i] < 0.0) {
6065 //if (dj[i]<-1.0e-3)
6066 //printf("bad dj at lb %d %g\n",i,dj[i]);
6067 cost[i] -= dj[i];
6068 dj[i] = 0.0;
6069 }
6070 } else {
6071 upper[i] = lower[i];
6072 }
6073 } else if (model2->getStatus(i) == atUpperBound) {
6074 if (optimizationDirection_ * dj[i] > tolerance) {
6075 if (optimizationDirection_ * dj[i] > 0.0) {
6076 //if (dj[i]>1.0e-3)
6077 //printf("bad dj at ub %d %g\n",i,dj[i]);
6078 cost[i] -= dj[i];
6079 dj[i] = 0.0;
6080 }
6081 } else {
6082 lower[i] = upper[i];
6083 }
6084 }
6085 }
6086 // just dual values pass
6087 //model2->setLogLevel(63);
6088 //model2->setFactorizationFrequency(1);
6089 model2->dual(2);
6090 CoinMemcpyN(saveCost, numberColumns, cost);
6091 delete [] saveCost;
6092 CoinMemcpyN(saveLower, numberColumns, lower);
6093 delete [] saveLower;
6094 CoinMemcpyN(saveUpper, numberColumns, upper);
6095 delete [] saveUpper;
6096 }
6097 // and finish
6098 // move solutions
6099 CoinMemcpyN(rowPrimal,
6100 numberRows, model2->primalRowSolution());
6101 CoinMemcpyN(columnPrimal,
6102 numberColumns, model2->primalColumnSolution());
6103 }
6104// double saveScale = model2->objectiveScale();
6105// model2->setObjectiveScale(1.0e-3);
6106// model2->primal(2);
6107// model2->setObjectiveScale(saveScale);
6108 model2->primal(1);
6109 } else if (barrierStatus == 4 && crossover) {
6110 // memory problems
6111 model2->setPerturbation(savePerturbation);
6112 model2->createStatus();
6113 model2->dual();
6114 }
6115 model2->setMaximumIterations(saveMaxIts);
6116 delete [] rowPrimal;
6117 delete [] columnPrimal;
6118 delete [] rowDual;
6119 delete [] columnDual;
6120 if (saveLower) {
6121 pinfo2.postsolve(true);
6122 delete model2;
6123 model2 = saveModel2;
6124 int numberRows = model2->numberRows();
6125 int numberColumns = model2->numberColumns();
6126 CoinMemcpyN(saveLower, numberColumns, model2->columnLower());
6127 CoinMemcpyN(saveLower + numberColumns, numberRows, model2->rowLower());
6128 delete [] saveLower;
6129 CoinMemcpyN(saveUpper, numberColumns, model2->columnUpper());
6130 CoinMemcpyN(saveUpper + numberColumns, numberRows, model2->rowUpper());
6131 delete [] saveUpper;
6132 model2->primal(1);
6133 }
6134 model2->setPerturbation(savePerturbation);
6135 return model2->status();
6136}
6137/* For strong branching. On input lower and upper are new bounds
6138 while on output they are objective function values (>1.0e50 infeasible).
6139 Return code is 0 if nothing interesting, -1 if infeasible both
6140 ways and +1 if infeasible one way (check values to see which one(s))
6141*/
6142int ClpSimplex::strongBranching(int numberVariables, const int * variables,
6143 double * newLower, double * newUpper,
6144 double ** outputSolution,
6145 int * outputStatus, int * outputIterations,
6146 bool stopOnFirstInfeasible,
6147 bool alwaysFinish,
6148 int startFinishOptions)
6149{
6150 return static_cast<ClpSimplexDual *> (this)->strongBranching(numberVariables, variables,
6151 newLower, newUpper, outputSolution,
6152 outputStatus, outputIterations,
6153 stopOnFirstInfeasible,
6154 alwaysFinish, startFinishOptions);
6155}
6156#endif
6157/* Borrow model. This is so we dont have to copy large amounts
6158 of data around. It assumes a derived class wants to overwrite
6159 an empty model with a real one - while it does an algorithm.
6160 This is same as ClpModel one, but sets scaling on etc. */
6161void
6162ClpSimplex::borrowModel(ClpModel & otherModel)
6163{
6164 ClpModel::borrowModel(otherModel);
6165 createStatus();
6166 //ClpDualRowSteepest steep1;
6167 //setDualRowPivotAlgorithm(steep1);
6168 //ClpPrimalColumnSteepest steep2;
6169 //setPrimalColumnPivotAlgorithm(steep2);
6170}
6171void
6172ClpSimplex::borrowModel(ClpSimplex & otherModel)
6173{
6174 ClpModel::borrowModel(otherModel);
6175 createStatus();
6176 dualBound_ = otherModel.dualBound_;
6177 dualTolerance_ = otherModel.dualTolerance_;
6178 primalTolerance_ = otherModel.primalTolerance_;
6179 delete dualRowPivot_;
6180 dualRowPivot_ = otherModel.dualRowPivot_->clone(true);
6181 dualRowPivot_->setModel(this);
6182 delete primalColumnPivot_;
6183 primalColumnPivot_ = otherModel.primalColumnPivot_->clone(true);
6184 primalColumnPivot_->setModel(this);
6185 perturbation_ = otherModel.perturbation_;
6186 moreSpecialOptions_ = otherModel.moreSpecialOptions_;
6187 automaticScale_ = otherModel.automaticScale_;
6188 maximumPerturbationSize_ = otherModel.maximumPerturbationSize_;
6189 perturbationArray_ = otherModel.perturbationArray_;
6190}
6191/// Saves scalars for ClpSimplex
6192typedef struct {
6193 double optimizationDirection;
6194 double dblParam[ClpLastDblParam];
6195 double objectiveValue;
6196 double dualBound;
6197 double dualTolerance;
6198 double primalTolerance;
6199 double sumDualInfeasibilities;
6200 double sumPrimalInfeasibilities;
6201 double infeasibilityCost;
6202 int numberRows;
6203 int numberColumns;
6204 int intParam[ClpLastIntParam];
6205 int numberIterations;
6206 int problemStatus;
6207 int maximumIterations;
6208 int lengthNames;
6209 int numberDualInfeasibilities;
6210 int numberDualInfeasibilitiesWithoutFree;
6211 int numberPrimalInfeasibilities;
6212 int numberRefinements;
6213 int scalingFlag;
6214 int algorithm;
6215 unsigned int specialOptions;
6216 int dualPivotChoice;
6217 int primalPivotChoice;
6218 int matrixStorageChoice;
6219} Clp_scalars;
6220#ifndef SLIM_NOIO
6221int outDoubleArray(double * array, int length, FILE * fp)
6222{
6223 size_t numberWritten;
6224 if (array && length) {
6225 numberWritten = fwrite(&length, sizeof(int), 1, fp);
6226 if (numberWritten != 1)
6227 return 1;
6228 numberWritten = fwrite(array, sizeof(double), length, fp);
6229 if (numberWritten != static_cast<size_t>(length))
6230 return 1;
6231 } else {
6232 length = 0;
6233 numberWritten = fwrite(&length, sizeof(int), 1, fp);
6234 if (numberWritten != 1)
6235 return 1;
6236 }
6237 return 0;
6238}
6239// Save model to file, returns 0 if success
6240int
6241ClpSimplex::saveModel(const char * fileName)
6242{
6243 FILE * fp = fopen(fileName, "wb");
6244 if (fp) {
6245 Clp_scalars scalars;
6246 size_t numberWritten;
6247 // Fill in scalars
6248 scalars.optimizationDirection = optimizationDirection_;
6249 CoinMemcpyN( dblParam_, ClpLastDblParam, scalars.dblParam);
6250 scalars.objectiveValue = objectiveValue_;
6251 scalars.dualBound = dualBound_;
6252 scalars.dualTolerance = dualTolerance_;
6253 scalars.primalTolerance = primalTolerance_;
6254 scalars.sumDualInfeasibilities = sumDualInfeasibilities_;
6255 scalars.sumPrimalInfeasibilities = sumPrimalInfeasibilities_;
6256 scalars.infeasibilityCost = infeasibilityCost_;
6257 scalars.numberRows = numberRows_;
6258 scalars.numberColumns = numberColumns_;
6259 CoinMemcpyN( intParam_, ClpLastIntParam, scalars.intParam);
6260 scalars.numberIterations = numberIterations_;
6261 scalars.problemStatus = problemStatus_;
6262 scalars.maximumIterations = maximumIterations();
6263 scalars.lengthNames = lengthNames_;
6264 scalars.numberDualInfeasibilities = numberDualInfeasibilities_;
6265 scalars.numberDualInfeasibilitiesWithoutFree
6266 = numberDualInfeasibilitiesWithoutFree_;
6267 scalars.numberPrimalInfeasibilities = numberPrimalInfeasibilities_;
6268 scalars.numberRefinements = numberRefinements_;
6269 scalars.scalingFlag = scalingFlag_;
6270 scalars.algorithm = algorithm_;
6271 scalars.specialOptions = specialOptions_;
6272 scalars.dualPivotChoice = dualRowPivot_->type();
6273 scalars.primalPivotChoice = primalColumnPivot_->type();
6274 scalars.matrixStorageChoice = matrix_->type();
6275
6276 // put out scalars
6277 numberWritten = fwrite(&scalars, sizeof(Clp_scalars), 1, fp);
6278 if (numberWritten != 1)
6279 return 1;
6280 size_t length;
6281#ifndef CLP_NO_STD
6282 int i;
6283 // strings
6284 for (i = 0; i < ClpLastStrParam; i++) {
6285 length = strParam_[i].size();
6286 numberWritten = fwrite(&length, sizeof(int), 1, fp);
6287 if (numberWritten != 1)
6288 return 1;
6289 if (length) {
6290 numberWritten = fwrite(strParam_[i].c_str(), length, 1, fp);
6291 if (numberWritten != 1)
6292 return 1;
6293 }
6294 }
6295#endif
6296 // arrays - in no particular order
6297 if (outDoubleArray(rowActivity_, numberRows_, fp))
6298 return 1;
6299 if (outDoubleArray(columnActivity_, numberColumns_, fp))
6300 return 1;
6301 if (outDoubleArray(dual_, numberRows_, fp))
6302 return 1;
6303 if (outDoubleArray(reducedCost_, numberColumns_, fp))
6304 return 1;
6305 if (outDoubleArray(rowLower_, numberRows_, fp))
6306 return 1;
6307 if (outDoubleArray(rowUpper_, numberRows_, fp))
6308 return 1;
6309 if (outDoubleArray(objective(), numberColumns_, fp))
6310 return 1;
6311 if (outDoubleArray(rowObjective_, numberRows_, fp))
6312 return 1;
6313 if (outDoubleArray(columnLower_, numberColumns_, fp))
6314 return 1;
6315 if (outDoubleArray(columnUpper_, numberColumns_, fp))
6316 return 1;
6317 if (ray_) {
6318 if (problemStatus_ == 1) {
6319 if (outDoubleArray(ray_, numberRows_, fp))
6320 return 1;
6321 } else if (problemStatus_ == 2) {
6322 if (outDoubleArray(ray_, numberColumns_, fp))
6323 return 1;
6324 } else {
6325 if (outDoubleArray(NULL, 0, fp))
6326 return 1;
6327 }
6328 } else {
6329 if (outDoubleArray(NULL, 0, fp))
6330 return 1;
6331 }
6332 if (status_ && (numberRows_ + numberColumns_) > 0) {
6333 length = numberRows_ + numberColumns_;
6334 numberWritten = fwrite(&length, sizeof(int), 1, fp);
6335 if (numberWritten != 1)
6336 return 1;
6337 numberWritten = fwrite(status_, sizeof(char), length, fp);
6338 if (numberWritten != length)
6339 return 1;
6340 } else {
6341 length = 0;
6342 numberWritten = fwrite(&length, sizeof(int), 1, fp);
6343 if (numberWritten != 1)
6344 return 1;
6345 }
6346#ifndef CLP_NO_STD
6347 if (lengthNames_) {
6348 char * array =
6349 new char[CoinMax(numberRows_, numberColumns_)*(lengthNames_+1)];
6350 char * put = array;
6351 CoinAssert (numberRows_ == static_cast<int> (rowNames_.size()));
6352 for (i = 0; i < numberRows_; i++) {
6353 assert(static_cast<int>(rowNames_[i].size()) <= lengthNames_);
6354 strcpy(put, rowNames_[i].c_str());
6355 put += lengthNames_ + 1;
6356 }
6357 numberWritten = fwrite(array, lengthNames_ + 1, numberRows_, fp);
6358 if (numberWritten != static_cast<size_t>(numberRows_))
6359 return 1;
6360 put = array;
6361 CoinAssert (numberColumns_ == static_cast<int> (columnNames_.size()));
6362 for (i = 0; i < numberColumns_; i++) {
6363 assert(static_cast<int> (columnNames_[i].size()) <= lengthNames_);
6364 strcpy(put, columnNames_[i].c_str());
6365 put += lengthNames_ + 1;
6366 }
6367 numberWritten = fwrite(array, lengthNames_ + 1, numberColumns_, fp);
6368 if (numberWritten != static_cast<size_t>(numberColumns_))
6369 return 1;
6370 delete [] array;
6371 }
6372#endif
6373 // integers
6374 if (integerType_) {
6375 int marker = 1;
6376 numberWritten = fwrite(&marker, sizeof(int), 1, fp);
6377 numberWritten = fwrite(integerType_, 1, numberColumns_, fp);
6378 if (numberWritten != static_cast<size_t>(numberColumns_))
6379 return 1;
6380 } else {
6381 int marker = 0;
6382 numberWritten = fwrite(&marker, sizeof(int), 1, fp);
6383 }
6384 // just standard type at present
6385 assert (matrix_->type() == 1);
6386 CoinAssert (matrix_->getNumCols() == numberColumns_);
6387 CoinAssert (matrix_->getNumRows() == numberRows_);
6388 // we are going to save with gaps
6389 length = matrix_->getVectorStarts()[numberColumns_-1]
6390 + matrix_->getVectorLengths()[numberColumns_-1];
6391 numberWritten = fwrite(&length, sizeof(int), 1, fp);
6392 if (numberWritten != 1)
6393 return 1;
6394 numberWritten = fwrite(matrix_->getElements(),
6395 sizeof(double), length, fp);
6396 if (numberWritten != length)
6397 return 1;
6398 numberWritten = fwrite(matrix_->getIndices(),
6399 sizeof(int), length, fp);
6400 if (numberWritten != length)
6401 return 1;
6402 numberWritten = fwrite(matrix_->getVectorStarts(),
6403 sizeof(int), numberColumns_ + 1, fp);
6404 if (numberWritten != static_cast<size_t>(numberColumns_) + 1)
6405 return 1;
6406 numberWritten = fwrite(matrix_->getVectorLengths(),
6407 sizeof(int), numberColumns_, fp);
6408 if (numberWritten != static_cast<size_t>(numberColumns_))
6409 return 1;
6410 // finished
6411 fclose(fp);
6412 return 0;
6413 } else {
6414 return -1;
6415 }
6416}
6417
6418int inDoubleArray(double * &array, int length, FILE * fp)
6419{
6420 size_t numberRead;
6421 int length2;
6422 numberRead = fread(&length2, sizeof(int), 1, fp);
6423 if (numberRead != 1)
6424 return 1;
6425 if (length2) {
6426 // lengths must match
6427 if (length != length2)
6428 return 2;
6429 array = new double[length];
6430 numberRead = fread(array, sizeof(double), length, fp);
6431 if (numberRead != static_cast<size_t>(length))
6432 return 1;
6433 }
6434 return 0;
6435}
6436/* Restore model from file, returns 0 if success,
6437 deletes current model */
6438int
6439ClpSimplex::restoreModel(const char * fileName)
6440{
6441 FILE * fp = fopen(fileName, "rb");
6442 if (fp) {
6443 // Get rid of current model
6444 // save event handler in case already set
6445 ClpEventHandler * handler = eventHandler_->clone();
6446 ClpModel::gutsOfDelete(0);
6447 eventHandler_ = handler;
6448 gutsOfDelete(0);
6449 int i;
6450 for (i = 0; i < 6; i++) {
6451 rowArray_[i] = NULL;
6452 columnArray_[i] = NULL;
6453 }
6454 // get an empty factorization so we can set tolerances etc
6455 getEmptyFactorization();
6456 // Say sparse
6457 factorization_->sparseThreshold(1);
6458 Clp_scalars scalars;
6459 size_t numberRead;
6460
6461 // get scalars
6462 numberRead = fread(&scalars, sizeof(Clp_scalars), 1, fp);
6463 if (numberRead != 1)
6464 return 1;
6465 // Fill in scalars
6466 optimizationDirection_ = scalars.optimizationDirection;
6467 CoinMemcpyN( scalars.dblParam, ClpLastDblParam, dblParam_);
6468 objectiveValue_ = scalars.objectiveValue;
6469 dualBound_ = scalars.dualBound;
6470 dualTolerance_ = scalars.dualTolerance;
6471 primalTolerance_ = scalars.primalTolerance;
6472 sumDualInfeasibilities_ = scalars.sumDualInfeasibilities;
6473 sumPrimalInfeasibilities_ = scalars.sumPrimalInfeasibilities;
6474 infeasibilityCost_ = scalars.infeasibilityCost;
6475 numberRows_ = scalars.numberRows;
6476 numberColumns_ = scalars.numberColumns;
6477 CoinMemcpyN( scalars.intParam, ClpLastIntParam, intParam_);
6478 numberIterations_ = scalars.numberIterations;
6479 problemStatus_ = scalars.problemStatus;
6480 setMaximumIterations(scalars.maximumIterations);
6481 lengthNames_ = scalars.lengthNames;
6482 numberDualInfeasibilities_ = scalars.numberDualInfeasibilities;
6483 numberDualInfeasibilitiesWithoutFree_
6484 = scalars.numberDualInfeasibilitiesWithoutFree;
6485 numberPrimalInfeasibilities_ = scalars.numberPrimalInfeasibilities;
6486 numberRefinements_ = scalars.numberRefinements;
6487 scalingFlag_ = scalars.scalingFlag;
6488 algorithm_ = scalars.algorithm;
6489 specialOptions_ = scalars.specialOptions;
6490 // strings
6491 CoinBigIndex length;
6492#ifndef CLP_NO_STD
6493 for (i = 0; i < ClpLastStrParam; i++) {
6494 numberRead = fread(&length, sizeof(int), 1, fp);
6495 if (numberRead != 1)
6496 return 1;
6497 if (length) {
6498 char * array = new char[length+1];
6499 numberRead = fread(array, length, 1, fp);
6500 if (numberRead != 1)
6501 return 1;
6502 array[length] = '\0';
6503 strParam_[i] = array;
6504 delete [] array;
6505 }
6506 }
6507#endif
6508 // arrays - in no particular order
6509 if (inDoubleArray(rowActivity_, numberRows_, fp))
6510 return 1;
6511 if (inDoubleArray(columnActivity_, numberColumns_, fp))
6512 return 1;
6513 if (inDoubleArray(dual_, numberRows_, fp))
6514 return 1;
6515 if (inDoubleArray(reducedCost_, numberColumns_, fp))
6516 return 1;
6517 if (inDoubleArray(rowLower_, numberRows_, fp))
6518 return 1;
6519 if (inDoubleArray(rowUpper_, numberRows_, fp))
6520 return 1;
6521 double * objective = NULL;
6522 if (inDoubleArray(objective, numberColumns_, fp))
6523 return 1;
6524 delete objective_;
6525 objective_ = new ClpLinearObjective(objective, numberColumns_);
6526 delete [] objective;
6527 if (inDoubleArray(rowObjective_, numberRows_, fp))
6528 return 1;
6529 if (inDoubleArray(columnLower_, numberColumns_, fp))
6530 return 1;
6531 if (inDoubleArray(columnUpper_, numberColumns_, fp))
6532 return 1;
6533 if (problemStatus_ == 1) {
6534 if (inDoubleArray(ray_, numberRows_, fp))
6535 return 1;
6536 } else if (problemStatus_ == 2) {
6537 if (inDoubleArray(ray_, numberColumns_, fp))
6538 return 1;
6539 } else {
6540 // ray should be null
6541 numberRead = fread(&length, sizeof(int), 1, fp);
6542 if (numberRead != 1)
6543 return 1;
6544 if (length)
6545 return 2;
6546 }
6547 delete [] status_;
6548 status_ = NULL;
6549 // status region
6550 numberRead = fread(&length, sizeof(int), 1, fp);
6551 if (numberRead != 1)
6552 return 1;
6553 if (length) {
6554 if (length != numberRows_ + numberColumns_)
6555 return 1;
6556 status_ = new char unsigned[length];
6557 numberRead = fread(status_, sizeof(char), length, fp);
6558 if (numberRead != static_cast<size_t>(length))
6559 return 1;
6560 }
6561#ifndef CLP_NO_STD
6562 if (lengthNames_) {
6563 char * array =
6564 new char[CoinMax(numberRows_, numberColumns_)*(lengthNames_+1)];
6565 char * get = array;
6566 numberRead = fread(array, lengthNames_ + 1, numberRows_, fp);
6567 if (numberRead != static_cast<size_t>(numberRows_))
6568 return 1;
6569 rowNames_ = std::vector<std::string> ();
6570 rowNames_.resize(numberRows_);
6571 for (i = 0; i < numberRows_; i++) {
6572 rowNames_.push_back(get);
6573 get += lengthNames_ + 1;
6574 }
6575 get = array;
6576 numberRead = fread(array, lengthNames_ + 1, numberColumns_, fp);
6577 if (numberRead != static_cast<size_t>(numberColumns_))
6578 return 1;
6579 columnNames_ = std::vector<std::string> ();
6580 columnNames_.resize(numberColumns_);
6581 for (i = 0; i < numberColumns_; i++) {
6582 columnNames_.push_back(get);
6583 get += lengthNames_ + 1;
6584 }
6585 delete [] array;
6586 }
6587#endif
6588 // integers
6589 int ifInteger;
6590 delete [] integerType_;
6591 numberRead = fread(&ifInteger, sizeof(int), 1, fp);
6592 // But try and stay compatible with previous version
6593 bool alreadyGotLength = false;
6594 if (numberRead != 1)
6595 return 1;
6596 if (ifInteger == 1) {
6597 integerType_ = new char [numberColumns_];
6598 numberRead = fread(integerType_, 1, numberColumns_, fp);
6599 if (numberRead != static_cast<size_t>(numberColumns_))
6600 return 1;
6601 } else {
6602 integerType_ = NULL;
6603 if (ifInteger) {
6604 // probably old style save
6605 alreadyGotLength = true;
6606 length = ifInteger;
6607 }
6608 }
6609 // Pivot choices
6610 assert(scalars.dualPivotChoice > 0 && (scalars.dualPivotChoice & 63) < 3);
6611 delete dualRowPivot_;
6612 switch ((scalars.dualPivotChoice & 63)) {
6613 default:
6614 printf("Need another dualPivot case %d\n", scalars.dualPivotChoice & 63);
6615 case 1:
6616 // Dantzig
6617 dualRowPivot_ = new ClpDualRowDantzig();
6618 break;
6619 case 2:
6620 // Steepest - use mode
6621 dualRowPivot_ = new ClpDualRowSteepest(scalars.dualPivotChoice >> 6);
6622 break;
6623 }
6624 assert(scalars.primalPivotChoice > 0 && (scalars.primalPivotChoice & 63) < 3);
6625 delete primalColumnPivot_;
6626 switch ((scalars.primalPivotChoice & 63)) {
6627 default:
6628 printf("Need another primalPivot case %d\n",
6629 scalars.primalPivotChoice & 63);
6630 case 1:
6631 // Dantzig
6632 primalColumnPivot_ = new ClpPrimalColumnDantzig();
6633 break;
6634 case 2:
6635 // Steepest - use mode
6636 primalColumnPivot_
6637 = new ClpPrimalColumnSteepest(scalars.primalPivotChoice >> 6);
6638 break;
6639 }
6640 assert(scalars.matrixStorageChoice == 1);
6641 delete matrix_;
6642 // get arrays
6643 if (!alreadyGotLength) {
6644 numberRead = fread(&length, sizeof(int), 1, fp);
6645 if (numberRead != 1)
6646 return 1;
6647 }
6648 double * elements = new double[length];
6649 int * indices = new int[length];
6650 CoinBigIndex * starts = new CoinBigIndex[numberColumns_+1];
6651 int * lengths = new int[numberColumns_];
6652 numberRead = fread(elements, sizeof(double), length, fp);
6653 if (numberRead != static_cast<size_t>(length))
6654 return 1;
6655 numberRead = fread(indices, sizeof(int), length, fp);
6656 if (numberRead != static_cast<size_t>(length))
6657 return 1;
6658 numberRead = fread(starts, sizeof(int), numberColumns_ + 1, fp);
6659 if (numberRead != static_cast<size_t>(numberColumns_) + 1)
6660 return 1;
6661 numberRead = fread(lengths, sizeof(int), numberColumns_, fp);
6662 if (numberRead != static_cast<size_t>(numberColumns_))
6663 return 1;
6664 // assign matrix
6665 CoinPackedMatrix * matrix = new CoinPackedMatrix();
6666 matrix->setExtraGap(0.0);
6667 matrix->setExtraMajor(0.0);
6668 // Pack down
6669 length = 0;
6670 for (i = 0; i < numberColumns_; i++) {
6671 int start = starts[i];
6672 starts[i] = length;
6673 for (CoinBigIndex j = start; j < start + lengths[i]; j++) {
6674 elements[length] = elements[j];
6675 indices[length++] = indices[j];
6676 }
6677 lengths[i] = length - starts[i];
6678 }
6679 starts[numberColumns_] = length;
6680 matrix->assignMatrix(true, numberRows_, numberColumns_,
6681 length, elements, indices, starts, lengths);
6682 // and transfer to Clp
6683 matrix_ = new ClpPackedMatrix(matrix);
6684 // finished
6685 fclose(fp);
6686 return 0;
6687 } else {
6688 return -1;
6689 }
6690 return 0;
6691}
6692#endif
6693// value of incoming variable (in Dual)
6694double
6695ClpSimplex::valueIncomingDual() const
6696{
6697 // Need value of incoming for list of infeasibilities as may be infeasible
6698 double valueIncoming = (dualOut_ / alpha_) * directionOut_;
6699 if (directionIn_ == -1)
6700 valueIncoming = upperIn_ - valueIncoming;
6701 else
6702 valueIncoming = lowerIn_ - valueIncoming;
6703 return valueIncoming;
6704}
6705// Sanity check on input data - returns true if okay
6706bool
6707ClpSimplex::sanityCheck()
6708{
6709 // bad if empty
6710 if (!numberColumns_ || ((!numberRows_ || !matrix_->getNumElements()) && objective_->type() < 2)) {
6711 int infeasNumber[2];
6712 double infeasSum[2];
6713 problemStatus_ = emptyProblem(infeasNumber, infeasSum, false);
6714 numberDualInfeasibilities_ = infeasNumber[0];
6715 sumDualInfeasibilities_ = infeasSum[0];
6716 numberPrimalInfeasibilities_ = infeasNumber[1];
6717 sumPrimalInfeasibilities_ = infeasSum[1];
6718 return false;
6719 }
6720 int numberBad ;
6721 double largestBound, smallestBound, minimumGap;
6722 double smallestObj, largestObj;
6723 int firstBad;
6724 int modifiedBounds = 0;
6725 int i;
6726 numberBad = 0;
6727 firstBad = -1;
6728 minimumGap = 1.0e100;
6729 smallestBound = 1.0e100;
6730 largestBound = 0.0;
6731 smallestObj = 1.0e100;
6732 largestObj = 0.0;
6733 // If bounds are too close - fix
6734 double fixTolerance = primalTolerance_;
6735 if (fixTolerance < 2.0e-8)
6736 fixTolerance *= 1.1;
6737 for (i = numberColumns_; i < numberColumns_ + numberRows_; i++) {
6738 double value;
6739 value = fabs(cost_[i]);
6740 if (value > 1.0e50) {
6741 numberBad++;
6742 if (firstBad < 0)
6743 firstBad = i;
6744 } else if (value) {
6745 if (value > largestObj)
6746 largestObj = value;
6747 if (value < smallestObj)
6748 smallestObj = value;
6749 }
6750 value = upper_[i] - lower_[i];
6751 if (value < -primalTolerance_) {
6752 numberBad++;
6753 if (firstBad < 0)
6754 firstBad = i;
6755 } else if (value <= fixTolerance) {
6756 if (value) {
6757 // modify
6758 upper_[i] = lower_[i];
6759 modifiedBounds++;
6760 }
6761 } else {
6762 if (value < minimumGap)
6763 minimumGap = value;
6764 }
6765 if (lower_[i] > -1.0e100 && lower_[i]) {
6766 value = fabs(lower_[i]);
6767 if (value > largestBound)
6768 largestBound = value;
6769 if (value < smallestBound)
6770 smallestBound = value;
6771 }
6772 if (upper_[i] < 1.0e100 && upper_[i]) {
6773 value = fabs(upper_[i]);
6774 if (value > largestBound)
6775 largestBound = value;
6776 if (value < smallestBound)
6777 smallestBound = value;
6778 }
6779 }
6780 if (largestBound)
6781 handler_->message(CLP_RIMSTATISTICS3, messages_)
6782 << smallestBound
6783 << largestBound
6784 << minimumGap
6785 << CoinMessageEol;
6786 minimumGap = 1.0e100;
6787 smallestBound = 1.0e100;
6788 largestBound = 0.0;
6789 for (i = 0; i < numberColumns_; i++) {
6790 double value;
6791 value = fabs(cost_[i]);
6792 if (value > 1.0e50) {
6793 numberBad++;
6794 if (firstBad < 0)
6795 firstBad = i;
6796 } else if (value) {
6797 if (value > largestObj)
6798 largestObj = value;
6799 if (value < smallestObj)
6800 smallestObj = value;
6801 }
6802 value = upper_[i] - lower_[i];
6803 if (value < -primalTolerance_) {
6804 numberBad++;
6805 if (firstBad < 0)
6806 firstBad = i;
6807 } else if (value <= fixTolerance) {
6808 if (value) {
6809 // modify
6810 upper_[i] = lower_[i];
6811 modifiedBounds++;
6812 }
6813 } else {
6814 if (value < minimumGap)
6815 minimumGap = value;
6816 }
6817 if (lower_[i] > -1.0e100 && lower_[i]) {
6818 value = fabs(lower_[i]);
6819 if (value > largestBound)
6820 largestBound = value;
6821 if (value < smallestBound)
6822 smallestBound = value;
6823 }
6824 if (upper_[i] < 1.0e100 && upper_[i]) {
6825 value = fabs(upper_[i]);
6826 if (value > largestBound)
6827 largestBound = value;
6828 if (value < smallestBound)
6829 smallestBound = value;
6830 }
6831 }
6832 char rowcol[] = {'R', 'C'};
6833 if (numberBad) {
6834 handler_->message(CLP_BAD_BOUNDS, messages_)
6835 << numberBad
6836 << rowcol[isColumn(firstBad)] << sequenceWithin(firstBad)
6837 << CoinMessageEol;
6838 problemStatus_ = 4;
6839 return false;
6840 }
6841 if (modifiedBounds)
6842 handler_->message(CLP_MODIFIEDBOUNDS, messages_)
6843 << modifiedBounds
6844 << CoinMessageEol;
6845 handler_->message(CLP_RIMSTATISTICS1, messages_)
6846 << smallestObj
6847 << largestObj
6848 << CoinMessageEol;
6849 if (largestBound)
6850 handler_->message(CLP_RIMSTATISTICS2, messages_)
6851 << smallestBound
6852 << largestBound
6853 << minimumGap
6854 << CoinMessageEol;
6855 return true;
6856}
6857// Set up status array (for OsiClp)
6858void
6859ClpSimplex::createStatus()
6860{
6861 if(!status_)
6862 status_ = new unsigned char [numberColumns_+numberRows_];
6863 memset(status_, 0, (numberColumns_ + numberRows_)*sizeof(char));
6864 int i;
6865 // set column status to one nearest zero
6866 for (i = 0; i < numberColumns_; i++) {
6867#if 0
6868 if (columnLower_[i] >= 0.0) {
6869 setColumnStatus(i, atLowerBound);
6870 } else if (columnUpper_[i] <= 0.0) {
6871 setColumnStatus(i, atUpperBound);
6872 } else if (columnLower_[i] < -1.0e20 && columnUpper_[i] > 1.0e20) {
6873 // free
6874 setColumnStatus(i, isFree);
6875 } else if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
6876 setColumnStatus(i, atLowerBound);
6877 } else {
6878 setColumnStatus(i, atUpperBound);
6879 }
6880#else
6881 setColumnStatus(i, atLowerBound);
6882#endif
6883 }
6884 for (i = 0; i < numberRows_; i++) {
6885 setRowStatus(i, basic);
6886 }
6887}
6888/* Sets up all slack basis and resets solution to
6889 as it was after initial load or readMps */
6890void ClpSimplex::allSlackBasis(bool resetSolution)
6891{
6892 createStatus();
6893 if (resetSolution) {
6894 // put back to as it was originally
6895 int i;
6896 // set column status to one nearest zero
6897 // But set value to zero if lb <0.0 and ub>0.0
6898 for (i = 0; i < numberColumns_; i++) {
6899 if (columnLower_[i] >= 0.0) {
6900 columnActivity_[i] = columnLower_[i];
6901 setColumnStatus(i, atLowerBound);
6902 } else if (columnUpper_[i] <= 0.0) {
6903 columnActivity_[i] = columnUpper_[i];
6904 setColumnStatus(i, atUpperBound);
6905 } else if (columnLower_[i] < -1.0e20 && columnUpper_[i] > 1.0e20) {
6906 // free
6907 columnActivity_[i] = 0.0;
6908 setColumnStatus(i, isFree);
6909 } else if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
6910 columnActivity_[i] = 0.0;
6911 setColumnStatus(i, atLowerBound);
6912 } else {
6913 columnActivity_[i] = 0.0;
6914 setColumnStatus(i, atUpperBound);
6915 }
6916 }
6917 if (solution_) {
6918 // do that as well
6919 if (!columnScale_) {
6920 for (i = 0; i < numberColumns_; i++) {
6921 solution_[i] = columnActivity_[i];
6922 }
6923 } else {
6924 double * inverseColumnScale = columnScale_ + numberColumns_;
6925 for (i = 0; i < numberColumns_; i++) {
6926 solution_[i] = columnActivity_[i] * (rhsScale_ * inverseColumnScale[i]);
6927 }
6928 }
6929 }
6930 }
6931}
6932/* Loads a problem (the constraints on the
6933 rows are given by lower and upper bounds). If a pointer is 0 then the
6934 following values are the default:
6935 <ul>
6936 <li> <code>colub</code>: all columns have upper bound infinity
6937 <li> <code>collb</code>: all columns have lower bound 0
6938 <li> <code>rowub</code>: all rows have upper bound infinity
6939 <li> <code>rowlb</code>: all rows have lower bound -infinity
6940 <li> <code>obj</code>: all variables have 0 objective coefficient
6941 </ul>
6942*/
6943void
6944ClpSimplex::loadProblem ( const ClpMatrixBase& matrix,
6945 const double* collb, const double* colub,
6946 const double* obj,
6947 const double* rowlb, const double* rowub,
6948 const double * rowObjective)
6949{
6950 ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub,
6951 rowObjective);
6952 createStatus();
6953}
6954void
6955ClpSimplex::loadProblem ( const CoinPackedMatrix& matrix,
6956 const double* collb, const double* colub,
6957 const double* obj,
6958 const double* rowlb, const double* rowub,
6959 const double * rowObjective)
6960{
6961 ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub,
6962 rowObjective);
6963 createStatus();
6964}
6965
6966/* Just like the other loadProblem() method except that the matrix is
6967 given in a standard column major ordered format (without gaps). */
6968void
6969ClpSimplex::loadProblem ( const int numcols, const int numrows,
6970 const CoinBigIndex* start, const int* index,
6971 const double* value,
6972 const double* collb, const double* colub,
6973 const double* obj,
6974 const double* rowlb, const double* rowub,
6975 const double * rowObjective)
6976{
6977 ClpModel::loadProblem(numcols, numrows, start, index, value,
6978 collb, colub, obj, rowlb, rowub,
6979 rowObjective);
6980 createStatus();
6981}
6982#ifndef SLIM_NOIO
6983// This loads a model from a coinModel object - returns number of errors
6984int
6985ClpSimplex::loadProblem ( CoinModel & modelObject, bool /*keepSolution*/)
6986{
6987 unsigned char * status = NULL;
6988 double * psol = NULL;
6989 double * dsol = NULL;
6990 if (status_ && numberRows_ && numberRows_ == modelObject.numberRows() &&
6991 numberColumns_ == modelObject.numberColumns()) {
6992 status = new unsigned char [numberRows_+numberColumns_];
6993 CoinMemcpyN(status_, numberRows_ + numberColumns_, status);
6994 psol = new double [numberRows_+numberColumns_];
6995 CoinMemcpyN(columnActivity_, numberColumns_, psol);
6996 CoinMemcpyN(rowActivity_, numberRows_, psol + numberColumns_);
6997 dsol = new double [numberRows_+numberColumns_];
6998 CoinMemcpyN(reducedCost_, numberColumns_, dsol);
6999 CoinMemcpyN(dual_, numberRows_, dsol + numberColumns_);
7000 }
7001 int returnCode = ClpModel::loadProblem(modelObject);
7002 const int * integerType = modelObject.integerTypeArray();
7003 if (integerType) {
7004 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
7005 if (integerType[iColumn])
7006 setInteger(iColumn);
7007 }
7008 }
7009 createStatus();
7010 if (status) {
7011 // copy back
7012 CoinMemcpyN(status, numberRows_ + numberColumns_, status_);
7013 CoinMemcpyN(psol, numberColumns_, columnActivity_);
7014 CoinMemcpyN(psol + numberColumns_, numberRows_, rowActivity_);
7015 CoinMemcpyN(dsol, numberColumns_, reducedCost_);
7016 CoinMemcpyN(dsol + numberColumns_, numberRows_, dual_);
7017 delete [] status;
7018 delete [] psol;
7019 delete [] dsol;
7020 }
7021 optimizationDirection_ = modelObject.optimizationDirection();
7022 return returnCode;
7023}
7024#endif
7025void
7026ClpSimplex::loadProblem ( const int numcols, const int numrows,
7027 const CoinBigIndex* start, const int* index,
7028 const double* value, const int * length,
7029 const double* collb, const double* colub,
7030 const double* obj,
7031 const double* rowlb, const double* rowub,
7032 const double * rowObjective)
7033{
7034 ClpModel::loadProblem(numcols, numrows, start, index, value, length,
7035 collb, colub, obj, rowlb, rowub,
7036 rowObjective);
7037 createStatus();
7038}
7039#ifndef SLIM_NOIO
7040// Read an mps file from the given filename
7041int
7042ClpSimplex::readMps(const char *filename,
7043 bool keepNames,
7044 bool ignoreErrors)
7045{
7046 int status = ClpModel::readMps(filename, keepNames, ignoreErrors);
7047 createStatus();
7048 return status;
7049}
7050// Read GMPL files from the given filenames
7051int
7052ClpSimplex::readGMPL(const char *filename, const char * dataName,
7053 bool keepNames)
7054{
7055 int status = ClpModel::readGMPL(filename, dataName, keepNames);
7056 createStatus();
7057 return status;
7058}
7059// Read file in LP format from file with name filename.
7060int
7061ClpSimplex::readLp(const char *filename, const double epsilon )
7062{
7063 FILE *fp = fopen(filename, "r");
7064
7065 if(!fp) {
7066 printf("### ERROR: ClpSimplex::readLp(): Unable to open file %s for reading\n",
7067 filename);
7068 return(1);
7069 }
7070 CoinLpIO m;
7071 m.readLp(fp, epsilon);
7072 fclose(fp);
7073
7074 // set problem name
7075 setStrParam(ClpProbName, m.getProblemName());
7076 // no errors
7077 loadProblem(*m.getMatrixByRow(), m.getColLower(), m.getColUpper(),
7078 m.getObjCoefficients(), m.getRowLower(), m.getRowUpper());
7079
7080 if (m.integerColumns()) {
7081 integerType_ = new char[numberColumns_];
7082 CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_);
7083 } else {
7084 integerType_ = NULL;
7085 }
7086 createStatus();
7087 unsigned int maxLength = 0;
7088 int iRow;
7089 rowNames_ = std::vector<std::string> ();
7090 columnNames_ = std::vector<std::string> ();
7091 rowNames_.reserve(numberRows_);
7092 for (iRow = 0; iRow < numberRows_; iRow++) {
7093 const char * name = m.rowName(iRow);
7094 if (name) {
7095 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
7096 rowNames_.push_back(name);
7097 } else {
7098 rowNames_.push_back("");
7099 }
7100 }
7101
7102 int iColumn;
7103 columnNames_.reserve(numberColumns_);
7104 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
7105 const char * name = m.columnName(iColumn);
7106 if (name) {
7107 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
7108 columnNames_.push_back(name);
7109 } else {
7110 columnNames_.push_back("");
7111 }
7112 }
7113 lengthNames_ = static_cast<int> (maxLength);
7114
7115 return 0;
7116}
7117#endif
7118// Just check solution (for external use)
7119void
7120ClpSimplex::checkSolution(int setToBounds)
7121{
7122 if (setToBounds) {
7123 // Set all ones that look at bounds to bounds
7124 bool changed = false;
7125 int i;
7126 for (i = 0; i < numberRows_; i++) {
7127 double newValue = 0.0;
7128 switch(getRowStatus(i)) {
7129
7130 case basic:
7131 newValue = rowActivity_[i];
7132 break;
7133 case atUpperBound:
7134 newValue = rowUpper_[i];
7135 if (newValue > largeValue_) {
7136 if (rowLower_[i] > -largeValue_) {
7137 newValue = rowLower_[i];
7138 setRowStatus(i, atLowerBound);
7139 } else {
7140 // say free
7141 setRowStatus(i, isFree);
7142 newValue = 0.0;
7143 }
7144 }
7145 break;
7146 case ClpSimplex::isFixed:
7147 case atLowerBound:
7148 newValue = rowLower_[i];
7149 if (newValue < -largeValue_) {
7150 if (rowUpper_[i] < largeValue_) {
7151 newValue = rowUpper_[i];
7152 setRowStatus(i, atUpperBound);
7153 } else {
7154 // say free
7155 setRowStatus(i, isFree);
7156 newValue = 0.0;
7157 }
7158 }
7159 break;
7160 case isFree:
7161 newValue = rowActivity_[i];
7162 break;
7163 // not really free - fall through to superbasic
7164 case superBasic:
7165 if (rowUpper_[i] > largeValue_) {
7166 if (rowLower_[i] > -largeValue_) {
7167 newValue = rowLower_[i];
7168 setRowStatus(i, atLowerBound);
7169 } else {
7170 // say free
7171 setRowStatus(i, isFree);
7172 newValue = 0.0;
7173 }
7174 } else {
7175 if (rowLower_[i] > -largeValue_) {
7176 // set to nearest
7177 if (fabs(newValue - rowLower_[i])
7178 < fabs(newValue - rowUpper_[i])) {
7179 newValue = rowLower_[i];
7180 setRowStatus(i, atLowerBound);
7181 } else {
7182 newValue = rowUpper_[i];
7183 setRowStatus(i, atUpperBound);
7184 }
7185 } else {
7186 newValue = rowUpper_[i];
7187 setRowStatus(i, atUpperBound);
7188 }
7189 }
7190 break;
7191 }
7192 if (fabs(newValue - rowActivity_[i]) > 1.0e-12) {
7193 changed = true;
7194 rowActivity_[i] = newValue;
7195 }
7196 }
7197 for (i = 0; i < numberColumns_; i++) {
7198 double newValue = 0.0;
7199 switch(getColumnStatus(i)) {
7200
7201 case basic:
7202 newValue = columnActivity_[i];
7203 break;
7204 case atUpperBound:
7205 newValue = columnUpper_[i];
7206 if (newValue > largeValue_) {
7207 if (columnLower_[i] > -largeValue_) {
7208 newValue = columnLower_[i];
7209 setColumnStatus(i, atLowerBound);
7210 } else {
7211 // say free
7212 setColumnStatus(i, isFree);
7213 newValue = 0.0;
7214 }
7215 }
7216 break;
7217 case ClpSimplex::isFixed:
7218 case atLowerBound:
7219 newValue = columnLower_[i];
7220 if (newValue < -largeValue_) {
7221 if (columnUpper_[i] < largeValue_) {
7222 newValue = columnUpper_[i];
7223 setColumnStatus(i, atUpperBound);
7224 } else {
7225 // say free
7226 setColumnStatus(i, isFree);
7227 newValue = 0.0;
7228 }
7229 }
7230 break;
7231 case isFree:
7232 newValue = columnActivity_[i];
7233 break;
7234 // not really free - fall through to superbasic
7235 case superBasic:
7236 if (columnUpper_[i] > largeValue_) {
7237 if (columnLower_[i] > -largeValue_) {
7238 newValue = columnLower_[i];
7239 setColumnStatus(i, atLowerBound);
7240 } else {
7241 // say free
7242 setColumnStatus(i, isFree);
7243 newValue = 0.0;
7244 }
7245 } else {
7246 if (columnLower_[i] > -largeValue_) {
7247 // set to nearest
7248 if (fabs(newValue - columnLower_[i])
7249 < fabs(newValue - columnUpper_[i])) {
7250 newValue = columnLower_[i];
7251 setColumnStatus(i, atLowerBound);
7252 } else {
7253 newValue = columnUpper_[i];
7254 setColumnStatus(i, atUpperBound);
7255 }
7256 } else {
7257 newValue = columnUpper_[i];
7258 setColumnStatus(i, atUpperBound);
7259 }
7260 }
7261 break;
7262 }
7263 if (fabs(newValue - columnActivity_[i]) > 1.0e-12) {
7264 changed = true;
7265 columnActivity_[i] = newValue;
7266 }
7267 }
7268 if (!changed && setToBounds == 1)
7269 // no need to do anything
7270 setToBounds = 0;
7271 }
7272 if (!setToBounds) {
7273 // Just use column solution
7274 CoinZeroN(rowActivity_, numberRows_);
7275 matrix()->times(columnActivity_, rowActivity_) ;
7276 // put in standard form
7277 createRim(7 + 8 + 16 + 32);
7278 dualTolerance_ = dblParam_[ClpDualTolerance];
7279 primalTolerance_ = dblParam_[ClpPrimalTolerance];
7280 checkPrimalSolution( rowActivityWork_, columnActivityWork_);
7281 checkDualSolution();
7282 } else {
7283 startup(0, 0);
7284 gutsOfSolution(NULL, NULL);
7285 }
7286 if (!numberDualInfeasibilities_ &&
7287 !numberPrimalInfeasibilities_)
7288 problemStatus_ = 0;
7289 else
7290 problemStatus_ = -1;
7291#ifdef CLP_DEBUG
7292 int i;
7293 double value = 0.0;
7294 for (i = 0; i < numberRows_ + numberColumns_; i++)
7295 value += dj_[i] * solution_[i];
7296 printf("dual value %g, primal %g\n", value, objectiveValue());
7297#endif
7298 // release extra memory
7299 deleteRim(0);
7300}
7301// Check unscaled primal solution but allow for rounding error
7302void
7303ClpSimplex::checkUnscaledSolution()
7304{
7305 if (problemStatus_==1 && matrix_->getNumElements()) {
7306 const double * element = matrix_->getElements();
7307 const CoinBigIndex * columnStart = matrix_->getVectorStarts();
7308 const int * columnLength = matrix_->getVectorLengths();
7309 const int * row = matrix_->getIndices();
7310 memset(rowActivity_,0,numberRows_*sizeof(double));
7311 double * sum = new double [numberRows_+100000];
7312 memset(sum,0,numberRows_*sizeof(double));
7313 // clean column activity
7314 for (int i=0;i<numberColumns_;i++) {
7315 double value = columnActivity_[i];
7316 value = CoinMax(value,columnLower_[i]);
7317 value = CoinMin(value,columnUpper_[i]);
7318 //columnActivity_[i]=value;
7319 if (value) {
7320 for (CoinBigIndex j=columnStart[i];
7321 j<columnStart[i]+columnLength[i];j++) {
7322 double value2 = value*element[j];
7323 int iRow = row[j];
7324 assert (iRow>=0&&iRow<numberRows_);
7325 rowActivity_[iRow] += value2;
7326 sum[iRow]+=fabs(value2);
7327 }
7328 }
7329 }
7330 sumPrimalInfeasibilities_ = 0.0;
7331 numberPrimalInfeasibilities_ = 0;
7332 double sumPrimalInfeasibilities2 = 0.0;
7333 int numberPrimalInfeasibilities2 = 0;
7334 double fudgeFactor = 1.0e-12;
7335 double fudgeFactor2 = 1.0e-12;
7336 double tolerance = primalTolerance_;
7337 for (int i=0;i<numberRows_;i++) {
7338 double useTolerance = CoinMax(tolerance,fudgeFactor*sum[i]);
7339 double value = rowActivity_[i];
7340 useTolerance = CoinMax(useTolerance,fudgeFactor2*fabs(value));
7341 if (value>rowUpper_[i]) {
7342 sumPrimalInfeasibilities2 += value - rowUpper_[i];
7343 numberPrimalInfeasibilities2++;
7344 if (value>rowUpper_[i]+useTolerance) {
7345 sumPrimalInfeasibilities_ += value - (rowUpper_[i]+useTolerance);
7346 numberPrimalInfeasibilities_++;
7347 }
7348 } else if (value<rowLower_[i]) {
7349 sumPrimalInfeasibilities2 -= value - rowLower_[i];
7350 numberPrimalInfeasibilities2++;
7351 if (value<rowLower_[i]-useTolerance) {
7352 sumPrimalInfeasibilities_ -= value - (rowLower_[i]-useTolerance);
7353 numberPrimalInfeasibilities_++;
7354 }
7355 }
7356 }
7357 char line[1000];
7358 if (!numberPrimalInfeasibilities2) {
7359 sprintf(line,"%d unscaled row infeasibilities - summing to %g",
7360 numberPrimalInfeasibilities2,
7361 sumPrimalInfeasibilities2);
7362 handler_->message(CLP_GENERAL, messages_)
7363 << line
7364 << CoinMessageEol;
7365 }
7366 if (!numberPrimalInfeasibilities_) {
7367 if (!numberDualInfeasibilities_)
7368 problemStatus_=0;
7369 } else {
7370 sprintf(line,"%d relaxed row infeasibilities - summing to %g",
7371 numberPrimalInfeasibilities_,
7372 sumPrimalInfeasibilities_);
7373 handler_->message(CLP_GENERAL, messages_)
7374 << line
7375 << CoinMessageEol;
7376 }
7377 delete [] sum;
7378 }
7379}
7380/* Crash - at present just aimed at dual, returns
7381 -2 if dual preferred and crash basis created
7382 -1 if dual preferred and all slack basis preferred
7383 0 if basis going in was not all slack
7384 1 if primal preferred and all slack basis preferred
7385 2 if primal preferred and crash basis created.
7386
7387 if gap between bounds <="gap" variables can be flipped
7388 ( If pivot -1 then can be made super basic!)
7389
7390 If "pivot" is
7391 -1 No pivoting - always primal
7392 0 No pivoting (so will just be choice of algorithm)
7393 1 Simple pivoting e.g. gub
7394 2 Mini iterations
7395 3 Just throw all free variables in basis
7396*/
7397int
7398ClpSimplex::crash(double gap, int pivot)
7399{
7400 //CoinAssert(!rowObjective_); // not coded
7401 int iColumn;
7402 int numberBad = 0;
7403 int numberBasic = 0;
7404 double dualTolerance = dblParam_[ClpDualTolerance];
7405 //double primalTolerance=dblParam_[ClpPrimalTolerance];
7406 int returnCode = 0;
7407 // If no basis then make all slack one
7408 if (!status_)
7409 createStatus();
7410
7411 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
7412 if (getColumnStatus(iColumn) == basic)
7413 numberBasic++;
7414 }
7415 if (!numberBasic || pivot == 3) {
7416 if (pivot == 3) {
7417 // Just throw all free variables in basis
7418 for (int iRow = 0; iRow < numberRows_; iRow++) {
7419 if (fabs(rowLower_[iRow]) < fabs(rowUpper_[iRow]))
7420 setRowStatus(iRow, atLowerBound);
7421 else
7422 setRowStatus(iRow, atUpperBound);
7423 }
7424 for (int iColumn = 0; iColumn < numberColumns_; iColumn++) {
7425 if (columnLower_[iColumn] < -1.0e20 && columnUpper_[iColumn] > 1.0e20)
7426 setColumnStatus(iColumn, basic);
7427 }
7428 return 0;
7429 }
7430 // all slack
7431 double * dj = new double [numberColumns_];
7432 double * solution = columnActivity_;
7433 const double * linearObjective = objective();
7434 //double objectiveValue=0.0;
7435 int iColumn;
7436 double direction = optimizationDirection_;
7437 // direction is actually scale out not scale in
7438 if (direction)
7439 direction = 1.0 / direction;
7440 for (iColumn = 0; iColumn < numberColumns_; iColumn++)
7441 dj[iColumn] = direction * linearObjective[iColumn];
7442 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
7443 // assume natural place is closest to zero
7444 double lowerBound = columnLower_[iColumn];
7445 double upperBound = columnUpper_[iColumn];
7446 if (lowerBound > -1.0e20 || upperBound < 1.0e20) {
7447 bool atLower;
7448 if (fabs(upperBound) < fabs(lowerBound)) {
7449 atLower = false;
7450 setColumnStatus(iColumn, atUpperBound);
7451 solution[iColumn] = upperBound;
7452 } else {
7453 atLower = true;
7454 setColumnStatus(iColumn, atLowerBound);
7455 solution[iColumn] = lowerBound;
7456 }
7457 if (dj[iColumn] < -dualTolerance_) {
7458 // should be at upper bound
7459 if (atLower) {
7460 // can we flip
7461 if (upperBound - lowerBound <= gap) {
7462 columnActivity_[iColumn] = upperBound;
7463 setColumnStatus(iColumn, atUpperBound);
7464 } else if (pivot < 0) {
7465 // set superbasic
7466 columnActivity_[iColumn] = lowerBound + gap;
7467 setColumnStatus(iColumn, superBasic);
7468 } else if (dj[iColumn] < -dualTolerance) {
7469 numberBad++;
7470 }
7471 }
7472 } else if (dj[iColumn] > dualTolerance_) {
7473 // should be at lower bound
7474 if (!atLower) {
7475 // can we flip
7476 if (upperBound - lowerBound <= gap) {
7477 columnActivity_[iColumn] = lowerBound;
7478 setColumnStatus(iColumn, atLowerBound);
7479 } else if (pivot < 0) {
7480 // set superbasic
7481 columnActivity_[iColumn] = upperBound - gap;
7482 setColumnStatus(iColumn, superBasic);
7483 } else if (dj[iColumn] > dualTolerance) {
7484 numberBad++;
7485 }
7486 }
7487 }
7488 } else {
7489 // free
7490 setColumnStatus(iColumn, isFree);
7491 if (fabs(dj[iColumn]) > dualTolerance)
7492 numberBad++;
7493 }
7494 }
7495 if (numberBad || pivot) {
7496 if (pivot <= 0) {
7497 delete [] dj;
7498 returnCode = 1;
7499 } else {
7500 // see if can be made dual feasible with gubs etc
7501 double * pi = new double[numberRows_];
7502 memset (pi, 0, numberRows_ * sizeof(double));
7503 int * way = new int[numberColumns_];
7504 int numberIn = 0;
7505
7506 // Get column copy
7507 CoinPackedMatrix * columnCopy = matrix();
7508 // Get a row copy in standard format
7509 CoinPackedMatrix copy;
7510 copy.setExtraGap(0.0);
7511 copy.setExtraMajor(0.0);
7512 copy.reverseOrderedCopyOf(*columnCopy);
7513 // get matrix data pointers
7514 const int * column = copy.getIndices();
7515 const CoinBigIndex * rowStart = copy.getVectorStarts();
7516 const int * rowLength = copy.getVectorLengths();
7517 const double * elementByRow = copy.getElements();
7518 //const int * row = columnCopy->getIndices();
7519 //const CoinBigIndex * columnStart = columnCopy->getVectorStarts();
7520 //const int * columnLength = columnCopy->getVectorLengths();
7521 //const double * element = columnCopy->getElements();
7522
7523
7524 // if equality row and bounds mean artificial in basis bad
7525 // then do anyway
7526
7527 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
7528 // - if we want to reduce dj, + if we want to increase
7529 int thisWay = 100;
7530 double lowerBound = columnLower_[iColumn];
7531 double upperBound = columnUpper_[iColumn];
7532 if (upperBound > lowerBound) {
7533 switch(getColumnStatus(iColumn)) {
7534
7535 case basic:
7536 thisWay = 0;
7537 case ClpSimplex::isFixed:
7538 break;
7539 case isFree:
7540 case superBasic:
7541 if (dj[iColumn] < -dualTolerance)
7542 thisWay = 1;
7543 else if (dj[iColumn] > dualTolerance)
7544 thisWay = -1;
7545 else
7546 thisWay = 0;
7547 break;
7548 case atUpperBound:
7549 if (dj[iColumn] > dualTolerance)
7550 thisWay = -1;
7551 else if (dj[iColumn] < -dualTolerance)
7552 thisWay = -3;
7553 else
7554 thisWay = -2;
7555 break;
7556 case atLowerBound:
7557 if (dj[iColumn] < -dualTolerance)
7558 thisWay = 1;
7559 else if (dj[iColumn] > dualTolerance)
7560 thisWay = 3;
7561 else
7562 thisWay = 2;
7563 break;
7564 }
7565 }
7566 way[iColumn] = thisWay;
7567 }
7568 /*if (!numberBad)
7569 printf("Was dual feasible before passes - rows %d\n",
7570 numberRows_);*/
7571 int lastNumberIn = -100000;
7572 int numberPasses = 5;
7573 while (numberIn > lastNumberIn + numberRows_ / 100) {
7574 lastNumberIn = numberIn;
7575 // we need to maximize chance of doing good
7576 int iRow;
7577 for (iRow = 0; iRow < numberRows_; iRow++) {
7578 double lowerBound = rowLower_[iRow];
7579 double upperBound = rowUpper_[iRow];
7580 if (getRowStatus(iRow) == basic) {
7581 // see if we can find a column to pivot on
7582 int j;
7583 // down is amount pi can go down
7584 double maximumDown = COIN_DBL_MAX;
7585 double maximumUp = COIN_DBL_MAX;
7586 double minimumDown = 0.0;
7587 double minimumUp = 0.0;
7588 int iUp = -1;
7589 int iDown = -1;
7590 int iUpB = -1;
7591 int iDownB = -1;
7592 if (lowerBound < -1.0e20)
7593 maximumUp = -1.0;
7594 if (upperBound > 1.0e20)
7595 maximumDown = -1.0;
7596 for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
7597 int iColumn = column[j];
7598 double value = elementByRow[j];
7599 double djValue = dj[iColumn];
7600 /* way -
7601 -3 - okay at upper bound with negative dj
7602 -2 - marginal at upper bound with zero dj - can only decrease
7603 -1 - bad at upper bound
7604 0 - we can never pivot on this row
7605 1 - bad at lower bound
7606 2 - marginal at lower bound with zero dj - can only increase
7607 3 - okay at lower bound with positive dj
7608 100 - fine we can just ignore
7609 */
7610 if (way[iColumn] != 100) {
7611 switch(way[iColumn]) {
7612
7613 case -3:
7614 if (value > 0.0) {
7615 if (maximumDown * value > -djValue) {
7616 maximumDown = -djValue / value;
7617 iDown = iColumn;
7618 }
7619 } else {
7620 if (-maximumUp * value > -djValue) {
7621 maximumUp = djValue / value;
7622 iUp = iColumn;
7623 }
7624 }
7625 break;
7626 case -2:
7627 if (value > 0.0) {
7628 maximumDown = 0.0;
7629 } else {
7630 maximumUp = 0.0;
7631 }
7632 break;
7633 case -1:
7634 // see if could be satisfied
7635 // dj value > 0
7636 if (value > 0.0) {
7637 maximumDown = 0.0;
7638 if (maximumUp * value < djValue - dualTolerance) {
7639 maximumUp = 0.0; // would improve but not enough
7640 } else {
7641 if (minimumUp * value < djValue) {
7642 minimumUp = djValue / value;
7643 iUpB = iColumn;
7644 }
7645 }
7646 } else {
7647 maximumUp = 0.0;
7648 if (-maximumDown * value < djValue - dualTolerance) {
7649 maximumDown = 0.0; // would improve but not enough
7650 } else {
7651 if (-minimumDown * value < djValue) {
7652 minimumDown = -djValue / value;
7653 iDownB = iColumn;
7654 }
7655 }
7656 }
7657
7658 break;
7659 case 0:
7660 maximumDown = -1.0;
7661 maximumUp = -1.0;
7662 break;
7663 case 1:
7664 // see if could be satisfied
7665 // dj value < 0
7666 if (value > 0.0) {
7667 maximumUp = 0.0;
7668 if (maximumDown * value < -djValue - dualTolerance) {
7669 maximumDown = 0.0; // would improve but not enough
7670 } else {
7671 if (minimumDown * value < -djValue) {
7672 minimumDown = -djValue / value;
7673 iDownB = iColumn;
7674 }
7675 }
7676 } else {
7677 maximumDown = 0.0;
7678 if (-maximumUp * value < -djValue - dualTolerance) {
7679 maximumUp = 0.0; // would improve but not enough
7680 } else {
7681 if (-minimumUp * value < -djValue) {
7682 minimumUp = djValue / value;
7683 iUpB = iColumn;
7684 }
7685 }
7686 }
7687
7688 break;
7689 case 2:
7690 if (value > 0.0) {
7691 maximumUp = 0.0;
7692 } else {
7693 maximumDown = 0.0;
7694 }
7695
7696 break;
7697 case 3:
7698 if (value > 0.0) {
7699 if (maximumUp * value > djValue) {
7700 maximumUp = djValue / value;
7701 iUp = iColumn;
7702 }
7703 } else {
7704 if (-maximumDown * value > djValue) {
7705 maximumDown = -djValue / value;
7706 iDown = iColumn;
7707 }
7708 }
7709
7710 break;
7711 default:
7712 break;
7713 }
7714 }
7715 }
7716 if (iUpB >= 0)
7717 iUp = iUpB;
7718 if (maximumUp <= dualTolerance || maximumUp < minimumUp)
7719 iUp = -1;
7720 if (iDownB >= 0)
7721 iDown = iDownB;
7722 if (maximumDown <= dualTolerance || maximumDown < minimumDown)
7723 iDown = -1;
7724 if (iUp >= 0 || iDown >= 0) {
7725 // do something
7726 if (iUp >= 0 && iDown >= 0) {
7727 if (maximumDown > maximumUp)
7728 iUp = -1;
7729 }
7730 double change;
7731 int kColumn;
7732 if (iUp >= 0) {
7733 kColumn = iUp;
7734 change = maximumUp;
7735 // just do minimum if was dual infeasible
7736 // ? only if maximum large?
7737 if (minimumUp > 0.0)
7738 change = minimumUp;
7739 setRowStatus(iRow, atUpperBound);
7740 } else {
7741 kColumn = iDown;
7742 change = -maximumDown;
7743 // just do minimum if was dual infeasible
7744 // ? only if maximum large?
7745 if (minimumDown > 0.0)
7746 change = -minimumDown;
7747 setRowStatus(iRow, atLowerBound);
7748 }
7749 assert (fabs(change) < 1.0e200);
7750 setColumnStatus(kColumn, basic);
7751 numberIn++;
7752 pi[iRow] = change;
7753 for (j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
7754 int iColumn = column[j];
7755 double value = elementByRow[j];
7756 double djValue = dj[iColumn] - change * value;
7757 dj[iColumn] = djValue;
7758 if (abs(way[iColumn]) == 1) {
7759 numberBad--;
7760 /*if (!numberBad)
7761 printf("Became dual feasible at row %d out of %d\n",
7762 iRow, numberRows_);*/
7763 lastNumberIn = -1000000;
7764 }
7765 int thisWay = 100;
7766 double lowerBound = columnLower_[iColumn];
7767 double upperBound = columnUpper_[iColumn];
7768 if (upperBound > lowerBound) {
7769 switch(getColumnStatus(iColumn)) {
7770
7771 case basic:
7772 thisWay = 0;
7773 case isFixed:
7774 break;
7775 case isFree:
7776 case superBasic:
7777 if (djValue < -dualTolerance)
7778 thisWay = 1;
7779 else if (djValue > dualTolerance)
7780 thisWay = -1;
7781 else {
7782 thisWay = 0;
7783 }
7784 break;
7785 case atUpperBound:
7786 if (djValue > dualTolerance) {
7787 thisWay = -1;
7788 } else if (djValue < -dualTolerance)
7789 thisWay = -3;
7790 else
7791 thisWay = -2;
7792 break;
7793 case atLowerBound:
7794 if (djValue < -dualTolerance) {
7795 thisWay = 1;
7796 } else if (djValue > dualTolerance)
7797 thisWay = 3;
7798 else
7799 thisWay = 2;
7800 break;
7801 }
7802 }
7803 way[iColumn] = thisWay;
7804 }
7805 }
7806 }
7807 }
7808 if (numberIn == lastNumberIn || numberBad || pivot < 2)
7809 break;
7810 if (!(--numberPasses))
7811 break;
7812 //printf("%d put in so far\n",numberIn);
7813 }
7814 // last attempt to flip
7815 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
7816 double lowerBound = columnLower_[iColumn];
7817 double upperBound = columnUpper_[iColumn];
7818 if (upperBound - lowerBound <= gap && upperBound > lowerBound) {
7819 double djValue = dj[iColumn];
7820 switch(getColumnStatus(iColumn)) {
7821
7822 case basic:
7823 case ClpSimplex::isFixed:
7824 break;
7825 case isFree:
7826 case superBasic:
7827 break;
7828 case atUpperBound:
7829 if (djValue > dualTolerance) {
7830 setColumnStatus(iColumn, atUpperBound);
7831 solution[iColumn] = upperBound;
7832 }
7833 break;
7834 case atLowerBound:
7835 if (djValue < -dualTolerance) {
7836 setColumnStatus(iColumn, atUpperBound);
7837 solution[iColumn] = upperBound;
7838 }
7839 break;
7840 }
7841 }
7842 }
7843 delete [] pi;
7844 delete [] dj;
7845 delete [] way;
7846 handler_->message(CLP_CRASH, messages_)
7847 << numberIn
7848 << numberBad
7849 << CoinMessageEol;
7850 returnCode = -1;
7851 }
7852 } else {
7853 delete [] dj;
7854 returnCode = -1;
7855 }
7856 //cleanStatus();
7857 }
7858 return returnCode;
7859}
7860/* Pivot in a variable and out a variable. Returns 0 if okay,
7861 1 if inaccuracy forced re-factorization, -1 if would be singular.
7862 Also updates primal/dual infeasibilities.
7863 Assumes sequenceIn_ and pivotRow_ set and also directionIn and Out.
7864*/
7865int ClpSimplex::pivot()
7866{
7867 // scaling not allowed
7868 assert (!scalingFlag_);
7869 // assume In_ and Out_ are correct and directionOut_ set
7870 // (or In_ if flip
7871 lowerIn_ = lower_[sequenceIn_];
7872 valueIn_ = solution_[sequenceIn_];
7873 upperIn_ = upper_[sequenceIn_];
7874 dualIn_ = dj_[sequenceIn_];
7875 lowerOut_ = lower_[sequenceOut_];
7876 valueOut_ = solution_[sequenceOut_];
7877 upperOut_ = upper_[sequenceOut_];
7878 // for now assume primal is feasible (or in dual)
7879 dualOut_ = dj_[sequenceOut_];
7880 assert(fabs(dualOut_) < 1.0e-6);
7881 bool roundAgain = true;
7882 int returnCode = 0;
7883 bool updateSolution = true;
7884 while (roundAgain) {
7885 roundAgain = false;
7886 unpack(rowArray_[1]);
7887 factorization_->updateColumnFT(rowArray_[2], rowArray_[1]);
7888 alpha_ = 0.0;
7889 int i;
7890 int * index = rowArray_[1]->getIndices();
7891 int number = rowArray_[1]->getNumElements();
7892 double * element = rowArray_[1]->denseVector();
7893 assert ( !rowArray_[3]->getNumElements());
7894 double * saveSolution = rowArray_[3]->denseVector();
7895 for (i = 0; i < number; i++) {
7896 int ii = index[i];
7897 if ( pivotVariable_[ii] == sequenceOut_) {
7898 pivotRow_ = ii;
7899 alpha_ = element[pivotRow_];
7900 break;
7901 }
7902 }
7903 if (fabs(alpha_) < 1.0e-8) {
7904 // be on safe side and clear arrays
7905 rowArray_[0]->clear();
7906 rowArray_[1]->clear();
7907 return -1; // will be singular
7908 }
7909 // we are going to subtract movement from current basic
7910 double movement;
7911 // see where incoming will go to
7912 if (sequenceOut_ < 0 || sequenceIn_ == sequenceOut_) {
7913 // flip so go to bound
7914 movement = ((directionIn_ > 0) ? upperIn_ : lowerIn_) - valueIn_;
7915 } else {
7916 // get where outgoing needs to get to
7917 double outValue = (directionOut_ < 0) ? upperOut_ : lowerOut_;
7918 // solutionOut_ - movement*alpha_ == outValue
7919 movement = (valueOut_ - outValue) / alpha_;
7920 // set directionIn_ correctly
7921 directionIn_ = (movement > 0) ? 1 : -1;
7922 }
7923 theta_ = movement;
7924 double oldValueIn = valueIn_;
7925 // update primal solution
7926 for (i = 0; i < number; i++) {
7927 int ii = index[i];
7928 // get column
7929 int ij = pivotVariable_[ii];
7930 double value = element[ii];
7931 saveSolution[ii] = solution_[ij];
7932 solution_[ij] -= movement * value;
7933 }
7934 //rowArray_[1]->setNumElements(0);
7935 // see where something went to
7936#ifndef NDEBUG
7937 CoinRelFltEq eq(1.0e-9);
7938#endif
7939 if (sequenceOut_ < 0) {
7940 if (directionIn_ < 0) {
7941 assert (eq(solution_[sequenceIn_], upperIn_));
7942 solution_[sequenceIn_] = upperIn_;
7943 } else {
7944 assert (eq(solution_[sequenceIn_], lowerIn_));
7945 solution_[sequenceIn_] = lowerIn_;
7946 }
7947 } else {
7948 if (directionOut_ < 0) {
7949 assert (eq(solution_[sequenceOut_], upperOut_));
7950 solution_[sequenceOut_] = upperOut_;
7951 } else {
7952 assert (eq(solution_[sequenceOut_], lowerOut_));
7953 solution_[sequenceOut_] = lowerOut_;
7954 }
7955 valueOut_ = solution_[sequenceOut_];
7956 solution_[sequenceIn_] = valueIn_ + movement;
7957 }
7958 valueIn_ = solution_[sequenceIn_];
7959 double objectiveChange = dualIn_ * movement;
7960 // update duals
7961 if (pivotRow_ >= 0) {
7962 if (fabs(alpha_) < 1.0e-8) {
7963 // be on safe side and clear arrays
7964 rowArray_[0]->clear();
7965 rowArray_[1]->clear();
7966 return -1; // will be singular
7967 }
7968 double multiplier = dualIn_ / alpha_;
7969 rowArray_[0]->insert(pivotRow_, multiplier);
7970 factorization_->updateColumnTranspose(rowArray_[2], rowArray_[0]);
7971 // put row of tableau in rowArray[0] and columnArray[0]
7972 matrix_->transposeTimes(this, -1.0,
7973 rowArray_[0], columnArray_[1], columnArray_[0]);
7974 // update column djs
7975 int i;
7976 int * index = columnArray_[0]->getIndices();
7977 int number = columnArray_[0]->getNumElements();
7978 double * element = columnArray_[0]->denseVector();
7979 for (i = 0; i < number; i++) {
7980 int ii = index[i];
7981 dj_[ii] += element[ii];
7982 reducedCost_[ii] = dj_[ii];
7983 element[ii] = 0.0;
7984 }
7985 columnArray_[0]->setNumElements(0);
7986 // and row djs
7987 index = rowArray_[0]->getIndices();
7988 number = rowArray_[0]->getNumElements();
7989 element = rowArray_[0]->denseVector();
7990 for (i = 0; i < number; i++) {
7991 int ii = index[i];
7992 dj_[ii+numberColumns_] += element[ii];
7993 dual_[ii] = dj_[ii+numberColumns_];
7994 element[ii] = 0.0;
7995 }
7996 rowArray_[0]->setNumElements(0);
7997 // check incoming
7998 assert (fabs(dj_[sequenceIn_]) < 1.0e-6 || CoinAbs(solveType_) == 2);
7999 }
8000
8001 // if stable replace in basis
8002 int updateStatus = factorization_->replaceColumn(this,
8003 rowArray_[2],
8004 rowArray_[1],
8005 pivotRow_,
8006 alpha_);
8007 bool takePivot = true;
8008 // See if Factorization updated
8009 if (updateStatus) {
8010 updateSolution = false;
8011 returnCode = 1;
8012 }
8013 // if no pivots, bad update but reasonable alpha - take and invert
8014 if (updateStatus == 2 &&
8015 lastGoodIteration_ == numberIterations_ && fabs(alpha_) > 1.0e-5)
8016 updateStatus = 4;
8017 if (updateStatus == 1 || updateStatus == 4 || fabs(alpha_) < 1.0e-6) {
8018 // slight error
8019 if (factorization_->pivots() > 5 || updateStatus == 4) {
8020 returnCode = 1;
8021 }
8022 } else if (updateStatus == 2) {
8023 // major error - put back solution
8024 valueIn_ = oldValueIn;
8025 solution_[sequenceIn_] = valueIn_;
8026 int * index = rowArray_[1]->getIndices();
8027 int number = rowArray_[1]->getNumElements();
8028 for (i = 0; i < number; i++) {
8029 int ii = index[i];
8030 // get column
8031 int ij = pivotVariable_[ii];
8032 solution_[ij] = saveSolution[ii];
8033 }
8034 if (sequenceOut_ >= 0)
8035 valueOut_ = solution_[sequenceOut_];
8036 takePivot = false;
8037 if (factorization_->pivots()) {
8038 // refactorize here
8039 int factorStatus = internalFactorize(1);
8040 if (factorStatus) {
8041 printf("help in user pivot\n");
8042 abort();
8043 }
8044 gutsOfSolution(NULL, NULL);
8045 valueIn_ = solution_[sequenceIn_];
8046 if (sequenceOut_ >= 0)
8047 valueOut_ = solution_[sequenceOut_];
8048 roundAgain = true;
8049 } else {
8050 returnCode = -1;
8051 }
8052 } else if (updateStatus == 3) {
8053 // out of memory
8054 // increase space if not many iterations
8055 if (factorization_->pivots() <
8056 0.5 * factorization_->maximumPivots() &&
8057 factorization_->pivots() < 200)
8058 factorization_->areaFactor(
8059 factorization_->areaFactor() * 1.1);
8060 returnCode = 1; // factorize now
8061 }
8062 {
8063 // clear saveSolution
8064 int * index = rowArray_[1]->getIndices();
8065 int number = rowArray_[1]->getNumElements();
8066 for (i = 0; i < number; i++) {
8067 int ii = index[i];
8068 saveSolution[ii] = 0.0;
8069 }
8070 }
8071 rowArray_[1]->clear();
8072 if (takePivot) {
8073 int save = algorithm_;
8074 // make simple so always primal
8075 algorithm_ = 1;
8076 housekeeping(objectiveChange);
8077 algorithm_ = save;
8078 }
8079 }
8080 if (returnCode == 1) {
8081 // refactorize here
8082 int factorStatus = internalFactorize(1);
8083 if (factorStatus) {
8084 printf("help in user pivot\n");
8085 abort();
8086 }
8087 updateSolution = true;
8088 }
8089 if (updateSolution) {
8090 // just for now - recompute anyway
8091 gutsOfSolution(NULL, NULL);
8092 }
8093 return returnCode;
8094}
8095
8096/* Pivot in a variable and choose an outgoing one. Assumes primal
8097 feasible - will not go through a bound. Returns step length in theta
8098 Returns ray in ray_ (or NULL if no pivot)
8099 Return codes as before but -1 means no acceptable pivot
8100*/
8101int ClpSimplex::primalPivotResult()
8102{
8103 assert (sequenceIn_ >= 0);
8104 valueIn_ = solution_[sequenceIn_];
8105 lowerIn_ = lower_[sequenceIn_];
8106 upperIn_ = upper_[sequenceIn_];
8107 dualIn_ = dj_[sequenceIn_];
8108
8109 int returnCode = static_cast<ClpSimplexPrimal *> (this)->pivotResult();
8110 if (returnCode < 0 && returnCode > -4) {
8111 return 0;
8112 } else {
8113 COIN_DETAIL_PRINT(printf("Return code of %d from ClpSimplexPrimal::pivotResult\n",
8114 returnCode));
8115 return -1;
8116 }
8117}
8118
8119/* Pivot out a variable and choose an incoing one. Assumes dual
8120 feasible - will not go through a reduced cost.
8121 Returns step length in theta
8122 Returns ray in ray_ (or NULL if no pivot)
8123 Return codes as before but -1 means no acceptable pivot
8124*/
8125int
8126ClpSimplex::dualPivotResult()
8127{
8128 return static_cast<ClpSimplexDual *> (this)->pivotResult();
8129}
8130// Factorization frequency
8131int
8132ClpSimplex::factorizationFrequency() const
8133{
8134 if (factorization_)
8135 return factorization_->maximumPivots();
8136 else
8137 return -1;
8138}
8139void
8140ClpSimplex::setFactorizationFrequency(int value)
8141{
8142 if (factorization_)
8143 factorization_->maximumPivots(value);
8144}
8145// Common bits of coding for dual and primal
8146int
8147ClpSimplex::startup(int ifValuesPass, int startFinishOptions)
8148{
8149 // Get rid of some arrays and empty factorization
8150 int useFactorization = false;
8151 if ((startFinishOptions & 2) != 0 && (whatsChanged_&(2 + 512)) == 2 + 512)
8152 useFactorization = true; // Keep factorization if possible
8153#if 0
8154 // seems to be needed if rows deleted later in CbcModel!
8155 if (!solution_ && scaledMatrix_) {
8156 // get rid of scaled matrix
8157 if (scaledMatrix_->getNumRows() != numberRows_) {
8158 delete scaledMatrix_;
8159 scaledMatrix_ = NULL;
8160 }
8161 }
8162#endif
8163 // sanity check
8164 // bad if empty (trap here to avoid using bad matrix_)
8165#if 0
8166 // but also check bounds
8167 {
8168 int badProblem = 0;
8169 int i;
8170 for (i = 0; i < numberColumns_; i++) {
8171 if (columnLower_[i] > columnUpper_[i])
8172 badProblem++;
8173 }
8174 for (i = 0; i < numberRows_; i++) {
8175 if (rowLower_[i] > rowUpper_[i])
8176 badProblem++;
8177 }
8178 if (badProblem) {
8179 numberDualInfeasibilities_ = 0;
8180 sumDualInfeasibilities_ = 0.0;
8181 numberPrimalInfeasibilities_ = badProblem;
8182 sumPrimalInfeasibilities_ = badProblem;
8183 secondaryStatus_ = 6; // so user can see something odd
8184 problemStatus_ = 1;
8185 bool printIt = (specialOptions_ & 32768) == 0 ? true : false; // no message if from Osi
8186 if (printIt)
8187 handler_->message(CLP_INFEASIBLE, messages_)
8188 << CoinMessageEol;
8189 return 2;
8190 }
8191 }
8192#endif
8193 if (!matrix_ || (!matrix_->getNumElements() && objective_->type() < 2)) {
8194 int infeasNumber[2];
8195 double infeasSum[2];
8196 bool printIt = (specialOptions_ & 32768) == 0 ? true : false; // no message if from Osi
8197 problemStatus_ = emptyProblem(infeasNumber, infeasSum, printIt);
8198 if ((startFinishOptions & 1) != 0) {
8199 // User may expect user data - fill in as required
8200 if (numberRows_) {
8201 if (!pivotVariable_)
8202 pivotVariable_ = new int [numberRows_];
8203 CoinIotaN(pivotVariable_, numberRows_, numberColumns_);
8204 }
8205 }
8206 numberDualInfeasibilities_ = infeasNumber[0];
8207 sumDualInfeasibilities_ = infeasSum[0];
8208 numberPrimalInfeasibilities_ = infeasNumber[1];
8209 sumPrimalInfeasibilities_ = infeasSum[1];
8210 return 2;
8211 }
8212 pivotRow_ = -1;
8213 sequenceIn_ = -1;
8214 sequenceOut_ = -1;
8215 secondaryStatus_ = 0;
8216
8217 primalTolerance_ = dblParam_[ClpPrimalTolerance];
8218 dualTolerance_ = dblParam_[ClpDualTolerance];
8219 if (problemStatus_ != 10)
8220 numberIterations_ = 0;
8221
8222 // put in standard form (and make row copy)
8223 // create modifiable copies of model rim and do optional scaling
8224 bool goodMatrix = createRim(7 + 8 + 16 + 32, true, startFinishOptions);
8225
8226 if (goodMatrix) {
8227 // switch off factorization if bad
8228 if (pivotVariable_[0] < 0)
8229 useFactorization = false;
8230 // Model looks okay
8231 // Do initial factorization
8232 // and set certain stuff
8233 // We can either set increasing rows so ...IsBasic gives pivot row
8234 // or we can just increment iBasic one by one
8235 // for now let ...iBasic give pivot row
8236 int saveThreshold = factorization_->denseThreshold();
8237 if (!useFactorization || factorization_->numberRows() != numberRows_) {
8238 useFactorization = false;
8239 factorization_->setDefaultValues();
8240 // Switch off dense (unless special option set)
8241 if ((specialOptions_ & 8) == 0)
8242 factorization_->setDenseThreshold(0);
8243 }
8244 // If values pass then perturb (otherwise may be optimal so leave a bit)
8245 if (ifValuesPass) {
8246 // do perturbation if asked for
8247
8248 if (perturbation_ < 100) {
8249 if (algorithm_ > 0 && (objective_->type() < 2 || !objective_->activated())) {
8250#ifndef FEB_TRY
8251 static_cast<ClpSimplexPrimal *> (this)->perturb(0);
8252#endif
8253 } else if (algorithm_ < 0) {
8254 static_cast<ClpSimplexDual *> (this)->perturb();
8255 }
8256 }
8257 }
8258 // for primal we will change bounds using infeasibilityCost_
8259 if (nonLinearCost_ == NULL && algorithm_ > 0) {
8260 // get a valid nonlinear cost function
8261 nonLinearCost_ = new ClpNonLinearCost(this);
8262 }
8263
8264 // loop round to clean up solution if values pass
8265 int numberThrownOut = -1;
8266 int totalNumberThrownOut = 0;
8267 problemStatus_ = -1;
8268 // see if we are re-using factorization
8269 if (!useFactorization) {
8270 while(numberThrownOut) {
8271 int status = internalFactorize(ifValuesPass ? 10 : 0);
8272 if (status < 0)
8273 return 1; // some error
8274 else
8275 numberThrownOut = status;
8276
8277 // for this we need clean basis so it is after factorize
8278 if (!numberThrownOut || numberThrownOut == numberRows_ + 1) {
8279 // solution will be done again - skip if absolutely sure
8280 if ((specialOptions_ & 512) == 0 || numberThrownOut == numberRows_ + 1) {
8281 //int saveFirstFree=firstFree_;
8282 numberThrownOut = gutsOfSolution( NULL, NULL,
8283 ifValuesPass != 0);
8284 //firstFree_=saveFirstFree;
8285 if (largestPrimalError_ > 10.0 && !ifValuesPass && !numberThrownOut) {
8286 // throw out up to 1000 structurals
8287 int iRow;
8288 int * sort = new int[numberRows_];
8289 double * array = rowArray_[0]->denseVector();
8290 memset(array, 0, numberRows_ * sizeof(double));
8291 times(-1.0, columnActivityWork_, array);
8292 int numberBasic = 0;
8293 for (iRow = 0; iRow < numberRows_; iRow++) {
8294 int iPivot = pivotVariable_[iRow];
8295 if (iPivot < numberColumns_) {
8296 // column
8297 double difference = fabs(array[iRow] + rowActivityWork_[iRow]);
8298 if (difference > 1.0e-4) {
8299 sort[numberThrownOut] = iPivot;
8300 array[numberThrownOut++] = difference;
8301 if (getStatus(iPivot) == basic)
8302 numberBasic++;
8303 }
8304 }
8305 }
8306 if (!numberBasic) {
8307 allSlackBasis(true);
8308 numberThrownOut = 1; // force another go
8309 } else {
8310 CoinSort_2(array, array + numberThrownOut, sort);
8311 numberThrownOut = CoinMin(1000, numberThrownOut);
8312 for (iRow = 0; iRow < numberThrownOut; iRow++) {
8313 int iColumn = sort[iRow];
8314 setColumnStatus(iColumn, superBasic);
8315 if (fabs(solution_[iColumn]) > 1.0e10) {
8316 if (upper_[iColumn] < 0.0) {
8317 solution_[iColumn] = upper_[iColumn];
8318 } else if (lower_[iColumn] > 0.0) {
8319 solution_[iColumn] = lower_[iColumn];
8320 } else {
8321 solution_[iColumn] = 0.0;
8322 }
8323 }
8324 }
8325 }
8326 CoinZeroN(array, numberRows_);
8327 delete [] sort;
8328 }
8329 } else {
8330 // make sure not optimal at once
8331 numberPrimalInfeasibilities_ = 1;
8332 numberThrownOut = 0;
8333 }
8334 } else {
8335 matrix_->rhsOffset(this, true); // redo rhs offset
8336 }
8337 totalNumberThrownOut += numberThrownOut;
8338
8339 }
8340 } else {
8341 // using previous factorization - we assume fine
8342 if ((moreSpecialOptions_ & 8) == 0 || !(whatsChanged_ & 64)) {
8343 // but we need to say not optimal (!(whatsChanged_ & 64) means that objective has changed)
8344 numberPrimalInfeasibilities_ = 1;
8345 numberDualInfeasibilities_ = 1;
8346 }
8347 matrix_->rhsOffset(this, true); // redo rhs offset
8348 }
8349 if (totalNumberThrownOut)
8350 handler_->message(CLP_SINGULARITIES, messages_)
8351 << totalNumberThrownOut
8352 << CoinMessageEol;
8353 // Switch back dense
8354 factorization_->setDenseThreshold(saveThreshold);
8355
8356 if (!numberPrimalInfeasibilities_ && !numberDualInfeasibilities_
8357 && !ifValuesPass &&
8358 (!nonLinearCost_ || !nonLinearCost_->numberInfeasibilities()))
8359 problemStatus_ = 0;
8360 else
8361 assert(problemStatus_ == -1);
8362
8363 // number of times we have declared optimality
8364 numberTimesOptimal_ = 0;
8365 if (disasterArea_)
8366 disasterArea_->intoSimplex();
8367
8368 return 0;
8369 } else {
8370 // bad matrix
8371 return 2;
8372 }
8373
8374}
8375
8376
8377void
8378ClpSimplex::finish(int startFinishOptions)
8379{
8380 // Get rid of some arrays and empty factorization
8381 int getRidOfData = 1;
8382 if (upper_ && ((startFinishOptions & 1) != 0 || problemStatus_ == 10)) {
8383 getRidOfData = 0; // Keep stuff
8384 // mark all as current
8385 whatsChanged_ = 0x3ffffff;
8386 } else {
8387 whatsChanged_ &= ~0xffff;
8388 }
8389 double saveObjValue = objectiveValue_;
8390 deleteRim(getRidOfData);
8391 if (matrix_->type()>=15)
8392 objectiveValue_ = saveObjValue;
8393 // Skip message if changing algorithms
8394 if (problemStatus_ != 10) {
8395 if (problemStatus_ == -1)
8396 problemStatus_ = 4;
8397 assert(problemStatus_ >= 0 && problemStatus_ < 6);
8398 if (handler_->detail(CLP_SIMPLEX_FINISHED, messages_) < 100) {
8399 handler_->message(CLP_SIMPLEX_FINISHED + problemStatus_, messages_)
8400 << objectiveValue()
8401 << CoinMessageEol;
8402 }
8403 }
8404 factorization_->relaxAccuracyCheck(1.0);
8405 // get rid of any network stuff - could do more
8406 factorization_->cleanUp();
8407}
8408// Save data
8409ClpDataSave
8410ClpSimplex::saveData()
8411{
8412 ClpDataSave saved;
8413 saved.dualBound_ = dualBound_;
8414 saved.infeasibilityCost_ = infeasibilityCost_;
8415 saved.sparseThreshold_ = factorization_->sparseThreshold();
8416 saved.pivotTolerance_ = factorization_->pivotTolerance();
8417 saved.zeroFactorizationTolerance_ = factorization_->zeroTolerance();
8418 saved.zeroSimplexTolerance_ = zeroTolerance_;
8419 saved.perturbation_ = perturbation_;
8420 saved.forceFactorization_ = forceFactorization_;
8421 saved.acceptablePivot_ = acceptablePivot_;
8422 saved.objectiveScale_ = objectiveScale_;
8423 // Progress indicator
8424 progress_.fillFromModel (this);
8425 return saved;
8426}
8427// Restore data
8428void
8429ClpSimplex::restoreData(ClpDataSave saved)
8430{
8431 //factorization_->sparseThreshold(saved.sparseThreshold_);
8432 factorization_->pivotTolerance(saved.pivotTolerance_);
8433 factorization_->zeroTolerance(saved.zeroFactorizationTolerance_);
8434 zeroTolerance_ = saved.zeroSimplexTolerance_;
8435 perturbation_ = saved.perturbation_;
8436 infeasibilityCost_ = saved.infeasibilityCost_;
8437 dualBound_ = saved.dualBound_;
8438 forceFactorization_ = saved.forceFactorization_;
8439 objectiveScale_ = saved.objectiveScale_;
8440 acceptablePivot_ = saved.acceptablePivot_;
8441}
8442// To flag a variable (not inline to allow for column generation)
8443void
8444ClpSimplex::setFlagged( int sequence)
8445{
8446 status_[sequence] |= 64;
8447 matrix_->generalExpanded(this, 7, sequence);
8448 lastFlaggedIteration_ = numberIterations_;
8449}
8450/* Factorizes and returns true if optimal. Used by user */
8451bool
8452ClpSimplex::statusOfProblem(bool initial)
8453{
8454 // We don't want scaling
8455 int saveFlag = scalingFlag_;
8456 if (!rowScale_)
8457 scalingFlag_ = 0;
8458 bool goodMatrix = createRim(7 + 8 + 16 + 32);
8459 if (!goodMatrix) {
8460 problemStatus_ = 4;
8461 scalingFlag_ = saveFlag;
8462 return false;
8463 }
8464 // is factorization okay?
8465 if (initial) {
8466 // First time - allow singularities
8467 int numberThrownOut = -1;
8468 int totalNumberThrownOut = 0;
8469 while(numberThrownOut) {
8470 int status = internalFactorize(0);
8471 if (status == numberRows_ + 1)
8472 status = 0; // all slack
8473 if (status < 0) {
8474 deleteRim(-1);
8475 scalingFlag_ = saveFlag;
8476 return false; // some error
8477 } else {
8478 numberThrownOut = status;
8479 }
8480
8481 // for this we need clean basis so it is after factorize
8482 //if (!numberThrownOut)
8483 //numberThrownOut = gutsOfSolution( NULL,NULL,
8484 // false);
8485 //else
8486 //matrix_->rhsOffset(this,true); // redo rhs offset
8487 totalNumberThrownOut += numberThrownOut;
8488
8489 }
8490
8491 if (totalNumberThrownOut)
8492 handler_->message(CLP_SINGULARITIES, messages_)
8493 << totalNumberThrownOut
8494 << CoinMessageEol;
8495 } else {
8496#ifndef NDEBUG
8497 int returnCode = internalFactorize(1);
8498 assert (!returnCode);
8499#else
8500 internalFactorize(1);
8501#endif
8502 }
8503 CoinMemcpyN(rowActivity_, numberRows_, rowActivityWork_);
8504 CoinMemcpyN(columnActivity_, numberColumns_, columnActivityWork_);
8505 gutsOfSolution(NULL, NULL);
8506 CoinMemcpyN(rowActivityWork_, numberRows_, rowActivity_);
8507 CoinMemcpyN(columnActivityWork_, numberColumns_, columnActivity_);
8508 CoinMemcpyN(dj_, numberColumns_, reducedCost_);
8509 deleteRim(-1);
8510 scalingFlag_ = saveFlag;
8511 return (primalFeasible() && dualFeasible());
8512}
8513/* Return model - updates any scalars */
8514void
8515ClpSimplex::returnModel(ClpSimplex & otherModel)
8516{
8517 ClpModel::returnModel(otherModel);
8518 otherModel.bestPossibleImprovement_ = bestPossibleImprovement_;
8519 otherModel.columnPrimalSequence_ = columnPrimalSequence_;
8520 otherModel.zeroTolerance_ = zeroTolerance_;
8521 otherModel.rowPrimalSequence_ = rowPrimalSequence_;
8522 otherModel.bestObjectiveValue_ = bestObjectiveValue_;
8523 otherModel.moreSpecialOptions_ = moreSpecialOptions_;
8524 otherModel.baseIteration_ = baseIteration_;
8525 otherModel.primalToleranceToGetOptimal_ = primalToleranceToGetOptimal_;
8526 otherModel.largestPrimalError_ = largestPrimalError_;
8527 otherModel.largestDualError_ = largestDualError_;
8528 otherModel.alphaAccuracy_ = alphaAccuracy_;
8529 otherModel.alpha_ = alpha_;
8530 otherModel.theta_ = theta_;
8531 otherModel.lowerIn_ = lowerIn_;
8532 otherModel.valueIn_ = valueIn_;
8533 otherModel.upperIn_ = upperIn_;
8534 otherModel.dualIn_ = dualIn_;
8535 otherModel.sequenceIn_ = sequenceIn_;
8536 otherModel.directionIn_ = directionIn_;
8537 otherModel.lowerOut_ = lowerOut_;
8538 otherModel.valueOut_ = valueOut_;
8539 otherModel.upperOut_ = upperOut_;
8540 otherModel.dualOut_ = dualOut_;
8541 otherModel.sequenceOut_ = sequenceOut_;
8542 otherModel.directionOut_ = directionOut_;
8543 otherModel.pivotRow_ = pivotRow_;
8544 otherModel.sumDualInfeasibilities_ = sumDualInfeasibilities_;
8545 otherModel.numberDualInfeasibilities_ = numberDualInfeasibilities_;
8546 otherModel.numberDualInfeasibilitiesWithoutFree_ =
8547 numberDualInfeasibilitiesWithoutFree_;
8548 otherModel.sumPrimalInfeasibilities_ = sumPrimalInfeasibilities_;
8549 otherModel.numberPrimalInfeasibilities_ = numberPrimalInfeasibilities_;
8550 otherModel.numberTimesOptimal_ = numberTimesOptimal_;
8551 otherModel.disasterArea_ = NULL;
8552 otherModel.sumOfRelaxedDualInfeasibilities_ = sumOfRelaxedDualInfeasibilities_;
8553 otherModel.sumOfRelaxedPrimalInfeasibilities_ = sumOfRelaxedPrimalInfeasibilities_;
8554 if (perturbationArray_ != otherModel.perturbationArray_)
8555 delete [] perturbationArray_;
8556 perturbationArray_ = NULL;
8557
8558}
8559/* Constructs a non linear cost from list of non-linearities (columns only)
8560 First lower of each column is taken as real lower
8561 Last lower is taken as real upper and cost ignored
8562
8563 Returns nonzero if bad data e.g. lowers not monotonic
8564*/
8565int
8566ClpSimplex::createPiecewiseLinearCosts(const int * starts,
8567 const double * lower, const double * gradient)
8568{
8569 delete nonLinearCost_;
8570 // Set up feasible bounds and check monotonicity
8571 int iColumn;
8572 int returnCode = 0;
8573
8574 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
8575 int iIndex = starts[iColumn];
8576 int end = starts[iColumn+1] - 1;
8577 columnLower_[iColumn] = lower[iIndex];
8578 columnUpper_[iColumn] = lower[end];
8579 double value = columnLower_[iColumn];
8580 iIndex++;
8581 for (; iIndex < end; iIndex++) {
8582 if (lower[iIndex] < value)
8583 returnCode++; // not monotonic
8584 value = lower[iIndex];
8585 }
8586 }
8587 nonLinearCost_ = new ClpNonLinearCost(this, starts, lower, gradient);
8588 specialOptions_ |= 2; // say keep
8589 return returnCode;
8590}
8591/* For advanced use. When doing iterative solves things can get
8592 nasty so on values pass if incoming solution has largest
8593 infeasibility < incomingInfeasibility throw out variables
8594 from basis until largest infeasibility < allowedInfeasibility
8595 or incoming largest infeasibility.
8596 If allowedInfeasibility>= incomingInfeasibility this is
8597 always possible altough you may end up with an all slack basis.
8598
8599 Defaults are 1.0,10.0
8600*/
8601void
8602ClpSimplex::setValuesPassAction(double incomingInfeasibility,
8603 double allowedInfeasibility)
8604{
8605 incomingInfeasibility_ = incomingInfeasibility;
8606 allowedInfeasibility_ = allowedInfeasibility;
8607 CoinAssert(incomingInfeasibility_ >= 0.0);
8608 CoinAssert(allowedInfeasibility_ >= incomingInfeasibility_);
8609}
8610// Allow initial dense factorization
8611void
8612ClpSimplex::setInitialDenseFactorization(bool onOff)
8613{
8614 if (onOff)
8615 specialOptions_ |= 8;
8616 else
8617 specialOptions_ &= ~8;
8618}
8619bool
8620ClpSimplex::initialDenseFactorization() const
8621{
8622 return (specialOptions_ & 8) != 0;
8623}
8624/* This constructor modifies original ClpSimplex and stores
8625 original stuff in created ClpSimplex. It is only to be used in
8626 conjunction with originalModel */
8627ClpSimplex::ClpSimplex (ClpSimplex * wholeModel,
8628 int numberColumns, const int * whichColumns)
8629{
8630
8631 // Set up dummy row selection list
8632 numberRows_ = wholeModel->numberRows_;
8633 int * whichRow = new int [numberRows_];
8634 int iRow;
8635 for (iRow = 0; iRow < numberRows_; iRow++)
8636 whichRow[iRow] = iRow;
8637 // ClpModel stuff (apart from numberColumns_)
8638 matrix_ = wholeModel->matrix_;
8639 rowCopy_ = wholeModel->rowCopy_;
8640 if (wholeModel->rowCopy_) {
8641 // note reversal of order
8642 wholeModel->rowCopy_ = wholeModel->rowCopy_->subsetClone(numberRows_, whichRow,
8643 numberColumns, whichColumns);
8644 } else {
8645 wholeModel->rowCopy_ = NULL;
8646 }
8647 whatsChanged_ &= ~0xffff;
8648 CoinAssert (wholeModel->matrix_);
8649 wholeModel->matrix_ = wholeModel->matrix_->subsetClone(numberRows_, whichRow,
8650 numberColumns, whichColumns);
8651 delete [] whichRow;
8652 numberColumns_ = wholeModel->numberColumns_;
8653 // Now ClpSimplex stuff and status_
8654 delete wholeModel->primalColumnPivot_;
8655 wholeModel->primalColumnPivot_ = new ClpPrimalColumnSteepest(0);
8656 nonLinearCost_ = wholeModel->nonLinearCost_;
8657
8658 // Now main arrays
8659 int iColumn;
8660 int numberTotal = numberRows_ + numberColumns;
8661 COIN_DETAIL_PRINT(printf("%d %d %d\n", numberTotal, numberRows_, numberColumns));
8662 // mapping
8663 int * mapping = new int[numberRows_+numberColumns_];
8664 for (iColumn = 0; iColumn < numberColumns_; iColumn++)
8665 mapping[iColumn] = -1;
8666 for (iRow = 0; iRow < numberRows_; iRow++)
8667 mapping[iRow+numberColumns_] = iRow + numberColumns;
8668 // Redo costs and bounds of whole model
8669 wholeModel->createRim(1 + 4, false);
8670 lower_ = wholeModel->lower_;
8671 wholeModel->lower_ = new double [numberTotal];
8672 CoinMemcpyN(lower_ + numberColumns_, numberRows_, wholeModel->lower_ + numberColumns);
8673 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
8674 int jColumn = whichColumns[iColumn];
8675 wholeModel->lower_[iColumn] = lower_[jColumn];
8676 // and pointer back
8677 mapping[jColumn] = iColumn;
8678 }
8679#ifdef CLP_DEBUG
8680 for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++)
8681 printf("mapx %d %d\n", iColumn, mapping[iColumn]);
8682#endif
8683 // Re-define pivotVariable_
8684 for (iRow = 0; iRow < numberRows_; iRow++) {
8685 int iPivot = wholeModel->pivotVariable_[iRow];
8686 wholeModel->pivotVariable_[iRow] = mapping[iPivot];
8687#ifdef CLP_DEBUG
8688 printf("p row %d, pivot %d -> %d\n", iRow, iPivot, mapping[iPivot]);
8689#endif
8690 assert (wholeModel->pivotVariable_[iRow] >= 0);
8691 }
8692 // Reverse mapping (so extended version of whichColumns)
8693 for (iColumn = 0; iColumn < numberColumns; iColumn++)
8694 mapping[iColumn] = whichColumns[iColumn];
8695 for (; iColumn < numberRows_ + numberColumns; iColumn++)
8696 mapping[iColumn] = iColumn + (numberColumns_ - numberColumns);
8697#ifdef CLP_DEBUG
8698 for (iColumn = 0; iColumn < numberRows_ + numberColumns; iColumn++)
8699 printf("map %d %d\n", iColumn, mapping[iColumn]);
8700#endif
8701 // Save mapping somewhere - doesn't matter
8702 rowUpper_ = reinterpret_cast<double *> (mapping);
8703 upper_ = wholeModel->upper_;
8704 wholeModel->upper_ = new double [numberTotal];
8705 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8706 int jColumn = mapping[iColumn];
8707 wholeModel->upper_[iColumn] = upper_[jColumn];
8708 }
8709 cost_ = wholeModel->cost_;
8710 wholeModel->cost_ = new double [numberTotal];
8711 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8712 int jColumn = mapping[iColumn];
8713 wholeModel->cost_[iColumn] = cost_[jColumn];
8714 }
8715 dj_ = wholeModel->dj_;
8716 wholeModel->dj_ = new double [numberTotal];
8717 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8718 int jColumn = mapping[iColumn];
8719 wholeModel->dj_[iColumn] = dj_[jColumn];
8720 }
8721 solution_ = wholeModel->solution_;
8722 wholeModel->solution_ = new double [numberTotal];
8723 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8724 int jColumn = mapping[iColumn];
8725 wholeModel->solution_[iColumn] = solution_[jColumn];
8726 }
8727 // now see what variables left out do to row solution
8728 double * rowSolution = wholeModel->solution_ + numberColumns;
8729 double * fullSolution = solution_;
8730 double * sumFixed = new double[numberRows_];
8731 memset (sumFixed, 0, numberRows_ * sizeof(double));
8732 // zero out ones in small problem
8733 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
8734 int jColumn = mapping[iColumn];
8735 fullSolution[jColumn] = 0.0;
8736 }
8737 // Get objective offset
8738 double originalOffset;
8739 wholeModel->getDblParam(ClpObjOffset, originalOffset);
8740 double offset = 0.0;
8741 const double * cost = cost_;
8742 for (iColumn = 0; iColumn < numberColumns_; iColumn++)
8743 offset += fullSolution[iColumn] * cost[iColumn];
8744 wholeModel->setDblParam(ClpObjOffset, originalOffset - offset);
8745 setDblParam(ClpObjOffset, originalOffset);
8746 matrix_->times(1.0, fullSolution, sumFixed, wholeModel->rowScale_, wholeModel->columnScale_);
8747
8748 double * lower = lower_ + numberColumns;
8749 double * upper = upper_ + numberColumns;
8750 double fixed = 0.0;
8751 for (iRow = 0; iRow < numberRows_; iRow++) {
8752 fixed += fabs(sumFixed[iRow]);
8753 if (lower[iRow] > -1.0e50)
8754 lower[iRow] -= sumFixed[iRow];
8755 if (upper[iRow] < 1.0e50)
8756 upper[iRow] -= sumFixed[iRow];
8757 rowSolution[iRow] -= sumFixed[iRow];
8758 }
8759 COIN_DETAIL_PRINT(printf("offset %g sumfixed %g\n", offset, fixed));
8760 delete [] sumFixed;
8761 columnScale_ = wholeModel->columnScale_;
8762 if (columnScale_) {
8763 wholeModel->columnScale_ = new double [numberTotal];
8764 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
8765 int jColumn = mapping[iColumn];
8766 wholeModel->columnScale_[iColumn] = columnScale_[jColumn];
8767 }
8768 }
8769 status_ = wholeModel->status_;
8770 wholeModel->status_ = new unsigned char [numberTotal];
8771 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8772 int jColumn = mapping[iColumn];
8773 wholeModel->status_[iColumn] = status_[jColumn];
8774 }
8775 savedSolution_ = wholeModel->savedSolution_;
8776 if (savedSolution_) {
8777 wholeModel->savedSolution_ = new double [numberTotal];
8778 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8779 int jColumn = mapping[iColumn];
8780 wholeModel->savedSolution_[iColumn] = savedSolution_[jColumn];
8781 }
8782 }
8783 saveStatus_ = wholeModel->saveStatus_;
8784 if (saveStatus_) {
8785 wholeModel->saveStatus_ = new unsigned char [numberTotal];
8786 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8787 int jColumn = mapping[iColumn];
8788 wholeModel->saveStatus_[iColumn] = saveStatus_[jColumn];
8789 }
8790 }
8791
8792 wholeModel->numberColumns_ = numberColumns;
8793 // Initialize weights
8794 wholeModel->primalColumnPivot_->saveWeights(wholeModel, 2);
8795 // Costs
8796 wholeModel->nonLinearCost_ = new ClpNonLinearCost(wholeModel);
8797 wholeModel->nonLinearCost_->checkInfeasibilities();
8798 COIN_DETAIL_PRINT(printf("after contraction %d infeasibilities summing to %g\n",
8799 nonLinearCost_->numberInfeasibilities(), nonLinearCost_->sumInfeasibilities()));
8800 // Redo some stuff
8801 wholeModel->reducedCostWork_ = wholeModel->dj_;
8802 wholeModel->rowReducedCost_ = wholeModel->dj_ + wholeModel->numberColumns_;
8803 wholeModel->columnActivityWork_ = wholeModel->solution_;
8804 wholeModel->rowActivityWork_ = wholeModel->solution_ + wholeModel->numberColumns_;
8805 wholeModel->objectiveWork_ = wholeModel->cost_;
8806 wholeModel->rowObjectiveWork_ = wholeModel->cost_ + wholeModel->numberColumns_;
8807 wholeModel->rowLowerWork_ = wholeModel->lower_ + wholeModel->numberColumns_;
8808 wholeModel->columnLowerWork_ = wholeModel->lower_;
8809 wholeModel->rowUpperWork_ = wholeModel->upper_ + wholeModel->numberColumns_;
8810 wholeModel->columnUpperWork_ = wholeModel->upper_;
8811#ifndef NDEBUG
8812 // Check status
8813 ClpSimplex * xxxx = wholeModel;
8814 int nBasic = 0;
8815 for (iColumn = 0; iColumn < xxxx->numberRows_ + xxxx->numberColumns_; iColumn++)
8816 if (xxxx->getStatus(iColumn) == basic)
8817 nBasic++;
8818 assert (nBasic == xxxx->numberRows_);
8819 for (iRow = 0; iRow < xxxx->numberRows_; iRow++) {
8820 int iPivot = xxxx->pivotVariable_[iRow];
8821 assert (xxxx->getStatus(iPivot) == basic);
8822 }
8823#endif
8824}
8825/* This copies back stuff from miniModel and then deletes miniModel.
8826 Only to be used with mini constructor */
8827void
8828ClpSimplex::originalModel(ClpSimplex * miniModel)
8829{
8830 int numberSmall = numberColumns_;
8831 numberColumns_ = miniModel->numberColumns_;
8832 int numberTotal = numberSmall + numberRows_;
8833 // copy back
8834 int iColumn;
8835 int * mapping = reinterpret_cast<int *> (miniModel->rowUpper_);
8836#ifdef CLP_DEBUG
8837 for (iColumn = 0; iColumn < numberRows_ + numberColumns_; iColumn++)
8838 printf("mapb %d %d\n", iColumn, mapping[iColumn]);
8839#endif
8840 // miniModel actually has full arrays
8841 // now see what variables left out do to row solution
8842 double * fullSolution = miniModel->solution_;
8843 double * sumFixed = new double[numberRows_];
8844 memset (sumFixed, 0, numberRows_ * sizeof(double));
8845 miniModel->matrix_->times(1.0, fullSolution, sumFixed, rowScale_, miniModel->columnScale_);
8846
8847 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8848 int jColumn = mapping[iColumn];
8849 miniModel->lower_[jColumn] = lower_[iColumn];
8850 miniModel->upper_[jColumn] = upper_[iColumn];
8851 miniModel->cost_[jColumn] = cost_[iColumn];
8852 miniModel->dj_[jColumn] = dj_[iColumn];
8853 miniModel->solution_[jColumn] = solution_[iColumn];
8854 miniModel->status_[jColumn] = status_[iColumn];
8855#ifdef CLP_DEBUG
8856 printf("%d in small -> %d in original\n", iColumn, jColumn);
8857#endif
8858 }
8859 delete [] lower_;
8860 lower_ = miniModel->lower_;
8861 delete [] upper_;
8862 upper_ = miniModel->upper_;
8863 delete [] cost_;
8864 cost_ = miniModel->cost_;
8865 delete [] dj_;
8866 dj_ = miniModel->dj_;
8867 delete [] solution_;
8868 solution_ = miniModel->solution_;
8869 delete [] status_;
8870 status_ = miniModel->status_;
8871 if (columnScale_) {
8872 for (iColumn = 0; iColumn < numberSmall; iColumn++) {
8873 int jColumn = mapping[iColumn];
8874 miniModel->columnScale_[jColumn] = columnScale_[iColumn];
8875 }
8876 delete [] columnScale_;
8877 columnScale_ = miniModel->columnScale_;
8878 }
8879 if (savedSolution_) {
8880 if (!miniModel->savedSolution_) {
8881 miniModel->savedSolution_ = ClpCopyOfArray(solution_, numberColumns_ + numberRows_);
8882 } else {
8883 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8884 int jColumn = mapping[iColumn];
8885 miniModel->savedSolution_[jColumn] = savedSolution_[iColumn];
8886 }
8887 }
8888 delete [] savedSolution_;
8889 savedSolution_ = miniModel->savedSolution_;
8890 }
8891 if (saveStatus_) {
8892 if (!miniModel->saveStatus_) {
8893 miniModel->saveStatus_ = ClpCopyOfArray(status_, numberColumns_ + numberRows_);
8894 } else {
8895 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
8896 int jColumn = mapping[iColumn];
8897 miniModel->saveStatus_[jColumn] = saveStatus_[iColumn];
8898 }
8899 }
8900 delete [] saveStatus_;
8901 saveStatus_ = miniModel->saveStatus_;
8902 }
8903 // Re-define pivotVariable_
8904 int iRow;
8905 for (iRow = 0; iRow < numberRows_; iRow++) {
8906 int iPivot = pivotVariable_[iRow];
8907#ifdef CLP_DEBUG
8908 printf("pb row %d, pivot %d -> %d\n", iRow, iPivot, mapping[iPivot]);
8909#endif
8910 pivotVariable_[iRow] = mapping[iPivot];
8911 assert (pivotVariable_[iRow] >= 0);
8912 }
8913 // delete stuff and move back
8914 delete matrix_;
8915 delete rowCopy_;
8916 delete primalColumnPivot_;
8917 delete nonLinearCost_;
8918 matrix_ = miniModel->matrix_;
8919 rowCopy_ = miniModel->rowCopy_;
8920 nonLinearCost_ = miniModel->nonLinearCost_;
8921 double originalOffset;
8922 miniModel->getDblParam(ClpObjOffset, originalOffset);
8923 setDblParam(ClpObjOffset, originalOffset);
8924 // Redo some stuff
8925 reducedCostWork_ = dj_;
8926 rowReducedCost_ = dj_ + numberColumns_;
8927 columnActivityWork_ = solution_;
8928 rowActivityWork_ = solution_ + numberColumns_;
8929 objectiveWork_ = cost_;
8930 rowObjectiveWork_ = cost_ + numberColumns_;
8931 rowLowerWork_ = lower_ + numberColumns_;
8932 columnLowerWork_ = lower_;
8933 rowUpperWork_ = upper_ + numberColumns_;
8934 columnUpperWork_ = upper_;
8935 // Cleanup
8936 for (iRow = 0; iRow < numberRows_; iRow++) {
8937 double value = rowActivityWork_[iRow] + sumFixed[iRow];
8938 rowActivityWork_[iRow] = value;
8939 switch(getRowStatus(iRow)) {
8940
8941 case basic:
8942 break;
8943 case atUpperBound:
8944 //rowActivityWork_[iRow]=rowUpperWork_[iRow];
8945 break;
8946 case ClpSimplex::isFixed:
8947 case atLowerBound:
8948 //rowActivityWork_[iRow]=rowLowerWork_[iRow];
8949 break;
8950 case isFree:
8951 break;
8952 // superbasic
8953 case superBasic:
8954 break;
8955 }
8956 }
8957 delete [] sumFixed;
8958 nonLinearCost_->checkInfeasibilities();
8959 COIN_DETAIL_PRINT(printf("in original %d infeasibilities summing to %g\n",
8960 nonLinearCost_->numberInfeasibilities(), nonLinearCost_->sumInfeasibilities()));
8961 // Initialize weights
8962 primalColumnPivot_ = new ClpPrimalColumnSteepest(10);
8963 primalColumnPivot_->saveWeights(this, 2);
8964#ifndef NDEBUG
8965 // Check status
8966 ClpSimplex * xxxx = this;
8967 int nBasic = 0;
8968 for (iColumn = 0; iColumn < xxxx->numberRows_ + xxxx->numberColumns_; iColumn++)
8969 if (xxxx->getStatus(iColumn) == basic)
8970 nBasic++;
8971 assert (nBasic == xxxx->numberRows_);
8972 for (iRow = 0; iRow < xxxx->numberRows_; iRow++) {
8973 int iPivot = xxxx->pivotVariable_[iRow];
8974 assert (xxxx->getStatus(iPivot) == basic);
8975 }
8976#endif
8977}
8978// Pass in Event handler (cloned and deleted at end)
8979void
8980ClpSimplex::passInEventHandler(const ClpEventHandler * eventHandler)
8981{
8982 delete eventHandler_;
8983 eventHandler_ = eventHandler->clone();
8984 eventHandler_->setSimplex(this);
8985}
8986#ifndef NDEBUG
8987// For errors to make sure print to screen
8988// only called in debug mode
8989static void indexError(int index,
8990 std::string methodName)
8991{
8992 std::cerr << "Illegal index " << index << " in ClpSimplex::" << methodName << std::endl;
8993 throw CoinError("Illegal index", methodName, "ClpSimplex");
8994}
8995#endif
8996// These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal)
8997//Get a row of the tableau (slack part in slack if not NULL)
8998void
8999ClpSimplex::getBInvARow(int row, double* z, double * slack)
9000{
9001#ifndef NDEBUG
9002 int n = numberRows();
9003 if (row < 0 || row >= n) {
9004 indexError(row, "getBInvARow");
9005 }
9006#endif
9007 if (!rowArray_[0]) {
9008 printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
9009 abort();
9010 }
9011 CoinIndexedVector * rowArray0 = rowArray(0);
9012 CoinIndexedVector * rowArray1 = rowArray(1);
9013 CoinIndexedVector * columnArray0 = columnArray(0);
9014 CoinIndexedVector * columnArray1 = columnArray(1);
9015 rowArray0->clear();
9016 rowArray1->clear();
9017 columnArray0->clear();
9018 columnArray1->clear();
9019 // put +1 in row
9020 // But swap if pivot variable was slack as clp stores slack as -1.0
9021 int pivot = pivotVariable_[row];
9022 double value;
9023 // And if scaled then adjust
9024 if (!rowScale_) {
9025 if (pivot < numberColumns_)
9026 value = 1.0;
9027 else
9028 value = -1.0;
9029 } else {
9030 if (pivot < numberColumns_)
9031 value = columnScale_[pivot];
9032 else
9033 value = -1.0 * inverseRowScale_[pivot-numberColumns_];
9034 }
9035 rowArray1->insert(row, value);
9036 factorization_->updateColumnTranspose(rowArray0, rowArray1);
9037 // put row of tableau in rowArray1 and columnArray0
9038 clpMatrix()->transposeTimes(this, 1.0,
9039 rowArray1, columnArray1, columnArray0);
9040 if (!rowScale_) {
9041 CoinMemcpyN(columnArray0->denseVector(), numberColumns_, z);
9042 } else {
9043 double * array = columnArray0->denseVector();
9044 for (int i = 0; i < numberColumns_; i++)
9045 z[i] = array[i] * inverseColumnScale_[i];
9046 }
9047 if (slack) {
9048 if (!rowScale_) {
9049 CoinMemcpyN(rowArray1->denseVector(), numberRows_, slack);
9050 } else {
9051 double * array = rowArray1->denseVector();
9052 for (int i = 0; i < numberRows_; i++)
9053 slack[i] = array[i] * rowScale_[i];
9054 }
9055 }
9056 // don't need to clear everything always, but doesn't cost
9057 rowArray0->clear();
9058 rowArray1->clear();
9059 columnArray0->clear();
9060 columnArray1->clear();
9061}
9062
9063//Get a row of the basis inverse
9064void
9065ClpSimplex::getBInvRow(int row, double* z)
9066
9067{
9068#ifndef NDEBUG
9069 int n = numberRows();
9070 if (row < 0 || row >= n) {
9071 indexError(row, "getBInvRow");
9072 }
9073#endif
9074 if (!rowArray_[0]) {
9075 printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
9076 abort();
9077 }
9078 ClpFactorization * factorization = factorization_;
9079 CoinIndexedVector * rowArray0 = rowArray(0);
9080 CoinIndexedVector * rowArray1 = rowArray(1);
9081 rowArray0->clear();
9082 rowArray1->clear();
9083 // put +1 in row
9084 // But swap if pivot variable was slack as clp stores slack as -1.0
9085 double value = (pivotVariable_[row] < numberColumns_) ? 1.0 : -1.0;
9086 // but scale
9087 if (rowScale_) {
9088 int pivot = pivotVariable_[row];
9089 if (pivot < numberColumns_)
9090 value *= columnScale_[pivot];
9091 else
9092 value /= rowScale_[pivot-numberColumns_];
9093 }
9094 rowArray1->insert(row, value);
9095 factorization->updateColumnTranspose(rowArray0, rowArray1);
9096 if (!rowScale_) {
9097 CoinMemcpyN(rowArray1->denseVector(), numberRows_, z);
9098 } else {
9099 double * array = rowArray1->denseVector();
9100 for (int i = 0; i < numberRows_; i++) {
9101 z[i] = array[i] * rowScale_[i];
9102 }
9103 }
9104 rowArray1->clear();
9105}
9106
9107//Get a column of the tableau
9108void
9109ClpSimplex::getBInvACol(int col, double* vec)
9110{
9111 if (!rowArray_[0]) {
9112 printf("ClpSimplexPrimal or ClpSimplexDual should have been called with correct startFinishOption\n");
9113 abort();
9114 }
9115 CoinIndexedVector * rowArray0 = rowArray(0);
9116 CoinIndexedVector * rowArray1 = rowArray(1);
9117 rowArray0->clear();
9118 rowArray1->clear();
9119 // get column of matrix
9120#ifndef NDEBUG
9121 int n = numberColumns_ + numberRows_;
9122 if (col < 0 || col >= n) {
9123 indexError(col, "getBInvACol");
9124 }
9125#endif
9126 if (!rowScale_) {
9127 if (col < numberColumns_) {
9128 unpack(rowArray1, col);
9129 } else {
9130 rowArray1->insert(col - numberColumns_, 1.0);
9131 }
9132 } else {
9133 if (col < numberColumns_) {
9134 unpack(rowArray1, col);
9135 double multiplier = 1.0 * inverseColumnScale_[col];
9136 int number = rowArray1->getNumElements();
9137 int * index = rowArray1->getIndices();
9138 double * array = rowArray1->denseVector();
9139 for (int i = 0; i < number; i++) {
9140 int iRow = index[i];
9141 // make sure not packed
9142 assert (array[iRow]);
9143 array[iRow] *= multiplier;
9144 }
9145 } else {
9146 rowArray1->insert(col - numberColumns_, rowScale_[col-numberColumns_]);
9147 }
9148 }
9149 factorization_->updateColumn(rowArray0, rowArray1, false);
9150 // But swap if pivot variable was slack as clp stores slack as -1.0
9151 double * array = rowArray1->denseVector();
9152 if (!rowScale_) {
9153 for (int i = 0; i < numberRows_; i++) {
9154 double multiplier = (pivotVariable_[i] < numberColumns_) ? 1.0 : -1.0;
9155 vec[i] = multiplier * array[i];
9156 }
9157 } else {
9158 for (int i = 0; i < numberRows_; i++) {
9159 int pivot = pivotVariable_[i];
9160 if (pivot < numberColumns_)
9161 vec[i] = array[i] * columnScale_[pivot];
9162 else
9163 vec[i] = - array[i] / rowScale_[pivot-numberColumns_];
9164 }
9165 }
9166 rowArray1->clear();
9167}
9168
9169//Get a column of the basis inverse
9170void
9171ClpSimplex::getBInvCol(int col, double* vec)
9172{
9173 if (!rowArray_[0]) {
9174 printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
9175 abort();
9176 }
9177 CoinIndexedVector * rowArray0 = rowArray(0);
9178 CoinIndexedVector * rowArray1 = rowArray(1);
9179 rowArray0->clear();
9180 rowArray1->clear();
9181#ifndef NDEBUG
9182 int n = numberRows();
9183 if (col < 0 || col >= n) {
9184 indexError(col, "getBInvCol");
9185 }
9186#endif
9187 // put +1 in row
9188 // but scale
9189 double value;
9190 if (!rowScale_) {
9191 value = 1.0;
9192 } else {
9193 value = rowScale_[col];
9194 }
9195 rowArray1->insert(col, value);
9196 factorization_->updateColumn(rowArray0, rowArray1, false);
9197 // But swap if pivot variable was slack as clp stores slack as -1.0
9198 double * array = rowArray1->denseVector();
9199 if (!rowScale_) {
9200 for (int i = 0; i < numberRows_; i++) {
9201 double multiplier = (pivotVariable_[i] < numberColumns_) ? 1.0 : -1.0;
9202 vec[i] = multiplier * array[i];
9203 }
9204 } else {
9205 for (int i = 0; i < numberRows_; i++) {
9206 int pivot = pivotVariable_[i];
9207 double value = array[i];
9208 if (pivot < numberColumns_)
9209 vec[i] = value * columnScale_[pivot];
9210 else
9211 vec[i] = - value / rowScale_[pivot-numberColumns_];
9212 }
9213 }
9214 rowArray1->clear();
9215}
9216
9217/* Get basic indices (order of indices corresponds to the
9218 order of elements in a vector retured by getBInvACol() and
9219 getBInvCol()).
9220*/
9221void
9222ClpSimplex::getBasics(int* index)
9223{
9224 if (!rowArray_[0]) {
9225 printf("ClpSimplexPrimal or ClpSimplexDual must have been called with correct startFinishOption\n");
9226 abort();
9227 }
9228 CoinAssert (index);
9229 CoinMemcpyN(pivotVariable(), numberRows(), index);
9230}
9231/* Set an objective function coefficient */
9232void
9233ClpSimplex::setObjectiveCoefficient( int elementIndex, double elementValue )
9234{
9235#ifndef NDEBUG
9236 if (elementIndex < 0 || elementIndex >= numberColumns_) {
9237 indexError(elementIndex, "setObjectiveCoefficient");
9238 }
9239#endif
9240 if (objective()[elementIndex] != elementValue) {
9241 objective()[elementIndex] = elementValue;
9242 if ((whatsChanged_ & 1) != 0) {
9243 // work arrays exist - update as well
9244 whatsChanged_ &= ~64;
9245 double direction = optimizationDirection_ * objectiveScale_;
9246 if (!rowScale_) {
9247 objectiveWork_[elementIndex] = direction * elementValue;
9248 } else {
9249 objectiveWork_[elementIndex] = direction * elementValue
9250 * columnScale_[elementIndex];
9251 }
9252 }
9253 }
9254}
9255/* Set a single row lower bound<br>
9256 Use -DBL_MAX for -infinity. */
9257void
9258ClpSimplex::setRowLower( int elementIndex, double elementValue )
9259{
9260#ifndef NDEBUG
9261 int n = numberRows_;
9262 if (elementIndex < 0 || elementIndex >= n) {
9263 indexError(elementIndex, "setRowLower");
9264 }
9265#endif
9266 if (elementValue < -1.0e27)
9267 elementValue = -COIN_DBL_MAX;
9268 if (rowLower_[elementIndex] != elementValue) {
9269 rowLower_[elementIndex] = elementValue;
9270 if ((whatsChanged_ & 1) != 0) {
9271 // work arrays exist - update as well
9272 whatsChanged_ &= ~16;
9273 if (rowLower_[elementIndex] == -COIN_DBL_MAX) {
9274 rowLowerWork_[elementIndex] = -COIN_DBL_MAX;
9275 } else if (!rowScale_) {
9276 rowLowerWork_[elementIndex] = elementValue * rhsScale_;
9277 } else {
9278 rowLowerWork_[elementIndex] = elementValue * rhsScale_
9279 * rowScale_[elementIndex];
9280 }
9281 }
9282 }
9283}
9284
9285/* Set a single row upper bound<br>
9286 Use DBL_MAX for infinity. */
9287void
9288ClpSimplex::setRowUpper( int elementIndex, double elementValue )
9289{
9290#ifndef NDEBUG
9291 int n = numberRows_;
9292 if (elementIndex < 0 || elementIndex >= n) {
9293 indexError(elementIndex, "setRowUpper");
9294 }
9295#endif
9296 if (elementValue > 1.0e27)
9297 elementValue = COIN_DBL_MAX;
9298 if (rowUpper_[elementIndex] != elementValue) {
9299 rowUpper_[elementIndex] = elementValue;
9300 if ((whatsChanged_ & 1) != 0) {
9301 // work arrays exist - update as well
9302 whatsChanged_ &= ~32;
9303 if (rowUpper_[elementIndex] == COIN_DBL_MAX) {
9304 rowUpperWork_[elementIndex] = COIN_DBL_MAX;
9305 } else if (!rowScale_) {
9306 rowUpperWork_[elementIndex] = elementValue * rhsScale_;
9307 } else {
9308 rowUpperWork_[elementIndex] = elementValue * rhsScale_
9309 * rowScale_[elementIndex];
9310 }
9311 }
9312 }
9313}
9314
9315/* Set a single row lower and upper bound */
9316void
9317ClpSimplex::setRowBounds( int elementIndex,
9318 double lowerValue, double upperValue )
9319{
9320#ifndef NDEBUG
9321 int n = numberRows_;
9322 if (elementIndex < 0 || elementIndex >= n) {
9323 indexError(elementIndex, "setRowBounds");
9324 }
9325#endif
9326 if (lowerValue < -1.0e27)
9327 lowerValue = -COIN_DBL_MAX;
9328 if (upperValue > 1.0e27)
9329 upperValue = COIN_DBL_MAX;
9330 //CoinAssert (upperValue>=lowerValue);
9331 if (rowLower_[elementIndex] != lowerValue) {
9332 rowLower_[elementIndex] = lowerValue;
9333 if ((whatsChanged_ & 1) != 0) {
9334 // work arrays exist - update as well
9335 whatsChanged_ &= ~16;
9336 if (rowLower_[elementIndex] == -COIN_DBL_MAX) {
9337 rowLowerWork_[elementIndex] = -COIN_DBL_MAX;
9338 } else if (!rowScale_) {
9339 rowLowerWork_[elementIndex] = lowerValue * rhsScale_;
9340 } else {
9341 rowLowerWork_[elementIndex] = lowerValue * rhsScale_
9342 * rowScale_[elementIndex];
9343 }
9344 }
9345 }
9346 if (rowUpper_[elementIndex] != upperValue) {
9347 rowUpper_[elementIndex] = upperValue;
9348 if ((whatsChanged_ & 1) != 0) {
9349 // work arrays exist - update as well
9350 whatsChanged_ &= ~32;
9351 if (rowUpper_[elementIndex] == COIN_DBL_MAX) {
9352 rowUpperWork_[elementIndex] = COIN_DBL_MAX;
9353 } else if (!rowScale_) {
9354 rowUpperWork_[elementIndex] = upperValue * rhsScale_;
9355 } else {
9356 rowUpperWork_[elementIndex] = upperValue * rhsScale_
9357 * rowScale_[elementIndex];
9358 }
9359 }
9360 }
9361}
9362void ClpSimplex::setRowSetBounds(const int* indexFirst,
9363 const int* indexLast,
9364 const double* boundList)
9365{
9366#ifndef NDEBUG
9367 int n = numberRows_;
9368#endif
9369 int numberChanged = 0;
9370 const int * saveFirst = indexFirst;
9371 while (indexFirst != indexLast) {
9372 const int iRow = *indexFirst++;
9373#ifndef NDEBUG
9374 if (iRow < 0 || iRow >= n) {
9375 indexError(iRow, "setRowSetBounds");
9376 }
9377#endif
9378 double lowerValue = *boundList++;
9379 double upperValue = *boundList++;
9380 if (lowerValue < -1.0e27)
9381 lowerValue = -COIN_DBL_MAX;
9382 if (upperValue > 1.0e27)
9383 upperValue = COIN_DBL_MAX;
9384 //CoinAssert (upperValue>=lowerValue);
9385 if (rowLower_[iRow] != lowerValue) {
9386 rowLower_[iRow] = lowerValue;
9387 whatsChanged_ &= ~16;
9388 numberChanged++;
9389 }
9390 if (rowUpper_[iRow] != upperValue) {
9391 rowUpper_[iRow] = upperValue;
9392 whatsChanged_ &= ~32;
9393 numberChanged++;
9394 }
9395 }
9396 if (numberChanged && (whatsChanged_ & 1) != 0) {
9397 indexFirst = saveFirst;
9398 while (indexFirst != indexLast) {
9399 const int iRow = *indexFirst++;
9400 if (rowLower_[iRow] == -COIN_DBL_MAX) {
9401 rowLowerWork_[iRow] = -COIN_DBL_MAX;
9402 } else if (!rowScale_) {
9403 rowLowerWork_[iRow] = rowLower_[iRow] * rhsScale_;
9404 } else {
9405 rowLowerWork_[iRow] = rowLower_[iRow] * rhsScale_
9406 * rowScale_[iRow];
9407 }
9408 if (rowUpper_[iRow] == COIN_DBL_MAX) {
9409 rowUpperWork_[iRow] = COIN_DBL_MAX;
9410 } else if (!rowScale_) {
9411 rowUpperWork_[iRow] = rowUpper_[iRow] * rhsScale_;
9412 } else {
9413 rowUpperWork_[iRow] = rowUpper_[iRow] * rhsScale_
9414 * rowScale_[iRow];
9415 }
9416 }
9417 }
9418}
9419//-----------------------------------------------------------------------------
9420/* Set a single column lower bound<br>
9421 Use -DBL_MAX for -infinity. */
9422void
9423ClpSimplex::setColumnLower( int elementIndex, double elementValue )
9424{
9425#ifndef NDEBUG
9426 int n = numberColumns_;
9427 if (elementIndex < 0 || elementIndex >= n) {
9428 indexError(elementIndex, "setColumnLower");
9429 }
9430#endif
9431 if (elementValue < -1.0e27)
9432 elementValue = -COIN_DBL_MAX;
9433 if (columnLower_[elementIndex] != elementValue) {
9434 columnLower_[elementIndex] = elementValue;
9435 if ((whatsChanged_ & 1) != 0) {
9436 // work arrays exist - update as well
9437 whatsChanged_ &= ~128;
9438 double value;
9439 if (columnLower_[elementIndex] == -COIN_DBL_MAX) {
9440 value = -COIN_DBL_MAX;
9441 } else if (!columnScale_) {
9442 value = elementValue * rhsScale_;
9443 } else {
9444 value = elementValue * rhsScale_
9445 / columnScale_[elementIndex];
9446 }
9447 lower_[elementIndex] = value;
9448 if (maximumRows_ >= 0)
9449 lower_[elementIndex+maximumRows_+maximumColumns_] = value;
9450 }
9451 }
9452}
9453
9454/* Set a single column upper bound<br>
9455 Use DBL_MAX for infinity. */
9456void
9457ClpSimplex::setColumnUpper( int elementIndex, double elementValue )
9458{
9459#ifndef NDEBUG
9460 int n = numberColumns_;
9461 if (elementIndex < 0 || elementIndex >= n) {
9462 indexError(elementIndex, "setColumnUpper");
9463 }
9464#endif
9465 if (elementValue > 1.0e27)
9466 elementValue = COIN_DBL_MAX;
9467 if (columnUpper_[elementIndex] != elementValue) {
9468 columnUpper_[elementIndex] = elementValue;
9469 if ((whatsChanged_ & 1) != 0) {
9470 // work arrays exist - update as well
9471 whatsChanged_ &= ~256;
9472 double value;
9473 if (columnUpper_[elementIndex] == COIN_DBL_MAX) {
9474 value = COIN_DBL_MAX;
9475 } else if (!columnScale_) {
9476 value = elementValue * rhsScale_;
9477 } else {
9478 value = elementValue * rhsScale_
9479 / columnScale_[elementIndex];
9480 }
9481 //assert (columnUpperWork_==upper_);
9482 upper_[elementIndex] = value;
9483 if (maximumRows_ >= 0)
9484 upper_[elementIndex+maximumRows_+maximumColumns_] = value;
9485 }
9486 }
9487}
9488
9489/* Set a single column lower and upper bound */
9490void
9491ClpSimplex::setColumnBounds( int elementIndex,
9492 double lowerValue, double upperValue )
9493{
9494#ifndef NDEBUG
9495 int n = numberColumns_;
9496 if (elementIndex < 0 || elementIndex >= n) {
9497 indexError(elementIndex, "setColumnBounds");
9498 }
9499#endif
9500 if (lowerValue < -1.0e27)
9501 lowerValue = -COIN_DBL_MAX;
9502 if (columnLower_[elementIndex] != lowerValue) {
9503 columnLower_[elementIndex] = lowerValue;
9504 if ((whatsChanged_ & 1) != 0) {
9505 // work arrays exist - update as well
9506 whatsChanged_ &= ~128;
9507 if (columnLower_[elementIndex] == -COIN_DBL_MAX) {
9508 lower_[elementIndex] = -COIN_DBL_MAX;
9509 } else if (!columnScale_) {
9510 lower_[elementIndex] = lowerValue * rhsScale_;
9511 } else {
9512 lower_[elementIndex] = lowerValue * rhsScale_
9513 / columnScale_[elementIndex];
9514 }
9515 }
9516 }
9517 if (upperValue > 1.0e27)
9518 upperValue = COIN_DBL_MAX;
9519 //CoinAssert (upperValue>=lowerValue);
9520 if (columnUpper_[elementIndex] != upperValue) {
9521 columnUpper_[elementIndex] = upperValue;
9522 if ((whatsChanged_ & 1) != 0) {
9523 // work arrays exist - update as well
9524 whatsChanged_ &= ~256;
9525 if (columnUpper_[elementIndex] == COIN_DBL_MAX) {
9526 upper_[elementIndex] = COIN_DBL_MAX;
9527 } else if (!columnScale_) {
9528 upper_[elementIndex] = upperValue * rhsScale_;
9529 } else {
9530 upper_[elementIndex] = upperValue * rhsScale_
9531 / columnScale_[elementIndex];
9532 }
9533 }
9534 }
9535}
9536void ClpSimplex::setColumnSetBounds(const int* indexFirst,
9537 const int* indexLast,
9538 const double* boundList)
9539{
9540#ifndef NDEBUG
9541 int n = numberColumns_;
9542#endif
9543 int numberChanged = 0;
9544 const int * saveFirst = indexFirst;
9545 while (indexFirst != indexLast) {
9546 const int iColumn = *indexFirst++;
9547#ifndef NDEBUG
9548 if (iColumn < 0 || iColumn >= n) {
9549 indexError(iColumn, "setColumnSetBounds");
9550 }
9551#endif
9552 double lowerValue = *boundList++;
9553 double upperValue = *boundList++;
9554 if (lowerValue < -1.0e27)
9555 lowerValue = -COIN_DBL_MAX;
9556 if (upperValue > 1.0e27)
9557 upperValue = COIN_DBL_MAX;
9558 //CoinAssert (upperValue>=lowerValue);
9559 if (columnLower_[iColumn] != lowerValue) {
9560 columnLower_[iColumn] = lowerValue;
9561 whatsChanged_ &= ~16;
9562 numberChanged++;
9563 }
9564 if (columnUpper_[iColumn] != upperValue) {
9565 columnUpper_[iColumn] = upperValue;
9566 whatsChanged_ &= ~32;
9567 numberChanged++;
9568 }
9569 }
9570 if (numberChanged && (whatsChanged_ & 1) != 0) {
9571 indexFirst = saveFirst;
9572 while (indexFirst != indexLast) {
9573 const int iColumn = *indexFirst++;
9574 if (columnLower_[iColumn] == -COIN_DBL_MAX) {
9575 lower_[iColumn] = -COIN_DBL_MAX;
9576 } else if (!columnScale_) {
9577 lower_[iColumn] = columnLower_[iColumn] * rhsScale_;
9578 } else {
9579 lower_[iColumn] = columnLower_[iColumn] * rhsScale_
9580 / columnScale_[iColumn];
9581 }
9582 if (columnUpper_[iColumn] == COIN_DBL_MAX) {
9583 upper_[iColumn] = COIN_DBL_MAX;
9584 } else if (!columnScale_) {
9585 upper_[iColumn] = columnUpper_[iColumn] * rhsScale_;
9586 } else {
9587 upper_[iColumn] = columnUpper_[iColumn] * rhsScale_
9588 / columnScale_[iColumn];
9589 }
9590 }
9591 }
9592}
9593/* Just check solution (for internal use) - sets sum of
9594 infeasibilities etc. */
9595void
9596ClpSimplex::checkSolutionInternal()
9597{
9598 double dualTolerance = dblParam_[ClpDualTolerance];
9599 double primalTolerance = dblParam_[ClpPrimalTolerance];
9600 double nonLinearOffset = 0.0;
9601 const double * objective = objective_->gradient(this, columnActivity_,
9602 nonLinearOffset, true);
9603 int iRow, iColumn;
9604 assert (!rowObjective_);
9605
9606 objectiveValue_ = 0.0;
9607 // now look at solution
9608 sumPrimalInfeasibilities_ = 0.0;
9609 numberPrimalInfeasibilities_ = 0;
9610
9611 sumDualInfeasibilities_ = 0.0;
9612 numberDualInfeasibilities_ = 0;
9613 double maxmin = optimizationDirection_;
9614
9615 for (iRow = 0; iRow < numberRows_; iRow++) {
9616 double dualValue = dual_[iRow] * maxmin;
9617 double primalValue = rowActivity_[iRow];
9618 double lower = rowLower_[iRow];
9619 double upper = rowUpper_[iRow];
9620 ClpSimplex::Status status = getRowStatus(iRow);
9621 if (status != basic) {
9622 if (lower == upper) {
9623 status = ClpSimplex::isFixed;
9624 } else if (primalValue > upper - primalTolerance) {
9625 status = ClpSimplex::atUpperBound;
9626 } else if (primalValue < lower + primalTolerance) {
9627 status = ClpSimplex::atLowerBound;
9628 }
9629 setRowStatus(iRow, status);
9630 }
9631 if (primalValue > upper + primalTolerance) {
9632 sumPrimalInfeasibilities_ += primalValue - upper - primalTolerance;
9633 numberPrimalInfeasibilities_ ++;
9634 } else if (primalValue < lower - primalTolerance) {
9635 sumPrimalInfeasibilities_ += lower - primalValue - primalTolerance;
9636 numberPrimalInfeasibilities_ ++;
9637 } else {
9638 switch(status) {
9639
9640 case basic:
9641 case ClpSimplex::isFixed:
9642 break;
9643 case atUpperBound:
9644 // dual should not be positive
9645 if (dualValue > dualTolerance) {
9646 sumDualInfeasibilities_ += dualValue - dualTolerance_;
9647 numberDualInfeasibilities_ ++;
9648 }
9649 break;
9650 case atLowerBound:
9651 // dual should not be negative
9652 if (dualValue < -dualTolerance) {
9653 sumDualInfeasibilities_ -= dualValue + dualTolerance_;
9654 numberDualInfeasibilities_ ++;
9655 }
9656 break;
9657 case superBasic:
9658 case isFree:
9659 if (primalValue < upper - primalTolerance) {
9660 // dual should not be negative
9661 if (dualValue < -dualTolerance) {
9662 sumDualInfeasibilities_ -= dualValue + dualTolerance_;
9663 numberDualInfeasibilities_ ++;
9664 }
9665 }
9666 if (primalValue > lower + primalTolerance) {
9667 // dual should not be positive
9668 if (dualValue > dualTolerance) {
9669 sumDualInfeasibilities_ += dualValue - dualTolerance_;
9670 numberDualInfeasibilities_ ++;
9671 }
9672 }
9673 break;
9674 }
9675 }
9676 }
9677 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
9678 double dualValue = reducedCost_[iColumn] * maxmin;
9679 double primalValue = columnActivity_[iColumn];
9680 objectiveValue_ += objective[iColumn] * primalValue;
9681 double lower = columnLower_[iColumn];
9682 double upper = columnUpper_[iColumn];
9683 ClpSimplex::Status status = getColumnStatus(iColumn);
9684 if (status != basic && lower == upper) {
9685 status = ClpSimplex::isFixed;
9686 setColumnStatus(iColumn, ClpSimplex::isFixed);
9687 }
9688 if (primalValue > upper + primalTolerance) {
9689 sumPrimalInfeasibilities_ += primalValue - upper - primalTolerance;
9690 numberPrimalInfeasibilities_ ++;
9691 } else if (primalValue < lower - primalTolerance) {
9692 sumPrimalInfeasibilities_ += lower - primalValue - primalTolerance;
9693 numberPrimalInfeasibilities_ ++;
9694 } else {
9695 switch(status) {
9696
9697 case basic:
9698 // dual should be zero
9699 if (fabs(dualValue) > 10.0 * dualTolerance) {
9700 sumDualInfeasibilities_ -= dualValue + dualTolerance_;
9701 numberDualInfeasibilities_ ++;
9702 }
9703 break;
9704 case ClpSimplex::isFixed:
9705 break;
9706 case atUpperBound:
9707 // dual should not be positive
9708 if (dualValue > dualTolerance) {
9709 sumDualInfeasibilities_ += dualValue - dualTolerance_;
9710 numberDualInfeasibilities_ ++;
9711 }
9712 break;
9713 case atLowerBound:
9714 // dual should not be negative
9715 if (dualValue < -dualTolerance) {
9716 sumDualInfeasibilities_ -= dualValue + dualTolerance_;
9717 numberDualInfeasibilities_ ++;
9718 }
9719 break;
9720 case superBasic:
9721 case isFree:
9722 if (primalValue < upper - primalTolerance) {
9723 // dual should not be negative
9724 if (dualValue < -dualTolerance) {
9725 sumDualInfeasibilities_ -= dualValue + dualTolerance_;
9726 numberDualInfeasibilities_ ++;
9727 }
9728 }
9729 if (primalValue > lower + primalTolerance) {
9730 // dual should not be positive
9731 if (dualValue > dualTolerance) {
9732 sumDualInfeasibilities_ += dualValue - dualTolerance_;
9733 numberDualInfeasibilities_ ++;
9734 }
9735 }
9736 break;
9737 }
9738 }
9739 }
9740 objectiveValue_ += objective_->nonlinearOffset();
9741 // But do direction
9742 objectiveValue_ *= optimizationDirection_;
9743
9744 if (!numberDualInfeasibilities_ &&
9745 !numberPrimalInfeasibilities_)
9746 problemStatus_ = 0;
9747 else
9748 problemStatus_ = -1;
9749}
9750/*
9751 When scaling is on it is possible that the scaled problem
9752 is feasible but the unscaled is not. Clp returns a secondary
9753 status code to that effect. This option allows for a cleanup.
9754 If you use it I would suggest 1.
9755 This only affects actions when scaled optimal
9756 0 - no action
9757 1 - clean up using dual if primal infeasibility
9758 2 - clean up using dual if dual infeasibility
9759 3 - clean up using dual if primal or dual infeasibility
9760 11,12,13 - as 1,2,3 but use primal
9761*/
9762#ifdef COUNT_CLEANUPS
9763static int n1 = 0;
9764static int n2 = 0;
9765static int n3 = 0;
9766#endif
9767int
9768ClpSimplex::cleanup(int cleanupScaling)
9769{
9770#ifdef COUNT_CLEANUPS
9771 n1++;
9772#endif
9773 int returnCode = 0;
9774 if (!problemStatus_ && cleanupScaling) {
9775 int check = cleanupScaling % 10;
9776 bool primal = (secondaryStatus_ == 2 || secondaryStatus_ == 4);
9777 bool dual = (secondaryStatus_ == 3 || secondaryStatus_ == 4);
9778 if (((check & 1) != 0 && primal) || (((check & 2) != 0) && dual)) {
9779 // need cleanup
9780 int saveScalingFlag = scalingFlag_;
9781 // say matrix changed
9782 whatsChanged_ |= 1;
9783 scaling(0);
9784 if (cleanupScaling < 10) {
9785 // dual
9786 returnCode = this->dual();
9787 } else {
9788 // primal
9789 returnCode = this->primal();
9790 }
9791#ifdef COUNT_CLEANUPS
9792 n2++;
9793 n3 += numberIterations_;
9794 //printf("**cleanup took %d iterations\n",numberIterations_);
9795#endif
9796 scaling(saveScalingFlag);
9797 }
9798 }
9799 return returnCode;
9800}
9801#ifdef COUNT_CLEANUPS
9802void printHowMany()
9803{
9804 printf("There were %d cleanups out of %d solves and %d iterations\n",
9805 n2, n1, n3);
9806}
9807#endif
9808#ifndef SLIM_CLP
9809#include "CoinWarmStartBasis.hpp"
9810
9811// Returns a basis (to be deleted by user)
9812CoinWarmStartBasis *
9813ClpSimplex::getBasis() const
9814{
9815 int iRow, iColumn;
9816 CoinWarmStartBasis * basis = new CoinWarmStartBasis();
9817 basis->setSize(numberColumns_, numberRows_);
9818
9819 if (statusExists()) {
9820 // Flip slacks
9821 int lookupA[] = {0, 1, 3, 2, 0, 2};
9822 for (iRow = 0; iRow < numberRows_; iRow++) {
9823 int iStatus = getRowStatus(iRow);
9824 iStatus = lookupA[iStatus];
9825 basis->setArtifStatus(iRow, static_cast<CoinWarmStartBasis::Status> (iStatus));
9826 }
9827 int lookupS[] = {0, 1, 2, 3, 0, 3};
9828 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
9829 int iStatus = getColumnStatus(iColumn);
9830 iStatus = lookupS[iStatus];
9831 basis->setStructStatus(iColumn, static_cast<CoinWarmStartBasis::Status> (iStatus));
9832 }
9833 }
9834 return basis;
9835}
9836#endif
9837// Compute objective value from solution
9838void
9839ClpSimplex::computeObjectiveValue(bool useInternalArrays)
9840{
9841 int iSequence;
9842 objectiveValue_ = 0.0;
9843 const double * obj = objective();
9844 if (!useInternalArrays) {
9845 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
9846 double value = columnActivity_[iSequence];
9847 objectiveValue_ += value * obj[iSequence];
9848 }
9849 // But remember direction as we are using external objective
9850 objectiveValue_ *= optimizationDirection_;
9851 } else if (!columnScale_) {
9852 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
9853 double value = columnActivityWork_[iSequence];
9854 objectiveValue_ += value * obj[iSequence];
9855 }
9856 // But remember direction as we are using external objective
9857 objectiveValue_ *= optimizationDirection_;
9858 objectiveValue_ += objective_->nonlinearOffset();
9859 objectiveValue_ /= (objectiveScale_ * rhsScale_);
9860 } else {
9861 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
9862 double scaleFactor = columnScale_[iSequence];
9863 double valueScaled = columnActivityWork_[iSequence];
9864 objectiveValue_ += valueScaled * scaleFactor * obj[iSequence];
9865 }
9866 // But remember direction as we are using external objective
9867 objectiveValue_ *= optimizationDirection_;
9868 objectiveValue_ += objective_->nonlinearOffset();
9869 objectiveValue_ /= (objectiveScale_ * rhsScale_);
9870 }
9871}
9872// Compute minimization objective value from internal solution
9873double
9874ClpSimplex::computeInternalObjectiveValue()
9875{
9876 int iSequence;
9877 //double oldObj = objectiveValue_;
9878 double objectiveValue = 0.0;
9879 const double * obj = objective();
9880 if (!columnScale_) {
9881 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
9882 double value = solution_[iSequence];
9883 objectiveValue += value * obj[iSequence];
9884 }
9885 } else {
9886 for (iSequence = 0; iSequence < numberColumns_; iSequence++) {
9887 double value = solution_[iSequence] * columnScale_[iSequence];
9888 objectiveValue += value * obj[iSequence];
9889 }
9890 }
9891 objectiveValue *= optimizationDirection_ / rhsScale_;
9892 objectiveValue -= dblParam_[ClpObjOffset];
9893 return objectiveValue;
9894}
9895// If user left factorization frequency then compute
9896void
9897ClpSimplex::defaultFactorizationFrequency()
9898{
9899 if (factorizationFrequency() == 200) {
9900 // User did not touch preset
9901 const int cutoff1 = 10000;
9902 const int cutoff2 = 100000;
9903 const int base = 75;
9904 const int freq0 = 50;
9905 const int freq1 = 200;
9906 const int freq2 = 400;
9907 const int maximum = 1000;
9908 int frequency;
9909 if (numberRows_ < cutoff1)
9910 frequency = base + numberRows_ / freq0;
9911 else if (numberRows_ < cutoff2)
9912 frequency = base + cutoff1 / freq0 + (numberRows_ - cutoff1) / freq1;
9913 else
9914 frequency = base + cutoff1 / freq0 + (cutoff2 - cutoff1) / freq1 + (numberRows_ - cutoff2) / freq2;
9915 setFactorizationFrequency(CoinMin(maximum, frequency));
9916 }
9917}
9918// Gets clean and emptyish factorization
9919ClpFactorization *
9920ClpSimplex::getEmptyFactorization()
9921{
9922 if ((specialOptions_ & 65536) == 0) {
9923 assert (!factorization_);
9924 factorization_ = new ClpFactorization();
9925 } else if (!factorization_) {
9926 factorization_ = new ClpFactorization();
9927 factorization_->setPersistenceFlag(1);
9928 }
9929 return factorization_;
9930}
9931// May delete or may make clean and emptyish factorization
9932void
9933ClpSimplex::setEmptyFactorization()
9934{
9935 if (factorization_) {
9936 factorization_->cleanUp();
9937 if ((specialOptions_ & 65536) == 0) {
9938 delete factorization_;
9939 factorization_ = NULL;
9940 } else if (factorization_) {
9941 factorization_->almostDestructor();
9942 }
9943 }
9944}
9945/* Array persistence flag
9946 If 0 then as now (delete/new)
9947 1 then only do arrays if bigger needed
9948 2 as 1 but give a bit extra if bigger needed
9949*/
9950void
9951ClpSimplex::setPersistenceFlag(int value)
9952{
9953 if (value) {
9954 //specialOptions_|=65536;
9955 startPermanentArrays();
9956 } else {
9957 specialOptions_ &= ~65536;
9958 }
9959 if (factorization_)
9960 factorization_->setPersistenceFlag(value);
9961}
9962// Move status and solution across
9963void
9964ClpSimplex::moveInfo(const ClpSimplex & rhs, bool justStatus)
9965{
9966 objectiveValue_ = rhs.objectiveValue_;
9967 numberIterations_ = rhs. numberIterations_;
9968 problemStatus_ = rhs. problemStatus_;
9969 secondaryStatus_ = rhs. secondaryStatus_;
9970 if (numberRows_ == rhs.numberRows_ && numberColumns_ == rhs.numberColumns_ && !justStatus) {
9971 if (rhs.status_) {
9972 if (status_)
9973 CoinMemcpyN(rhs.status_, numberRows_ + numberColumns_, status_);
9974 else
9975 status_ = CoinCopyOfArray(rhs.status_, numberRows_ + numberColumns_);
9976 } else {
9977 delete [] status_;
9978 status_ = NULL;
9979 }
9980 CoinMemcpyN(rhs.columnActivity_, numberColumns_, columnActivity_);
9981 CoinMemcpyN(rhs.reducedCost_, numberColumns_, reducedCost_);
9982 CoinMemcpyN(rhs.rowActivity_, numberRows_, rowActivity_);
9983 CoinMemcpyN(rhs.dual_, numberRows_, dual_);
9984 }
9985}
9986// Save a copy of model with certain state - normally without cuts
9987void
9988ClpSimplex::makeBaseModel()
9989{
9990 delete baseModel_;
9991 baseModel_ = new ClpSimplex(*this);
9992}
9993// Switch off base model
9994void
9995ClpSimplex::deleteBaseModel()
9996{
9997 delete baseModel_;
9998 baseModel_ = NULL;
9999}
10000// Reset to base model
10001void
10002ClpSimplex::setToBaseModel(ClpSimplex * model)
10003{
10004 if (!model)
10005 model = baseModel_;
10006 assert (model);
10007 int multiplier = ((model->specialOptions_ & 65536) != 0) ? 2 : 1;
10008 assert (multiplier == 2);
10009 if (multiplier == 2) {
10010 assert (model->maximumRows_ >= 0);
10011 if (maximumRows_ < 0) {
10012 specialOptions_ |= 65536;
10013 maximumRows_ = model->maximumRows_;
10014 maximumColumns_ = model->maximumColumns_;
10015 }
10016 }
10017 COIN_DETAIL_PRINT(printf("resetbase a %d rows, %d maximum rows\n",
10018 numberRows_, maximumRows_));
10019 // temporary - later use maximumRows_ for rowUpper_ etc
10020 assert (numberRows_ >= model->numberRows_);
10021 abort();
10022}
10023// Start or reset using maximumRows_ and Columns_
10024bool
10025ClpSimplex::startPermanentArrays()
10026{
10027 int maximumRows = maximumRows_;
10028 int maximumColumns = maximumColumns_;
10029 ClpModel::startPermanentArrays();
10030 if (maximumRows != maximumRows_ ||
10031 maximumColumns != maximumColumns_) {
10032#if 0
10033 maximumInternalRows_ = maximumRows_;
10034 maximumInternalColumns_ = maximumColumns_;
10035 int numberTotal2 = (maximumRows_ + maximumColumns_) * 2;
10036 delete [] cost_;
10037 cost_ = new double[numberTotal2];
10038 delete [] lower_;
10039 delete [] upper_;
10040 lower_ = new double[numberTotal2];
10041 upper_ = new double[numberTotal2];
10042 delete [] dj_;
10043 dj_ = new double[numberTotal2];
10044 delete [] solution_;
10045 solution_ = new double[numberTotal2];
10046 assert (scalingFlag_ > 0);
10047 if (rowScale_ && rowScale_ != savedRowScale_)
10048 delete [] rowScale_;
10049 rowScale_ = NULL;
10050 // Do initial scaling
10051 delete [] savedRowScale_;
10052 savedRowScale_ = new double [4*maximumRows_];
10053 delete [] savedColumnScale_;
10054 savedColumnScale_ = new double [4*maximumColumns_];
10055 if (scalingFlag_ > 0) {
10056 rowScale_ = savedRowScale_;
10057 columnScale_ = savedColumnScale_;
10058 if (matrix_->scale(this)) {
10059 scalingFlag_ = -scalingFlag_; // not scaled after all
10060 assert (!rowScale_);
10061 }
10062 int numberRows2 = numberRows_ + numberExtraRows_;
10063 if (rowScale_) {
10064 CoinMemcpyN(rowScale_, 2 * numberRows2, savedRowScale_ + 2 * maximumRows_);
10065 CoinMemcpyN(columnScale_, 2 * numberColumns_, savedColumnScale_ + 2 * maximumColumns_);
10066 } else {
10067 abort();
10068 CoinFillN(savedRowScale_ + 2 * maximumRows_, 2 * numberRows2, 1.0);
10069 CoinFillN(savedColumnScale_ + 2 * maximumColumns_, 2 * numberColumns_, 1.0);
10070 }
10071 }
10072#else
10073 createRim(63);
10074#endif
10075 return true;
10076 } else {
10077 return false;
10078 }
10079}
10080#include "ClpNode.hpp"
10081//#define COIN_DEVELOP
10082// Fathom - 1 if solution
10083int
10084ClpSimplex::fathom(void * stuff)
10085{
10086 assert (stuff);
10087 ClpNodeStuff * info = reinterpret_cast<ClpNodeStuff *> (stuff);
10088 info->nNodes_ = 0;
10089 // say can declare optimal
10090 moreSpecialOptions_ |= 8;
10091 int saveMaxIterations = maximumIterations();
10092 setMaximumIterations((((moreSpecialOptions_&2048)==0) ? 100 : 2000)
10093 + 5 * (numberRows_ + numberColumns_));
10094 double saveObjLimit;
10095 getDblParam(ClpDualObjectiveLimit, saveObjLimit);
10096 if (perturbation_<100) {
10097 double limit = saveObjLimit * optimizationDirection_;
10098 setDblParam(ClpDualObjectiveLimit,
10099 (limit+1.0e-2+1.0e-7*fabs(limit))*optimizationDirection_);
10100 }
10101 #if 0
10102 bool onOptimal = (numberColumns_==100);
10103 double optVal[133];
10104 {
10105 memset(optVal, 0, sizeof(optVal));
10106#if 0
10107 int intIndicesV[] = {61, 62, 65, 66, 67, 68, 69, 70};
10108 double intSolnV[] = {4., 21., 4., 4., 6., 1., 25., 8.};
10109 int vecLen = sizeof(intIndicesV) / sizeof(int);
10110 for (int i = 0; i < vecLen; i++) {
10111 optVal[intIndicesV[i]] = intSolnV[i];
10112 }
10113#else
10114 int intIndicesAt1[] = { 0, 18, 25, 36, 44, 59, 61, 77, 82, 93 };
10115 int vecLen = sizeof(intIndicesAt1) / sizeof(int);
10116 for (int i = 0; i < vecLen; i++) {
10117 optVal[intIndicesAt1[i]] = 1;
10118 }
10119#endif
10120 }
10121 if (numberColumns_ == 100) {
10122 const char * integerType = integerInformation();
10123 for (int i = 0; i < 100; i++) {
10124 if (integerType[i]) {
10125 if (columnLower_[i] > optVal[i] || columnUpper_[i] < optVal[i]) {
10126 onOptimal = false;
10127 break;
10128 }
10129 }
10130 }
10131 if (onOptimal) {
10132 printf("On optimal path fathom\n");
10133 }
10134 }
10135#endif
10136 if (info->presolveType_) {
10137 // crunch down
10138 bool feasible = true;
10139 // Use dual region
10140 double * rhs = dual_;
10141 int * whichRow = new int[3*numberRows_];
10142 int * whichColumn = new int[2*numberColumns_];
10143 int nBound;
10144 bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true;
10145 ClpSimplex * small =
10146 static_cast<ClpSimplexOther *> (this)->crunch(rhs, whichRow, whichColumn,
10147 nBound, false, tightenBounds);
10148 if (small) {
10149 //double limit = 0.0;
10150 //getDblParam(ClpDualObjectiveLimit, limit);
10151 //printf("objlimit a %g",limit);
10152 //small->getDblParam(ClpDualObjectiveLimit, limit);
10153 //printf(" %g\n",limit);
10154 // pack down pseudocosts
10155 small->moreSpecialOptions_ = moreSpecialOptions_;
10156 if (info->upPseudo_) {
10157 const char * integerType2 = small->integerInformation();
10158 int n = small->numberColumns();
10159 int k = 0;
10160 int jColumn = 0;
10161 int j = 0;
10162 for (int i = 0; i < n; i++) {
10163 if (integerType2[i]) {
10164 int iColumn = whichColumn[i];
10165 // find
10166 while (jColumn != iColumn) {
10167 if (integerType_[jColumn])
10168 j++;
10169 jColumn++;
10170 }
10171 info->priority_[k] = info->priority_[j];
10172 info->upPseudo_[k] = info->upPseudo_[j];
10173 info->numberUp_[k] = info->numberUp_[j];
10174 info->numberUpInfeasible_[k] = info->numberUpInfeasible_[j];
10175 info->downPseudo_[k] = info->downPseudo_[j];
10176 info->numberDown_[k] = info->numberDown_[j];
10177 info->numberDownInfeasible_[k] = info->numberDownInfeasible_[j];
10178 assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40);
10179 assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40);
10180 k++;
10181 }
10182 }
10183 }
10184#if 0
10185 small->dual();
10186 if (small->problemStatus() == 0) {
10187 //problemStatus_ = 0;
10188 } else if (small->problemStatus() != 3) {
10189 feasible = false;
10190 } else {
10191 if (small->problemStatus_ == 3) {
10192 // may be problems
10193 printf("need coding from OsiClp for crunch\n");
10194 abort();
10195 }
10196 }
10197#endif
10198 } else {
10199 feasible = false;
10200 }
10201 int returnCode = 0;
10202 if (feasible) {
10203 info->presolveType_ = 0;
10204 // save and move pseudo costs
10205 returnCode = small->fathom(stuff);
10206 // restore pseudocosts
10207 if (info->upPseudo_) {
10208 int n = small->numberColumns();
10209 int * back = new int [numberColumns_];
10210 int numberIntegers = 0;
10211 for (int i = 0; i < numberColumns_; i++) {
10212 if (integerType_[i]) {
10213 back[i] = -10 - numberIntegers;
10214 numberIntegers++;
10215 } else {
10216 back[i] = -1;
10217 }
10218 }
10219 const char * integerType2 = small->integerInformation();
10220 int numberIntegers2 = 0;
10221 for (int i = 0; i < n; i++) {
10222 int iColumn = whichColumn[i];
10223 if (integerType2[i]) {
10224 int iBack = -back[iColumn];
10225 assert (iBack >= 10);
10226 iBack -= 10;
10227 back[iColumn] = iBack;
10228 numberIntegers2++;
10229 }
10230 }
10231 int k = numberIntegers2;
10232 for (int i = numberColumns_ - 1; i >= 0; i--) {
10233 int iBack = back[i];
10234 if (iBack <= -10) {
10235 // fixed integer
10236 numberIntegers--;
10237 info->numberUp_[numberIntegers] = -1; // say not updated
10238 } else if (iBack >= 0) {
10239 // not fixed integer
10240 numberIntegers--;
10241 k--;
10242 assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40);
10243 assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40);
10244 info->upPseudo_[numberIntegers] = info->upPseudo_[k];
10245 info->numberUp_[numberIntegers] = info->numberUp_[k];
10246 info->numberUpInfeasible_[numberIntegers] = info->numberUpInfeasible_[k];
10247 info->downPseudo_[numberIntegers] = info->downPseudo_[k];
10248 info->numberDown_[numberIntegers] = info->numberDown_[k];
10249 info->numberDownInfeasible_[numberIntegers] = info->numberDownInfeasible_[k];
10250 }
10251 }
10252 delete [] back;
10253 }
10254 if (returnCode) {
10255 bool fixBounds = (info->nNodes_ >= 0) ? true : false;
10256 //check this does everything
10257 static_cast<ClpSimplexOther *> (this)->afterCrunch(*small,
10258 whichRow, whichColumn, nBound);
10259 bool badSolution = false;
10260 for (int i = 0; i < numberColumns_; i++) {
10261 if (integerType_[i]) {
10262 double value = columnActivity_[i];
10263 double value2 = floor(value + 0.5);
10264 if (fabs(value - value2) >= 1.0e-4) {
10265 // Very odd - can't use
10266 badSolution = true;
10267 }
10268 columnActivity_[i] = value2;
10269 if (fixBounds) {
10270 columnLower_[i] = value2;
10271 columnUpper_[i] = value2;
10272 }
10273 }
10274 }
10275 if (badSolution) {
10276 info->nNodes_ = -1;
10277 returnCode = 0;
10278 }
10279 //setLogLevel(63);
10280 //double objectiveValue=doubleCheck();
10281 //printf("Solution of %g\n",objectiveValue);
10282 }
10283 delete small;
10284 }
10285 delete [] whichRow;
10286 delete [] whichColumn;
10287 setMaximumIterations(saveMaxIterations);
10288 setDblParam(ClpDualObjectiveLimit, saveObjLimit);
10289 return returnCode;
10290 }
10291 int returnCode = startFastDual2(info);
10292 if (returnCode) {
10293 stopFastDual2(info);
10294 setMaximumIterations(saveMaxIterations);
10295 setDblParam(ClpDualObjectiveLimit, saveObjLimit);
10296 return returnCode;
10297 }
10298 // Get fake bounds correctly
10299 //(static_cast<ClpSimplexDual *>(this))->resetFakeBounds(1);
10300 gutsOfSolution ( NULL, NULL);
10301 double dummyChange;
10302 (static_cast<ClpSimplexDual *>(this))->changeBounds(3, NULL, dummyChange);
10303 int saveNumberFake = numberFake_;
10304 int status = fastDual2(info);
10305#if 0
10306 {
10307 int iPivot;
10308 double * array = rowArray_[3]->denseVector();
10309 int i;
10310 for (iPivot = 0; iPivot < numberRows_; iPivot++) {
10311 int iSequence = pivotVariable_[iPivot];
10312 unpack(rowArray_[3], iSequence);
10313 factorization_->updateColumn(rowArray_[2], rowArray_[3]);
10314 assert (fabs(array[iPivot] - 1.0) < 1.0e-4);
10315 array[iPivot] = 0.0;
10316 for (i = 0; i < numberRows_; i++)
10317 assert (fabs(array[i]) < 1.0e-4);
10318 rowArray_[3]->clear();
10319 }
10320 }
10321#endif
10322 CoinAssert (problemStatus_ || objectiveValue_ < 1.0e50);
10323 if (status && problemStatus_ != 3) {
10324 // not finished - might be optimal
10325 checkPrimalSolution(rowActivityWork_, columnActivityWork_);
10326 double limit = 0.0;
10327 getDblParam(ClpDualObjectiveLimit, limit);
10328 //printf("objlimit b %g\n",limit);
10329 if (!numberPrimalInfeasibilities_ && objectiveValue()*optimizationDirection_ < limit) {
10330 problemStatus_ = 0;
10331 }
10332 status = problemStatus_;
10333 }
10334 if (problemStatus_ != 0 && problemStatus_ != 1) {
10335#ifdef COIN_DEVELOP
10336 printf("bad status %d on initial fast dual %d its\n", problemStatus_,
10337 numberIterations_);
10338#endif
10339 info->nNodes_ = -1;
10340 setMaximumIterations(saveMaxIterations);
10341 setDblParam(ClpDualObjectiveLimit, saveObjLimit);
10342 return 0;
10343 }
10344 int numberNodes = 1;
10345 int numberIterations = numberIterations_;
10346#if defined(COIN_DEVELOP) || !defined(NO_FATHOM_PRINT)
10347 int printFrequency = 2000;
10348#endif
10349 if (problemStatus_ == 1) {
10350 //printf("fathom infeasible on initial\n");
10351 stopFastDual2(info);
10352 info->numberNodesExplored_ = 1;
10353 info->numberIterations_ = numberIterations;
10354 setMaximumIterations(saveMaxIterations);
10355 setDblParam(ClpDualObjectiveLimit, saveObjLimit);
10356 return 0;
10357 } else if (problemStatus_ != 0) {
10358 stopFastDual2(info);
10359 info->numberNodesExplored_ = 1;
10360 info->numberIterations_ = numberIterations;
10361 setMaximumIterations(saveMaxIterations);
10362 setDblParam(ClpDualObjectiveLimit, saveObjLimit);
10363 // say bad
10364 info->nNodes_ = -1;
10365 return 0;
10366 }
10367 if (!columnScale_) {
10368 CoinMemcpyN(solution_, numberColumns_, columnActivity_);
10369 } else {
10370 assert(columnActivity_);
10371 assert(columnScale_);
10372 assert(solution_);
10373 int j;
10374 for (j = 0; j < numberColumns_; j++)
10375 columnActivity_[j] = solution_[j] * columnScale_[j];
10376 }
10377 double increment = info->integerIncrement_;
10378 int maxDepthSize = 10;
10379 int maxDepth = 0;
10380 int depth = 0;
10381 // Get fake bounds correctly
10382 (static_cast<ClpSimplexDual *>(this))->changeBounds(3, NULL, dummyChange);
10383 saveNumberFake = numberFake_;
10384 ClpNode ** nodes = new ClpNode * [maxDepthSize];
10385 int numberTotal = numberRows_ + numberColumns_;
10386 double * saveLower = CoinCopyOfArray(columnLower_, numberColumns_);
10387 double * saveUpper = CoinCopyOfArray(columnUpper_, numberColumns_);
10388 double * saveLowerInternal = CoinCopyOfArray(lower_, numberTotal);
10389 double * saveUpperInternal = CoinCopyOfArray(upper_, numberTotal);
10390 double * bestLower = NULL;
10391 double * bestUpper = NULL;
10392 int * back = new int [numberColumns_];
10393 int numberIntegers = 0;
10394 double sumChanges = 1.0e-5;
10395 int numberChanges = 1;
10396 for (int i = 0; i < numberColumns_; i++) {
10397 if (integerType_[i])
10398 back[i] = numberIntegers++;
10399 else
10400 back[i] = -1;
10401 }
10402 unsigned char * bestStatus = NULL;
10403 double bestObjective;
10404 getDblParam(ClpDualObjectiveLimit, bestObjective);
10405 double saveBestObjective = bestObjective;
10406 bool backtrack = false;
10407 bool printing = handler_->logLevel() > 0;
10408 while (depth >= 0) {
10409 // If backtrack get to correct depth
10410 if (backtrack) {
10411 depth--;
10412 while (depth >= 0) {
10413 if (!nodes[depth]->fathomed()) {
10414 nodes[depth]->changeState();
10415 break;
10416 }
10417 //if (printing)
10418 //printf("deleting node at depth %d\n",depth);
10419 //delete nodes[depth];
10420 //nodes[depth]=NULL;
10421 depth--;
10422 }
10423 if (depth < 0)
10424 break;
10425 // apply
10426 // First if backtracking we need to restore factorization, bounds and weights
10427 CoinMemcpyN(saveLowerInternal, numberTotal, lower_);
10428 CoinMemcpyN(saveUpperInternal, numberTotal, upper_);
10429 CoinMemcpyN(saveLower, numberColumns_, columnLower_);
10430 CoinMemcpyN(saveUpper, numberColumns_, columnUpper_);
10431 for (int i = 0; i < depth; i++) {
10432 nodes[i]->applyNode(this, 0);
10433 }
10434 nodes[depth]->applyNode(this, 1);
10435 int iColumn = nodes[depth]->sequence();
10436 if (printing)
10437 printf("after backtracking - applying node at depth %d - variable %d (%g,%g)\n",
10438 depth, iColumn,
10439 columnLower_[iColumn], columnUpper_[iColumn]);
10440 depth++;
10441 } else {
10442 // just bounds
10443 if (depth > 0) {
10444 nodes[depth-1]->applyNode(this, 0);
10445 int iColumn = nodes[depth-1]->sequence();
10446 if (printing)
10447 printf("No backtracking - applying node at depth-m %d - variable %d (%g,%g)\n",
10448 depth - 1, iColumn,
10449 columnLower_[iColumn], columnUpper_[iColumn]);
10450 }
10451 }
10452 // solve
10453#if 0
10454 {
10455 int iPivot;
10456 double * array = rowArray_[3]->denseVector();
10457 int i;
10458 for (iPivot = 0; iPivot < numberRows_; iPivot++) {
10459 int iSequence = pivotVariable_[iPivot];
10460 unpack(rowArray_[3], iSequence);
10461 factorization_->updateColumn(rowArray_[2], rowArray_[3]);
10462 assert (fabs(array[iPivot] - 1.0) < 1.0e-4);
10463 array[iPivot] = 0.0;
10464 for (i = 0; i < numberRows_; i++)
10465 assert (fabs(array[i]) < 1.0e-4);
10466 rowArray_[3]->clear();
10467 }
10468 }
10469#endif
10470#ifdef COIN_DEVELOP
10471 static int zzzzzz=0;
10472 zzzzzz++;
10473 if ((zzzzzz%100000)==0)
10474 printf("%d fathom solves\n",zzzzzz);
10475 if (zzzzzz==-1) {
10476 printf("TROUBLE\n");
10477 }
10478#endif
10479 // Get fake bounds correctly
10480 (static_cast<ClpSimplexDual *>(this))->changeBounds(3, NULL, dummyChange);
10481 fastDual2(info);
10482#if 0
10483 {
10484 int iPivot;
10485 double * array = rowArray_[3]->denseVector();
10486 int i;
10487 for (iPivot = 0; iPivot < numberRows_; iPivot++) {
10488 int iSequence = pivotVariable_[iPivot];
10489 unpack(rowArray_[3], iSequence);
10490 factorization_->updateColumn(rowArray_[2], rowArray_[3]);
10491 assert (fabs(array[iPivot] - 1.0) < 1.0e-4);
10492 array[iPivot] = 0.0;
10493 for (i = 0; i < numberRows_; i++)
10494 assert (fabs(array[i]) < 1.0e-4);
10495 rowArray_[3]->clear();
10496 }
10497 }
10498#endif
10499 // give up if odd
10500 if (problemStatus_ > 1) {
10501 info->nNodes_ = -1;
10502#ifdef COIN_DEVELOP
10503 printf("OUCH giving up on loop! %d %d %d %d - zzzzzz %d - max %d\n",
10504 numberNodes, numberIterations, problemStatus_, numberIterations_,zzzzzz,intParam_[0]);
10505 printf("xx %d\n", numberIterations*(numberRows_ + numberColumns_));
10506 //abort();
10507#endif
10508 break;
10509 }
10510 numberNodes++;
10511 numberIterations += numberIterations_;
10512 if ((numberNodes % 1000) == 0) {
10513#ifdef COIN_DEVELOP
10514 if ((numberNodes % printFrequency) == 0) {
10515 printf("Fathoming from node %d - %d nodes (%d iterations) - current depth %d\n",
10516 info->nodeCalled_,numberNodes,
10517 numberIterations, depth+info->startingDepth_);
10518 printFrequency *= 2;
10519 }
10520#elif !defined(NO_FATHOM_PRINT)
10521 if ((numberNodes % printFrequency) == 0) {
10522 if ((moreSpecialOptions_&2048)!=0)
10523 info->handler_->message(CLP_FATHOM_STATUS, messages_)
10524 << info->nodeCalled_ << numberNodes
10525 << numberIterations << depth+info->startingDepth_
10526 << CoinMessageEol;
10527 printFrequency *= 2;
10528 }
10529#endif
10530 if ((numberIterations*(numberRows_ + numberColumns_) > 5.0e10 ||
10531 numberNodes > 2.0e4) &&
10532 (moreSpecialOptions_&4096)==0) {
10533 // give up
10534 info->nNodes_ = -1;
10535#ifdef COIN_DEVELOP
10536 printf("OUCH giving up on nodes %d %d\n", numberNodes, numberIterations);
10537 printf("xx %d\n", numberIterations*(numberRows_ + numberColumns_));
10538 //abort();
10539#endif
10540 break;
10541 }
10542 }
10543 if (problemStatus_ == 1 ||
10544 (problemStatus_ == 0 && objectiveValue()*optimizationDirection_ > bestObjective)) {
10545 backtrack = true;
10546 if (printing)
10547 printf("infeasible at depth %d\n", depth);
10548 if (depth > 0) {
10549 int way = nodes[depth-1]->way();
10550 int sequence = nodes[depth-1]->sequence();
10551#ifndef NDEBUG
10552 double branchingValue = nodes[depth-1]->branchingValue();
10553 if (way > 0)
10554 assert (columnLower_[sequence] == ceil(branchingValue));
10555 else
10556 assert (columnUpper_[sequence] == floor(branchingValue));
10557#endif
10558 sequence = back[sequence];
10559 double change = bestObjective - nodes[depth-1]->objectiveValue();
10560 if (change > 1.0e10)
10561 change = 10.0 * sumChanges / (1.0 + numberChanges);
10562 info->update(way, sequence, change, false);
10563 }
10564 } else if (problemStatus_ != 0) {
10565 abort();
10566 } else {
10567 // Create node
10568 ClpNode * node;
10569 computeDuals(NULL);
10570 if (depth > 0) {
10571 int way = nodes[depth-1]->way();
10572 int sequence = nodes[depth-1]->sequence();
10573#ifndef NDEBUG
10574 double branchingValue = nodes[depth-1]->branchingValue();
10575 if (way > 0)
10576 assert (columnLower_[sequence] == ceil(branchingValue));
10577 else
10578 assert (columnUpper_[sequence] == floor(branchingValue));
10579#endif
10580 sequence = back[sequence];
10581 info->update(way, sequence,
10582 objectiveValue() - nodes[depth-1]->objectiveValue(),
10583 true);
10584 numberChanges++;
10585 sumChanges += objectiveValue() - nodes[depth-1]->objectiveValue();
10586 }
10587 if (depth < maxDepth) {
10588 node = nodes[depth];
10589 node->gutsOfConstructor(this, info, 1, depth);
10590 } else {
10591 node = new ClpNode(this, info, depth);
10592 if (depth == maxDepthSize) {
10593 maxDepthSize = 2 * maxDepthSize + 10;
10594 ClpNode ** temp = new ClpNode * [maxDepthSize];
10595 for (int i = 0; i < depth; i++)
10596 temp[i] = nodes[i];
10597 delete [] nodes;
10598 nodes = temp;
10599 }
10600 nodes[maxDepth++] = node;
10601 }
10602#if 0
10603 if (numberColumns_ == 100 && onOptimal) {
10604 const char * integerType = integerInformation();
10605 bool localOptimal=true;
10606 for (int i = 0; i < 100; i++) {
10607 if (integerType[i]) {
10608 if (columnLower_[i] > optVal[i] || columnUpper_[i] < optVal[i]) {
10609 localOptimal = false;
10610 printf("bad %d %g %g %g\n", i, columnLower_[i], optVal[i],
10611 columnUpper_[i]);
10612 break;
10613 }
10614 }
10615 }
10616 if (localOptimal) {
10617 printf("still on optimal\n");
10618 }
10619 assert (onOptimal);
10620 }
10621#endif
10622 double objectiveValue=0.0;
10623 if (node->sequence() < 0) {
10624 objectiveValue = doubleCheck();
10625 node->gutsOfConstructor(this, info, 1, depth);
10626 }
10627 if (node->sequence() < 0) {
10628 // solution
10629 //double objectiveValue = doubleCheck();
10630 if (objectiveValue < bestObjective) {
10631#ifdef COIN_DEVELOP
10632 printf("Fathoming from node %d - solution of %g after %d nodes at depth %d\n",
10633 info->nodeCalled_,objectiveValue,
10634 numberNodes, depth+info->startingDepth_);
10635#elif !defined(NO_FATHOM_PRINT)
10636 if ((moreSpecialOptions_&2048)!=0)
10637 info->handler_->message(CLP_FATHOM_SOLUTION, messages_)
10638 << info->nodeCalled_ << objectiveValue
10639 << numberNodes << depth+info->startingDepth_
10640 << CoinMessageEol;
10641#endif
10642 // later then lower_ not columnLower_ (and total?)
10643 delete [] bestLower;
10644 bestLower = CoinCopyOfArray(columnLower_, numberColumns_);
10645 delete [] bestUpper;
10646 bestUpper = CoinCopyOfArray(columnUpper_, numberColumns_);
10647 delete [] bestStatus;
10648 bestStatus = CoinCopyOfArray(status_, numberTotal);
10649 bestObjective = objectiveValue - increment;
10650 if (perturbation_<100)
10651 bestObjective += 1.0e-2+1.0e-7*fabs(bestObjective);
10652 setDblParam(ClpDualObjectiveLimit, bestObjective * optimizationDirection_);
10653 } else {
10654 //#define CLP_INVESTIGATE
10655#ifdef COIN_DEVELOP
10656 printf("why bad solution feasible\n");
10657#endif
10658 }
10659 //delete node;
10660 backtrack = true;
10661 } else {
10662 if (printing)
10663 printf("depth %d variable %d\n", depth, node->sequence());
10664 depth++;
10665 backtrack = false;
10666 //nodes[depth++] = new ClpNode (this,info);
10667 }
10668 }
10669 }
10670 if (!info->nNodes_)
10671 assert (depth == -1);
10672 for (int i = 0; i < maxDepth; i++)
10673 delete nodes[i];
10674 delete [] nodes;
10675 delete [] back;
10676 stopFastDual2(info);
10677#ifndef NO_FATHOM_PRINT
10678 if ((moreSpecialOptions_&2048)!=0 && numberNodes >= 10000)
10679 info->handler_->message(CLP_FATHOM_FINISH, messages_)
10680 << info->nodeCalled_ << info->startingDepth_
10681 << numberNodes << numberIterations << maxDepth+info->startingDepth_
10682 << CoinMessageEol;
10683#endif
10684 //printf("fathom finished after %d nodes\n",numberNodes);
10685 if (bestStatus) {
10686 CoinMemcpyN(bestLower, numberColumns_, columnLower_);
10687 CoinMemcpyN(bestUpper, numberColumns_, columnUpper_);
10688 CoinMemcpyN(bestStatus, numberTotal, status_);
10689 delete [] bestLower;
10690 delete [] bestUpper;
10691 delete [] bestStatus;
10692 setDblParam(ClpDualObjectiveLimit, saveBestObjective);
10693 saveObjLimit = saveBestObjective;
10694 int saveOptions = specialOptions_;
10695 specialOptions_ &= ~65536;
10696 dual();
10697 specialOptions_ = saveOptions;
10698 info->numberNodesExplored_ = numberNodes;
10699 info->numberIterations_ = numberIterations;
10700 returnCode = 1;
10701 } else {
10702 info->numberNodesExplored_ = numberNodes;
10703 info->numberIterations_ = numberIterations;
10704 returnCode = 0;
10705 }
10706 if (info->nNodes_ < 0) {
10707 if (lower_) {
10708 CoinMemcpyN(saveLowerInternal, numberTotal, lower_);
10709 CoinMemcpyN(saveUpperInternal, numberTotal, upper_);
10710 numberFake_ = saveNumberFake;
10711 }
10712 CoinMemcpyN(saveLower, numberColumns_, columnLower_);
10713 CoinMemcpyN(saveUpper, numberColumns_, columnUpper_);
10714 }
10715 delete [] saveLower;
10716 delete [] saveUpper;
10717 delete [] saveLowerInternal;
10718 delete [] saveUpperInternal;
10719 setMaximumIterations(saveMaxIterations);
10720 setDblParam(ClpDualObjectiveLimit, saveObjLimit);
10721 return returnCode;
10722}
10723//#define CHECK_PATH
10724#ifdef CHECK_PATH
10725const double * debuggerSolution_Z = NULL;
10726int numberColumns_Z = -1;
10727int gotGoodNode_Z = -1;
10728#endif
10729/* Do up to N deep - returns
10730 -1 - no solution nNodes_ valid nodes
10731 >= if solution and that node gives solution
10732 ClpNode array is 2**N long. Values for N and
10733 array are in stuff (nNodes_ also in stuff) */
10734int
10735ClpSimplex::fathomMany(void * stuff)
10736{
10737 assert (stuff);
10738 ClpNodeStuff * info = reinterpret_cast<ClpNodeStuff *> (stuff);
10739 int nNodes = info->maximumNodes();
10740 int putNode = info->maximumSpace();
10741 int goodNodes = 0;
10742 info->nNodes_ = 0;
10743 ClpNode ** nodeInfo = info->nodeInfo_;
10744 assert (nodeInfo);
10745 // say can declare optimal
10746 moreSpecialOptions_ |= 8;
10747 double limit = 0.0;
10748 getDblParam(ClpDualObjectiveLimit, limit);
10749 for (int j = 0; j < putNode; j++) {
10750 if (nodeInfo[j]) {
10751 nodeInfo[j]->setObjectiveValue(limit);
10752 if (info->large_)
10753 nodeInfo[j]->cleanUpForCrunch();
10754 }
10755 }
10756#ifdef CHECK_PATH
10757 // Note - if code working can get assert on startOptimal==2 (if finds)
10758 int startOptimal = 0;
10759 if (numberColumns_ == numberColumns_Z) {
10760 assert (debuggerSolution_Z);
10761 startOptimal = 1;
10762 for (int i = 0; i < numberColumns_; i++) {
10763 if (columnUpper_[i] < debuggerSolution_Z[i] || columnLower_[i] > debuggerSolution_Z[i]) {
10764 startOptimal = 0;
10765 break;
10766 }
10767 }
10768 if (startOptimal) {
10769 printf("starting on optimal\n");
10770 }
10771 } else if (info->large_ && info->large_->numberColumns_ == numberColumns_Z) {
10772 assert (debuggerSolution_Z);
10773 startOptimal = 1;
10774 for (int i = 0; i < info->large_->numberColumns_; i++) {
10775 if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) {
10776 startOptimal = 0;
10777 break;
10778 }
10779 }
10780 if (startOptimal) {
10781 printf("starting on optimal (presolved) %d\n", numberColumns_);
10782 }
10783 }
10784#endif
10785 int whichSolution = -1;
10786 if (info->presolveType_) {
10787 // crunch down
10788 bool feasible = true;
10789 // Use dual region
10790 double * rhs = dual_;
10791 int * whichRow = new int[3*numberRows_];
10792 int * whichColumn = new int[2*numberColumns_];
10793 int nBound;
10794 bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true;
10795 ClpSimplex * small =
10796 static_cast<ClpSimplexOther *> (this)->crunch(rhs, whichRow, whichColumn,
10797 nBound, false, tightenBounds);
10798 if (small) {
10799 info->large_ = this;
10800 info->whichRow_ = whichRow;
10801 info->whichColumn_ = whichColumn;
10802 info->nBound_ = nBound;
10803 //double limit = 0.0;
10804 //getDblParam(ClpDualObjectiveLimit, limit);
10805 //printf("objlimit a %g",limit);
10806 //small->getDblParam(ClpDualObjectiveLimit, limit);
10807 //printf(" %g\n",limit);
10808 // pack down pseudocosts
10809 if (info->upPseudo_) {
10810 const char * integerType2 = small->integerInformation();
10811 int n = small->numberColumns();
10812 int k = 0;
10813 int jColumn = 0;
10814 int j = 0;
10815 for (int i = 0; i < n; i++) {
10816 if (integerType2[i]) {
10817 int iColumn = whichColumn[i];
10818 // find
10819 while (jColumn != iColumn) {
10820 if (integerType_[jColumn])
10821 j++;
10822 jColumn++;
10823 }
10824 info->upPseudo_[k] = info->upPseudo_[j];
10825 info->numberUp_[k] = info->numberUp_[j];
10826 info->numberUpInfeasible_[k] = info->numberUpInfeasible_[j];
10827 info->downPseudo_[k] = info->downPseudo_[j];
10828 info->numberDown_[k] = info->numberDown_[j];
10829 info->numberDownInfeasible_[k] = info->numberDownInfeasible_[j];
10830 assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40);
10831 assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40);
10832 k++;
10833 }
10834 }
10835 }
10836 } else {
10837 feasible = false;
10838 }
10839 if (feasible) {
10840 info->presolveType_ = 0;
10841 // save and move pseudo costs
10842 whichSolution = small->fathomMany(stuff);
10843 // restore pseudocosts
10844 if (info->upPseudo_) {
10845 int n = small->numberColumns();
10846 int * back = new int [numberColumns_];
10847 int numberIntegers = 0;
10848 for (int i = 0; i < numberColumns_; i++) {
10849 if (integerType_[i]) {
10850 back[i] = -10 - numberIntegers;
10851 numberIntegers++;
10852 } else {
10853 back[i] = -1;
10854 }
10855 }
10856 const char * integerType2 = small->integerInformation();
10857 int numberIntegers2 = 0;
10858 for (int i = 0; i < n; i++) {
10859 int iColumn = whichColumn[i];
10860 if (integerType2[i]) {
10861 int iBack = -back[iColumn];
10862 assert (iBack >= 10);
10863 iBack -= 10;
10864 back[iColumn] = iBack;
10865 numberIntegers2++;
10866 }
10867 }
10868 int k = numberIntegers2;
10869 for (int i = numberColumns_ - 1; i >= 0; i--) {
10870 int iBack = back[i];
10871 if (iBack <= -10) {
10872 // fixed integer
10873 numberIntegers--;
10874 info->numberUp_[numberIntegers] = -1; // say not updated
10875 } else if (iBack >= 0) {
10876 // not fixed integer
10877 numberIntegers--;
10878 k--;
10879 assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40);
10880 assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40);
10881 info->upPseudo_[numberIntegers] = info->upPseudo_[k];
10882 info->numberUp_[numberIntegers] = info->numberUp_[k];
10883 info->numberUpInfeasible_[numberIntegers] = info->numberUpInfeasible_[k];
10884 info->downPseudo_[numberIntegers] = info->downPseudo_[k];
10885 info->numberDown_[numberIntegers] = info->numberDown_[k];
10886 info->numberDownInfeasible_[numberIntegers] = info->numberDownInfeasible_[k];
10887 }
10888 }
10889 delete [] back;
10890 }
10891 delete small;
10892 }
10893 info->large_ = NULL;
10894 info->whichRow_ = NULL;
10895 info->whichColumn_ = NULL;
10896 delete [] whichRow;
10897 delete [] whichColumn;
10898 return whichSolution;
10899 }
10900#ifndef DEBUG
10901 {
10902 int nBasic = 0;
10903 int i;
10904 for (i = 0; i < numberRows_ + numberColumns_; i++) {
10905 if (getColumnStatus(i) == basic)
10906 nBasic++;
10907 }
10908 assert (nBasic == numberRows_);
10909 }
10910#endif
10911 int returnCode = startFastDual2(info);
10912 if (returnCode) {
10913 stopFastDual2(info);
10914 abort();
10915 return -1;
10916 }
10917 gutsOfSolution ( NULL, NULL);
10918 int status = fastDual2(info);
10919 CoinAssert (problemStatus_ || objectiveValue_ < 1.0e50);
10920 if (status && problemStatus_ != 3) {
10921 // not finished - might be optimal
10922 checkPrimalSolution(rowActivityWork_, columnActivityWork_);
10923 double limit = 0.0;
10924 getDblParam(ClpDualObjectiveLimit, limit);
10925 //printf("objlimit b %g\n",limit);
10926 if (!numberPrimalInfeasibilities_ && objectiveValue()*optimizationDirection_ < limit) {
10927 problemStatus_ = 0;
10928 }
10929 status = problemStatus_;
10930 }
10931 assert (problemStatus_ == 0 || problemStatus_ == 1); //(static_cast<ClpSimplexDual *> this)->dual(0,0);
10932 if (problemStatus_ == 10) {
10933 printf("Cleaning up with primal - need coding without createRim!\n");
10934 abort();
10935 }
10936 int numberNodes = 0;
10937 int numberIterations = numberIterations_;
10938 if (problemStatus_ == 1) {
10939 //printf("fathom infeasible on initial\n");
10940 stopFastDual2(info);
10941 info->nNodes_ = 0;
10942 info->numberNodesExplored_ = 0;
10943 info->numberIterations_ = numberIterations;
10944 return -1;
10945 } else if (problemStatus_ != 0) {
10946 abort();
10947 }
10948 if (!columnScale_) {
10949 CoinMemcpyN(solution_, numberColumns_, columnActivity_);
10950 } else {
10951 assert(columnActivity_);
10952 assert(columnScale_);
10953 assert(solution_);
10954 int j;
10955 for (j = 0; j < numberColumns_; j++)
10956 columnActivity_[j] = solution_[j] * columnScale_[j];
10957 }
10958 double increment = info->integerIncrement_;
10959 int depth = 0;
10960 int numberTotal = numberRows_ + numberColumns_;
10961 double * saveLower = CoinCopyOfArray(columnLower_, numberColumns_);
10962 double * saveUpper = CoinCopyOfArray(columnUpper_, numberColumns_);
10963 double * saveLowerInternal = CoinCopyOfArray(lower_, numberTotal);
10964 double * saveUpperInternal = CoinCopyOfArray(upper_, numberTotal);
10965 //double * bestLower = NULL;
10966 //double * bestUpper = NULL;
10967 int * back = new int [numberColumns_];
10968 int numberIntegers = 0;
10969 double sumChanges = 1.0e-5;
10970 int numberChanges = 1;
10971 for (int i = 0; i < numberColumns_; i++) {
10972 if (integerType_[i])
10973 back[i] = numberIntegers++;
10974 else
10975 back[i] = -1;
10976 }
10977 //unsigned char * bestStatus = NULL;
10978 double bestObjective;
10979 getDblParam(ClpDualObjectiveLimit, bestObjective);
10980 double saveBestObjective = bestObjective;
10981 bool backtrack = false;
10982 bool printing = handler_->logLevel() > 0;
10983#ifdef CHECK_PATH
10984 if (startOptimal)
10985 printing = true;
10986#endif
10987 /* Use nodeInfo for storage
10988 depth 0 will be putNode-1, 1 putNode-2 etc */
10989 int useDepth = putNode - 1;
10990 bool justDive = (info->solverOptions_ & 32) != 0;
10991 //printf("putNode %d nDepth %d\n");
10992 while (depth >= 0) {
10993 bool stopAtOnce = false;
10994 // If backtrack get to correct depth
10995 if (backtrack) {
10996 depth--;
10997 useDepth++;
10998 while (depth >= 0) {
10999 if (!nodeInfo[useDepth]->fathomed()) {
11000 nodeInfo[useDepth]->changeState();
11001 break;
11002 }
11003 //if (printing)
11004 //printf("deleting node at depth %d\n",depth);
11005 //delete nodes[useDepth];
11006 //nodes[useDepth]=NULL;
11007 depth--;
11008 useDepth++;
11009 }
11010 if (depth < 0)
11011 break;
11012 // apply
11013 // First if backtracking we need to restore factorization, bounds and weights
11014 CoinMemcpyN(saveLowerInternal, numberTotal, lower_);
11015 CoinMemcpyN(saveUpperInternal, numberTotal, upper_);
11016 CoinMemcpyN(saveLower, numberColumns_, columnLower_);
11017 CoinMemcpyN(saveUpper, numberColumns_, columnUpper_);
11018 for (int i = 0; i < depth; i++) {
11019 nodeInfo[putNode-1-i]->applyNode(this, 0);
11020 }
11021 nodeInfo[useDepth]->applyNode(this, 1);
11022 if (justDive)
11023 stopAtOnce = true;
11024 int iColumn = nodeInfo[useDepth]->sequence();
11025 if (printing)
11026 printf("after backtracking - applying node at depth %d - variable %d (%g,%g)\n",
11027 depth, iColumn,
11028 columnLower_[iColumn], columnUpper_[iColumn]);
11029 depth++;
11030 useDepth--;
11031 } else {
11032 // just bounds
11033 if (depth > 0) {
11034 // Choose variable here!!
11035 nodeInfo[useDepth+1]->chooseVariable(this, info);
11036 nodeInfo[useDepth+1]->applyNode(this, 0);
11037 int iColumn = nodeInfo[useDepth+1]->sequence();
11038 if (printing)
11039 printf("No backtracking - applying node at depth-m %d - variable %d (%g,%g)\n",
11040 depth - 1, iColumn,
11041 columnLower_[iColumn], columnUpper_[iColumn]);
11042 }
11043 }
11044 // solve
11045 double dummyChange;
11046 (static_cast<ClpSimplexDual *>(this))->changeBounds(3, NULL, dummyChange);
11047 //int saveNumberFake = numberFake_;
11048 fastDual2(info);
11049 numberNodes++;
11050 numberIterations += numberIterations_;
11051 if ((numberNodes % 1000) == 0 && printing)
11052 printf("After %d nodes (%d iterations) - best solution %g - current depth %d\n",
11053 numberNodes, numberIterations, bestObjective, depth);
11054 if (problemStatus_ == 1 ||
11055 (problemStatus_ == 0 && objectiveValue()*optimizationDirection_ > bestObjective)) {
11056 backtrack = true;
11057 if (printing)
11058 printf("infeasible at depth %d\n", depth);
11059#ifdef CHECK_PATH
11060 if (startOptimal && numberColumns_ == numberColumns_Z) {
11061 bool onOptimal = true;
11062 for (int i = 0; i < numberColumns_; i++) {
11063 if (columnUpper_[i] < debuggerSolution_Z[i] || columnLower_[i] > debuggerSolution_Z[i]) {
11064 onOptimal = false;
11065 break;
11066 }
11067 }
11068 if (onOptimal) {
11069 printf("INF on optimal fathom at depth %d\n", depth);
11070 abort();
11071 }
11072 } else if (info->large_ && startOptimal && info->large_->numberColumns_ == numberColumns_Z) {
11073 bool onOptimal = true;
11074 for (int i = 0; i < info->large_->numberColumns_; i++) {
11075 if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) {
11076 onOptimal = false;
11077 break;
11078 }
11079 }
11080 if (onOptimal) {
11081 printf("INF on optimal (pre) fathom at depth %d\n", depth);
11082 writeMps("fathom_pre.mps");
11083 abort();
11084 }
11085 }
11086#endif
11087 if (depth > 0) {
11088 int way = nodeInfo[useDepth+1]->way();
11089 int sequence = nodeInfo[useDepth+1]->sequence();
11090#ifndef NDEBUG
11091 double branchingValue = nodeInfo[useDepth+1]->branchingValue();
11092 if (way > 0)
11093 assert (columnLower_[sequence] == ceil(branchingValue));
11094 else
11095 assert (columnUpper_[sequence] == floor(branchingValue));
11096#endif
11097 sequence = back[sequence];
11098 double change = bestObjective - nodeInfo[useDepth+1]->objectiveValue();
11099 if (change > 1.0e10)
11100 change = 10.0 * sumChanges / (1.0 + numberChanges);
11101 info->update(way, sequence, change, false);
11102 }
11103 } else if (problemStatus_ != 0) {
11104 abort();
11105 } else {
11106 // Create node
11107 ClpNode * node;
11108 computeDuals(NULL);
11109 if (depth > 0) {
11110 int way = nodeInfo[useDepth+1]->way();
11111 int sequence = nodeInfo[useDepth+1]->sequence();
11112#ifndef NDEBUG
11113 double branchingValue = nodeInfo[useDepth+1]->branchingValue();
11114 if (way > 0)
11115 assert (columnLower_[sequence] == ceil(branchingValue));
11116 else
11117 assert (columnUpper_[sequence] == floor(branchingValue));
11118#endif
11119 sequence = back[sequence];
11120 info->update(way, sequence,
11121 objectiveValue() - nodeInfo[useDepth+1]->objectiveValue(),
11122 true);
11123 numberChanges++;
11124 sumChanges += objectiveValue() - nodeInfo[useDepth+1]->objectiveValue();
11125 }
11126#ifdef CHECK_PATH
11127 if (startOptimal && numberColumns_ == numberColumns_Z) {
11128 bool onOptimal = true;
11129 for (int i = 0; i < numberColumns_; i++) {
11130 if (columnUpper_[i] < debuggerSolution_Z[i] || columnLower_[i] > debuggerSolution_Z[i]) {
11131 onOptimal = false;
11132 break;
11133 }
11134 }
11135 if (onOptimal) {
11136 if (depth >= info->nDepth_) {
11137 printf("on optimal fathom at full depth %d %d %g\n",
11138 depth, goodNodes, objectiveValue());
11139 gotGoodNode_Z = goodNodes;
11140 startOptimal = 2;
11141 } else {
11142 printf("on optimal fathom at depth %d\n", depth);
11143 }
11144 }
11145 } else if (info->large_ && startOptimal && info->large_->numberColumns_ == numberColumns_Z) {
11146 bool onOptimal = true;
11147 // Fix bounds in large
11148 for (int i = 0; i < numberColumns_; i++) {
11149 if (integerType_[i]) {
11150 int iColumn = info->whichColumn_[i];
11151 info->large_->columnUpper_[iColumn] = columnUpper_[i];
11152 info->large_->columnLower_[iColumn] = columnLower_[i];
11153 COIN_DETAIL_PRINT(printf("%d dj %g dual %g scale %g\n",
11154 iColumn, dj_[i], reducedCost_[i], columnScale_[i]));
11155
11156 }
11157 }
11158 for (int i = 0; i < info->large_->numberColumns_; i++) {
11159 if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) {
11160 onOptimal = false;
11161 break;
11162 }
11163 }
11164 if (onOptimal) {
11165 if (depth >= info->nDepth_) {
11166 printf("on (pre) tentative optimal fathom at full depth %d %d %g\n",
11167 depth, goodNodes, objectiveValue());
11168 for (int i = 0; i < info->large_->numberColumns_; i++)
11169 printf("fathomA %d %g %g\n", i, info->large_->columnLower_[i],
11170 info->large_->columnUpper_[i]);
11171 } else {
11172 printf("on (pre) optimal fathom at depth %d\n", depth);
11173 }
11174 }
11175 }
11176#endif
11177 if (depth < info->nDepth_ && !stopAtOnce) {
11178 node = nodeInfo[useDepth];
11179 if (node) {
11180 node->gutsOfConstructor(this, info, 1, depth);
11181 } else {
11182 node = new ClpNode(this, info, depth);
11183 nodeInfo[useDepth] = node;
11184 }
11185 } else {
11186 // save
11187 node = nodeInfo[goodNodes];
11188 if (!node) {
11189 node = new ClpNode(this, info, depth);
11190 nodeInfo[goodNodes] = node;
11191 }
11192 if (!node->oddArraysExist())
11193 node->createArrays(this);
11194 node->gutsOfConstructor(this, info, 2, depth);
11195 }
11196 if (node->sequence() < 0) {
11197 // solution
11198 double objectiveValue = doubleCheck();
11199 if (printing)
11200 printf("Solution of %g after %d nodes at depth %d\n",
11201 objectiveValue, numberNodes, depth);
11202 if (objectiveValue < bestObjective && !problemStatus_) {
11203 // make sure node exists
11204 node = nodeInfo[goodNodes];
11205 if (!node) {
11206 node = new ClpNode(this, info, depth);
11207 nodeInfo[goodNodes] = node;
11208 }
11209 if (info->large_) {
11210 //check this does everything
11211 // Fix bounds in large
11212 for (int i = 0; i < numberColumns_; i++) {
11213 if (integerType_[i]) {
11214 int iColumn = info->whichColumn_[i];
11215 info->large_->columnUpper_[iColumn] = columnUpper_[i];
11216 info->large_->columnLower_[iColumn] = columnLower_[i];
11217 }
11218 }
11219 static_cast<ClpSimplexOther *> (info->large_)->afterCrunch(*this,
11220 info->whichRow_, info->whichColumn_, info->nBound_);
11221 // do as for large
11222 if (!node->oddArraysExist())
11223 node->createArrays(info->large_);
11224 node->gutsOfConstructor(info->large_, info, 2, depth);
11225 } else {
11226 if (!node->oddArraysExist())
11227 node->createArrays(this);
11228 node->gutsOfConstructor(this, info, 2, depth);
11229 }
11230 whichSolution = goodNodes;
11231 goodNodes++;
11232 if (goodNodes >= nNodes)
11233 justDive = true; // clean up phase
11234 assert (node->sequence() < 0);
11235 bestObjective = objectiveValue - increment;
11236 setDblParam(ClpDualObjectiveLimit, bestObjective * optimizationDirection_);
11237 } else {
11238#ifdef CLP_INVESTIGATE
11239 printf("why bad solution feasible\n");
11240 abort();
11241#endif
11242 }
11243 backtrack = true;
11244 } else {
11245 //if (printing)
11246 //printf("depth %d variable %d\n",depth,node->sequence());
11247 if (depth == info->nDepth_ || stopAtOnce) {
11248 if (info->large_) {
11249 //check this does everything
11250 // Fix bounds in large
11251 for (int i = 0; i < numberColumns_; i++) {
11252 if (integerType_[i]) {
11253 int iColumn = info->whichColumn_[i];
11254 info->large_->columnUpper_[iColumn] = columnUpper_[i];
11255 info->large_->columnLower_[iColumn] = columnLower_[i];
11256 }
11257 }
11258#ifdef CHECK_PATH
11259 if (startOptimal)
11260 for (int i = 0; i < info->large_->numberColumns_; i++)
11261 printf("fathomB %d %g %g %g\n", i, info->large_->columnLower_[i],
11262 info->large_->columnUpper_[i],
11263 node->dualSolution()[i]);
11264#endif
11265 static_cast<ClpSimplexOther *> (info->large_)->afterCrunch(*this,
11266 info->whichRow_, info->whichColumn_, info->nBound_);
11267#ifdef CHECK_PATH
11268 if (startOptimal) {
11269 bool onOptimal = true;
11270 for (int i = 0; i < info->large_->numberColumns_; i++)
11271 printf("fathomC %d %g %g\n", i, info->large_->columnLower_[i],
11272 info->large_->columnUpper_[i]);
11273 for (int i = 0; i < info->large_->numberColumns_; i++) {
11274 if (info->large_->columnUpper_[i] < debuggerSolution_Z[i] || info->large_->columnLower_[i] > debuggerSolution_Z[i]) {
11275 onOptimal = false;
11276 break;
11277 }
11278 }
11279 if (onOptimal) {
11280 printf("on (pre) optimal fathom at full depth %d %d %g\n",
11281 depth, goodNodes, info->large_->objectiveValue());
11282 startOptimal = 2;
11283 gotGoodNode_Z = goodNodes;
11284 for (int i = 0; i < info->large_->numberColumns_; i++)
11285 printf("fathom %d %g %g\n", i, info->large_->columnLower_[i],
11286 info->large_->columnUpper_[i]);
11287 }
11288 }
11289#endif
11290 // do as for large
11291 node->gutsOfConstructor(info->large_, info, 2, depth);
11292 }
11293 goodNodes++;
11294 if (goodNodes >= nNodes)
11295 justDive = true; // clean up phase
11296 backtrack = true;
11297 } else {
11298 depth++;
11299 useDepth--;
11300 backtrack = false;
11301 }
11302 }
11303 }
11304 }
11305 //printf("nNodes %d nDepth %d, useDepth %d goodNodes %d\n",
11306 // nNodes,info->nDepth_,useDepth,goodNodes);
11307#ifdef CHECK_PATH
11308 if (startOptimal) {
11309 assert(startOptimal == 2);
11310 printf("got fathomed optimal at end %d\n", startOptimal);
11311 if (startOptimal != 2)
11312 abort();
11313 }
11314#endif
11315 assert (depth == -1);
11316 delete [] saveLower;
11317 delete [] saveUpper;
11318 delete [] saveLowerInternal;
11319 delete [] saveUpperInternal;
11320 delete [] back;
11321 //printf("fathom finished after %d nodes\n",numberNodes);
11322 if (whichSolution >= 0) {
11323 setDblParam(ClpDualObjectiveLimit, saveBestObjective);
11324 }
11325 stopFastDual2(info);
11326 info->nNodes_ = goodNodes;
11327 info->numberNodesExplored_ = numberNodes;
11328 info->numberIterations_ = numberIterations;
11329 return whichSolution;
11330}
11331// Double checks OK
11332double
11333ClpSimplex::doubleCheck()
11334{
11335#if 0
11336 double * solution = CoinCopyOfArray(solution_, numberColumns_ + numberRows_);
11337 gutsOfSolution ( NULL, NULL);
11338 for (int i = 0; i < numberColumns_; i++) {
11339 if (fabs(solution[i] - solution_[i]) > 1.0e-7)
11340 printf("bada %d bad %g good %g\n",
11341 i, solution[i], solution_[i]);
11342 }
11343 //abort();
11344#endif
11345 dual(0, 7);
11346#if 0
11347 for (int i = 0; i < numberColumns_; i++) {
11348 if (fabs(solution[i] - solution_[i]) > 1.0e-7)
11349 printf("badb %d bad %g good %g\n",
11350 i, solution[i], solution_[i]);
11351 }
11352 dual(0, 1);
11353 for (int i = 0; i < numberColumns_; i++) {
11354 if (fabs(solution[i] - solution_[i]) > 1.0e-7)
11355 printf("badc %d bad %g good %g\n",
11356 i, solution[i], solution_[i]);
11357 }
11358 delete [] solution;
11359#endif
11360 return objectiveValue() * optimizationDirection_;
11361}
11362// Start Fast dual
11363int
11364ClpSimplex::startFastDual2(ClpNodeStuff * info)
11365{
11366 info->saveOptions_ = specialOptions_;
11367 assert ((info->solverOptions_ & 65536) == 0);
11368 info->solverOptions_ |= 65536;
11369 if ((specialOptions_ & 65536) == 0) {
11370 factorization_->setPersistenceFlag(2);
11371 } else {
11372 factorization_->setPersistenceFlag(2);
11373 startPermanentArrays();
11374 }
11375 //assert (!lower_);
11376 // create modifiable copies of model rim and do optional scaling
11377 createRim(7 + 8 + 16 + 32, true, 0);
11378#ifndef NDEBUG
11379 ClpPackedMatrix* clpMatrix =
11380 dynamic_cast< ClpPackedMatrix*>(matrix_);
11381 assert (clpMatrix && (clpMatrix->flags() & 1) == 0);
11382#endif
11383 // mark all as current
11384 whatsChanged_ = 0x3ffffff;
11385
11386 // change newLower and newUpper if scaled
11387
11388 // Do initial factorization
11389 // and set certain stuff
11390 // We can either set increasing rows so ...IsBasic gives pivot row
11391 // or we can just increment iBasic one by one
11392 // for now let ...iBasic give pivot row
11393 int factorizationStatus = internalFactorize(0);
11394 if (factorizationStatus < 0 ||
11395 (factorizationStatus && factorizationStatus <= numberRows_)) {
11396 // some error
11397#if 0
11398 // we should either debug or ignore
11399#ifdef CLP_INVESTIGATE
11400 //#ifndef NDEBUG
11401 printf("***** ClpDual strong branching factorization error - debug\n");
11402 abort();
11403 //#endif
11404#endif
11405 return -2;
11406#else
11407 dual(0, 7);
11408 createRim(7 + 8 + 16 + 32, true, 0);
11409 int factorizationStatus = internalFactorize(0);
11410 assert (factorizationStatus == 0);
11411 if (factorizationStatus)
11412 abort();
11413#endif
11414 }
11415 // Start of fast iterations
11416 factorization_->sparseThreshold(0);
11417 factorization_->goSparse();
11418 assert (!info->saveCosts_);
11419 int numberTotal = numberRows_ + numberColumns_;
11420 double * save = new double [4*numberTotal];
11421 CoinMemcpyN(cost_, numberTotal, save+3*numberTotal);
11422 if (perturbation_<100) {
11423 int saveIterations = numberIterations_;
11424 //int saveOptions = moreSpecialOptions_;
11425 int savePerturbation = perturbation_;
11426 numberIterations_ = 0;
11427 //moreSpecialOptions_ |= 128;
11428 bool allZero = true;
11429 for (int i=0;i<numberColumns_;i++) {
11430 if (cost_[i]) {
11431 if (upper_[i]>lower_[i]) {
11432 allZero=false;
11433 break;
11434 }
11435 }
11436 }
11437 if (allZero)
11438 perturbation_ = 58;
11439 static_cast< ClpSimplexDual *>(this)->perturb();
11440 numberIterations_ = saveIterations;
11441 //moreSpecialOptions_ = saveOptions;
11442 perturbation_ = savePerturbation;
11443 }
11444 info->saveCosts_ = save;
11445 CoinMemcpyN(cost_, numberTotal, save);
11446 return 0;
11447}
11448// Like Fast dual
11449int
11450ClpSimplex::fastDual2(ClpNodeStuff * info)
11451{
11452 assert ((info->solverOptions_ & 65536) != 0);
11453 int numberTotal = numberRows_ + numberColumns_;
11454 assert (info->saveCosts_);
11455 double * save = info->saveCosts_;
11456 CoinMemcpyN(save, numberTotal, cost_);
11457 save += numberTotal;
11458 CoinMemcpyN(lower_, numberTotal, save);
11459 save += numberTotal;
11460 CoinMemcpyN(upper_, numberTotal, save);
11461 double dummyChange;
11462 (static_cast<ClpSimplexDual *>(this))->changeBounds(3, NULL, dummyChange);
11463 numberPrimalInfeasibilities_ = 1;
11464 sumPrimalInfeasibilities_ = 0.5;
11465 sumOfRelaxedDualInfeasibilities_ = 0.0;
11466 sumOfRelaxedPrimalInfeasibilities_ = 0.5;
11467 checkDualSolution();
11468 //if (xxxxxx)
11469 //checkPrimalSolution(rowActivityWork_,columnActivityWork_);
11470 assert((specialOptions_ & 16384) == 0);
11471 specialOptions_ |= 524288; // say use solution
11472 ClpObjective * saveObjective = objective_;
11473#ifndef NDEBUG
11474 //(static_cast<ClpSimplexDual *>(this))->resetFakeBounds(-1);
11475#endif
11476 //int saveNumberFake = numberFake_;
11477 int status = static_cast<ClpSimplexDual *> (this)->fastDual(true);
11478 //numberFake_ = saveNumberFake;
11479 specialOptions_ &= ~524288; // say dont use solution
11480 CoinAssert (problemStatus_ || objectiveValue_ < 1.0e50);
11481 if (status && problemStatus_ != 3) {
11482 // not finished - might be optimal
11483 checkPrimalSolution(rowActivityWork_, columnActivityWork_);
11484 double limit = 0.0;
11485 getDblParam(ClpDualObjectiveLimit, limit);
11486 if (!numberPrimalInfeasibilities_ && objectiveValue()*optimizationDirection_ < limit) {
11487 problemStatus_ = 0;
11488 }
11489 }
11490 if (problemStatus_ == 10) {
11491 // Say second call
11492 moreSpecialOptions_ |= 256;
11493 //printf("Cleaning up with primal\n");
11494 //lastAlgorithm=1;
11495 int savePerturbation = perturbation_;
11496 int saveLog = handler_->logLevel();
11497 //handler_->setLogLevel(63);
11498 perturbation_ = 100;
11499 bool denseFactorization = initialDenseFactorization();
11500 // It will be safe to allow dense
11501 setInitialDenseFactorization(true);
11502 // Allow for catastrophe
11503 int saveMax = intParam_[ClpMaxNumIteration];
11504 if (intParam_[ClpMaxNumIteration] > 100000 + numberIterations_)
11505 intParam_[ClpMaxNumIteration] = numberIterations_ + 1000 + 2 * numberRows_ + numberColumns_;
11506 // check which algorithms allowed
11507 baseIteration_ = numberIterations_;
11508 status = static_cast<ClpSimplexPrimal *> (this)->primal(1, 7);
11509 baseIteration_ = 0;
11510 if (saveObjective != objective_) {
11511 // We changed objective to see if infeasible
11512 delete objective_;
11513 objective_ = saveObjective;
11514 if (!problemStatus_) {
11515 // carry on
11516 status = static_cast<ClpSimplexPrimal *> (this)->primal(1, 7);
11517 }
11518 }
11519 if (problemStatus_ == 3 && numberIterations_ < saveMax) {
11520#ifdef COIN_DEVELOP
11521 if (handler_->logLevel() > 0)
11522 printf("looks like trouble - too many iterations in clean up - trying again\n");
11523#endif
11524 // flatten solution and try again
11525 int iColumn;
11526 for (iColumn = 0; iColumn < numberTotal; iColumn++) {
11527 if (getStatus(iColumn) != basic) {
11528 setStatus(iColumn, superBasic);
11529 // but put to bound if close
11530 if (fabs(solution_[iColumn] - lower_[iColumn])
11531 <= primalTolerance_) {
11532 solution_[iColumn] = lower_[iColumn];
11533 setStatus(iColumn, atLowerBound);
11534 } else if (fabs(solution_[iColumn]
11535 - upper_[iColumn])
11536 <= primalTolerance_) {
11537 solution_[iColumn] = upper_[iColumn];
11538 setStatus(iColumn, atUpperBound);
11539 }
11540 }
11541 }
11542 problemStatus_ = -1;
11543 intParam_[ClpMaxNumIteration] = CoinMin(numberIterations_ + 1000 +
11544 2 * numberRows_ + numberColumns_, saveMax);
11545 perturbation_ = savePerturbation;
11546 baseIteration_ = numberIterations_;
11547 status = static_cast<ClpSimplexPrimal *> (this)->primal(0);
11548 baseIteration_ = 0;
11549 computeObjectiveValue();
11550 // can't rely on djs either
11551 memset(reducedCost_, 0, numberColumns_ * sizeof(double));
11552#ifdef COIN_DEVELOP
11553 if (problemStatus_ == 3 && numberIterations_ < saveMax && handler_->logLevel() > 0)
11554 printf("looks like real trouble - too many iterations in second clean up - giving up\n");
11555#endif
11556 }
11557 // Say not second call
11558 moreSpecialOptions_ &= ~256;
11559 intParam_[ClpMaxNumIteration] = saveMax;
11560
11561 setInitialDenseFactorization(denseFactorization);
11562 perturbation_ = savePerturbation;
11563 if (problemStatus_ == 10) {
11564 if (!numberPrimalInfeasibilities_)
11565 problemStatus_ = 0;
11566 else
11567 problemStatus_ = 4;
11568 }
11569 handler_->setLogLevel(saveLog);
11570 // if done primal arrays may be rubbish
11571 save = info->saveCosts_ + numberTotal;
11572 CoinMemcpyN(save, numberTotal, lower_);
11573 save += numberTotal;
11574 CoinMemcpyN(save, numberTotal, upper_);
11575 }
11576 status = problemStatus_;
11577 if (!problemStatus_) {
11578 int j;
11579 // Move solution to external array
11580 if (!columnScale_) {
11581 CoinMemcpyN(solution_, numberColumns_, columnActivity_);
11582 } else {
11583 for (j = 0; j < numberColumns_; j++)
11584 columnActivity_[j] = solution_[j] * columnScale_[j];
11585 }
11586 if ((info->solverOptions_ & 1) != 0) {
11587 // reduced costs
11588 if (!columnScale_) {
11589 CoinMemcpyN(dj_, numberColumns_, reducedCost_);
11590 } else {
11591 for (j = 0; j < numberColumns_; j++)
11592 reducedCost_[j] = dj_[j] * columnScale_[j+numberColumns_];
11593 }
11594 }
11595 if ((info->solverOptions_ & 2) != 0) {
11596 // dual
11597 if (!rowScale_) {
11598 //CoinMemcpyN(dual_,numberRows_,dj_+numberColumns_);
11599 } else {
11600 for (j = 0; j < numberRows_; j++)
11601 dual_[j] = dj_[j+numberColumns_] * rowScale_[j];
11602 }
11603 }
11604 if ((info->solverOptions_ & 4) != 0) {
11605 // row activity
11606 if (!rowScale_) {
11607 CoinMemcpyN(solution_ + numberColumns_, numberRows_, rowActivity_);
11608 } else {
11609 for (j = 0; j < numberRows_; j++)
11610 rowActivity_[j] = solution_[j+numberColumns_] * rowScale_[j+numberRows_];
11611 }
11612 }
11613 }
11614 save = info->saveCosts_;
11615 CoinMemcpyN(save, numberTotal, cost_);
11616#if 0
11617 save += numberTotal;
11618 CoinMemcpyN(save, numberTotal, lower_);
11619 save += numberTotal;
11620 CoinMemcpyN(save, numberTotal, upper_);
11621#endif
11622 return status;
11623}
11624// Stop Fast dual
11625void
11626ClpSimplex::stopFastDual2(ClpNodeStuff * info)
11627{
11628 delete [] info->saveCosts_;
11629 info->saveCosts_ = NULL;
11630 specialOptions_ = info->saveOptions_;
11631 // try just factorization
11632 if ((specialOptions_ & 65536) == 0)
11633 factorization_->setPersistenceFlag(0);
11634 deleteRim(1);
11635 whatsChanged_ &= ~0xffff;
11636 assert ((info->solverOptions_ & 65536) != 0);
11637 info->solverOptions_ &= ~65536;
11638}
11639// Deals with crunch aspects
11640ClpSimplex *
11641ClpSimplex::fastCrunch(ClpNodeStuff * info, int mode)
11642{
11643 ClpSimplex * small = NULL;
11644 if (mode == 0) {
11645 // before crunch
11646 // crunch down
11647 // Use dual region
11648 double * rhs = dual_;
11649 int * whichRow = new int[3*numberRows_];
11650 int * whichColumn = new int[2*numberColumns_];
11651 int nBound;
11652 bool tightenBounds = ((specialOptions_ & 64) == 0) ? false : true;
11653 small =
11654 static_cast<ClpSimplexOther *> (this)->crunch(rhs, whichRow, whichColumn,
11655 nBound, false, tightenBounds);
11656 if (small) {
11657 info->large_ = this;
11658 info->whichRow_ = whichRow;
11659 info->whichColumn_ = whichColumn;
11660 info->nBound_ = nBound;
11661 if (info->upPseudo_) {
11662 const char * integerType2 = small->integerInformation();
11663 int n = small->numberColumns();
11664 int k = 0;
11665 int jColumn = 0;
11666 int j = 0;
11667 for (int i = 0; i < n; i++) {
11668 if (integerType2[i]) {
11669 int iColumn = whichColumn[i];
11670 // find
11671 while (jColumn != iColumn) {
11672 if (integerType_[jColumn])
11673 j++;
11674 jColumn++;
11675 }
11676 info->upPseudo_[k] = info->upPseudo_[j];
11677 info->numberUp_[k] = info->numberUp_[j];
11678 info->numberUpInfeasible_[k] = info->numberUpInfeasible_[j];
11679 info->downPseudo_[k] = info->downPseudo_[j];
11680 info->numberDown_[k] = info->numberDown_[j];
11681 info->numberDownInfeasible_[k] = info->numberDownInfeasible_[j];
11682 assert (info->upPseudo_[k] > 1.0e-40 && info->upPseudo_[k] < 1.0e40);
11683 assert (info->downPseudo_[k] > 1.0e-40 && info->downPseudo_[k] < 1.0e40);
11684 k++;
11685 }
11686 }
11687 }
11688 } else {
11689 delete [] whichRow;
11690 delete [] whichColumn;
11691 }
11692 } else {
11693 // after crunch
11694 if (mode == 1) {
11695 // has solution
11696 ClpSimplex * other = info->large_;
11697 assert (other != this);
11698 static_cast<ClpSimplexOther *> (other)->afterCrunch(*this,
11699 info->whichRow_,
11700 info->whichColumn_, info->nBound_);
11701 for (int i = 0; i < other->numberColumns_; i++) {
11702 if (other->integerType_[i]) {
11703 double value = other->columnActivity_[i];
11704 double value2 = floor(value + 0.5);
11705 assert (fabs(value - value2) < 1.0e-4);
11706 other->columnActivity_[i] = value2;
11707 other->columnLower_[i] = value2;
11708 other->columnUpper_[i] = value2;
11709 }
11710 }
11711 }
11712 delete [] info->whichRow_;
11713 delete [] info->whichColumn_;
11714 }
11715 return small;
11716}
11717// Resizes rim part of model
11718void
11719ClpSimplex::resize (int newNumberRows, int newNumberColumns)
11720{
11721 ClpModel::resize(newNumberRows, newNumberColumns);
11722 if (saveStatus_) {
11723 // delete arrays
11724 int saveOptions = specialOptions_;
11725 specialOptions_ = 0;
11726 gutsOfDelete(2);
11727 specialOptions_ = saveOptions;
11728 }
11729}
11730// Return true if the objective limit test can be relied upon
11731bool
11732ClpSimplex::isObjectiveLimitTestValid() const
11733{
11734 if (problemStatus_ == 0) {
11735 return true;
11736 } else if (problemStatus_ == 1) {
11737 // ok if dual
11738 return (algorithm_ < 0);
11739 } else if (problemStatus_ == 2) {
11740 // ok if primal
11741 return (algorithm_ > 0);
11742 } else {
11743 return false;
11744 }
11745}
11746// Create C++ lines to get to current state
11747void
11748ClpSimplex::generateCpp( FILE * fp, bool defaultFactor)
11749{
11750 ClpModel::generateCpp(fp);
11751 ClpSimplex defaultModel;
11752 ClpSimplex * other = &defaultModel;
11753 int iValue1, iValue2;
11754 double dValue1, dValue2;
11755 // Stuff that can't be done easily
11756 if (factorizationFrequency() == other->factorizationFrequency()) {
11757 if (defaultFactor) {
11758 fprintf(fp, "3 // For branchAndBound this may help\n");
11759 fprintf(fp, "3 clpModel->defaultFactorizationFrequency();\n");
11760 } else {
11761 // tell user about default
11762 fprintf(fp, "3 // For initialSolve you don't need below but ...\n");
11763 fprintf(fp, "3 // clpModel->defaultFactorizationFrequency();\n");
11764 }
11765 }
11766 iValue1 = this->factorizationFrequency();
11767 iValue2 = other->factorizationFrequency();
11768 fprintf(fp, "%d int save_factorizationFrequency = clpModel->factorizationFrequency();\n", iValue1 == iValue2 ? 2 : 1);
11769 fprintf(fp, "%d clpModel->setFactorizationFrequency(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
11770 fprintf(fp, "%d clpModel->setFactorizationFrequency(save_factorizationFrequency);\n", iValue1 == iValue2 ? 7 : 6);
11771 dValue1 = this->dualBound();
11772 dValue2 = other->dualBound();
11773 fprintf(fp, "%d double save_dualBound = clpModel->dualBound();\n", dValue1 == dValue2 ? 2 : 1);
11774 fprintf(fp, "%d clpModel->setDualBound(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
11775 fprintf(fp, "%d clpModel->setDualBound(save_dualBound);\n", dValue1 == dValue2 ? 7 : 6);
11776 dValue1 = this->infeasibilityCost();
11777 dValue2 = other->infeasibilityCost();
11778 fprintf(fp, "%d double save_infeasibilityCost = clpModel->infeasibilityCost();\n", dValue1 == dValue2 ? 2 : 1);
11779 fprintf(fp, "%d clpModel->setInfeasibilityCost(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
11780 fprintf(fp, "%d clpModel->setInfeasibilityCost(save_infeasibilityCost);\n", dValue1 == dValue2 ? 7 : 6);
11781 iValue1 = this->perturbation();
11782 iValue2 = other->perturbation();
11783 fprintf(fp, "%d int save_perturbation = clpModel->perturbation();\n", iValue1 == iValue2 ? 2 : 1);
11784 fprintf(fp, "%d clpModel->setPerturbation(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
11785 fprintf(fp, "%d clpModel->setPerturbation(save_perturbation);\n", iValue1 == iValue2 ? 7 : 6);
11786}
11787