1/* $Id: ClpModel.cpp 1787 2011-09-03 13:06:58Z stefan $ */
2// copyright (C) 2002, International Business Machines
3// Corporation and others. All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include <cstdlib>
7#include <cmath>
8#include <cassert>
9#include <cfloat>
10#include <string>
11#include <cstdio>
12#include <iostream>
13
14/*
15 CLP_NO_VECTOR
16
17 There's no hint of the motivation for this, so here's a bit of speculation.
18 CLP_NO_VECTOR excises CoinPackedVector from the code. Looking over
19 affected code here, and the much more numerous occurrences of affected
20 code in CoinUtils, it looks to be an efficiency issue.
21
22 One good example is CoinPackedMatrix.isEquivalent. The default version
23 tests equivalence of major dimension vectors by retrieving them as
24 CPVs and invoking CPV.isEquivalent. As pointed out in the documention,
25 CPV.isEquivalent implicitly sorts the nonzeros of each vector (insertion in
26 a map) prior to comparison. As a one-off, this is arguably more efficient
27 than allocating and clearing a full vector, then dropping in the nonzeros,
28 then checking against the second vector (in fact, this is the algorithm
29 for testing a packed vector against a full vector).
30
31 In CPM.isEquivalent, we have a whole sequence of vectors to compare. Better
32 to allocate a full vector sized to match, clear it (one time cost), then
33 edit nonzeros in and out while doing comparisons. The cost of allocating
34 and clearing the full vector is amortised over all columns.
35*/
36
37
38#include "CoinPragma.hpp"
39
40#include "CoinHelperFunctions.hpp"
41#include "CoinTime.hpp"
42#include "ClpModel.hpp"
43#include "ClpEventHandler.hpp"
44#include "ClpPackedMatrix.hpp"
45#ifndef SLIM_CLP
46#include "ClpPlusMinusOneMatrix.hpp"
47#endif
48#ifndef CLP_NO_VECTOR
49#include "CoinPackedVector.hpp"
50#endif
51#include "CoinIndexedVector.hpp"
52#if SLIM_CLP==2
53#define SLIM_NOIO
54#endif
55#ifndef SLIM_NOIO
56#include "CoinMpsIO.hpp"
57#include "CoinFileIO.hpp"
58#include "CoinModel.hpp"
59#endif
60#include "ClpMessage.hpp"
61#include "CoinMessage.hpp"
62#include "ClpLinearObjective.hpp"
63#ifndef SLIM_CLP
64#include "ClpQuadraticObjective.hpp"
65#include "CoinBuild.hpp"
66#endif
67
68//#############################################################################
69ClpModel::ClpModel (bool emptyMessages) :
70
71 optimizationDirection_(1),
72 objectiveValue_(0.0),
73 smallElement_(1.0e-20),
74 objectiveScale_(1.0),
75 rhsScale_(1.0),
76 numberRows_(0),
77 numberColumns_(0),
78 rowActivity_(NULL),
79 columnActivity_(NULL),
80 dual_(NULL),
81 reducedCost_(NULL),
82 rowLower_(NULL),
83 rowUpper_(NULL),
84 objective_(NULL),
85 rowObjective_(NULL),
86 columnLower_(NULL),
87 columnUpper_(NULL),
88 matrix_(NULL),
89 rowCopy_(NULL),
90 scaledMatrix_(NULL),
91 ray_(NULL),
92 rowScale_(NULL),
93 columnScale_(NULL),
94 inverseRowScale_(NULL),
95 inverseColumnScale_(NULL),
96 scalingFlag_(3),
97 status_(NULL),
98 integerType_(NULL),
99 userPointer_(NULL),
100 trustedUserPointer_(NULL),
101 numberIterations_(0),
102 solveType_(0),
103 whatsChanged_(0),
104 problemStatus_(-1),
105 secondaryStatus_(0),
106 lengthNames_(0),
107 numberThreads_(0),
108 specialOptions_(0),
109#ifndef CLP_NO_STD
110 defaultHandler_(true),
111 rowNames_(),
112 columnNames_(),
113#else
114 defaultHandler_(true),
115#endif
116 maximumColumns_(-1),
117 maximumRows_(-1),
118 maximumInternalColumns_(-1),
119 maximumInternalRows_(-1),
120 savedRowScale_(NULL),
121 savedColumnScale_(NULL)
122{
123 intParam_[ClpMaxNumIteration] = 2147483647;
124 intParam_[ClpMaxNumIterationHotStart] = 9999999;
125 intParam_[ClpNameDiscipline] = 0;
126
127 dblParam_[ClpDualObjectiveLimit] = COIN_DBL_MAX;
128 dblParam_[ClpPrimalObjectiveLimit] = COIN_DBL_MAX;
129 dblParam_[ClpDualTolerance] = 1e-7;
130 dblParam_[ClpPrimalTolerance] = 1e-7;
131 dblParam_[ClpObjOffset] = 0.0;
132 dblParam_[ClpMaxSeconds] = -1.0;
133 dblParam_[ClpPresolveTolerance] = 1.0e-8;
134
135#ifndef CLP_NO_STD
136 strParam_[ClpProbName] = "ClpDefaultName";
137#endif
138 handler_ = new CoinMessageHandler();
139 handler_->setLogLevel(1);
140 eventHandler_ = new ClpEventHandler();
141 if (!emptyMessages) {
142 messages_ = ClpMessage();
143 coinMessages_ = CoinMessage();
144 }
145 randomNumberGenerator_.setSeed(1234567);
146}
147
148//-----------------------------------------------------------------------------
149
150ClpModel::~ClpModel ()
151{
152 if (defaultHandler_) {
153 delete handler_;
154 handler_ = NULL;
155 }
156 gutsOfDelete(0);
157}
158// Does most of deletion (0 = all, 1 = most)
159void
160ClpModel::gutsOfDelete(int type)
161{
162 if (!type || !permanentArrays()) {
163 maximumRows_ = -1;
164 maximumColumns_ = -1;
165 delete [] rowActivity_;
166 rowActivity_ = NULL;
167 delete [] columnActivity_;
168 columnActivity_ = NULL;
169 delete [] dual_;
170 dual_ = NULL;
171 delete [] reducedCost_;
172 reducedCost_ = NULL;
173 delete [] rowLower_;
174 delete [] rowUpper_;
175 delete [] rowObjective_;
176 rowLower_ = NULL;
177 rowUpper_ = NULL;
178 rowObjective_ = NULL;
179 delete [] columnLower_;
180 delete [] columnUpper_;
181 delete objective_;
182 columnLower_ = NULL;
183 columnUpper_ = NULL;
184 objective_ = NULL;
185 delete [] savedRowScale_;
186 if (rowScale_ == savedRowScale_)
187 rowScale_ = NULL;
188 savedRowScale_ = NULL;
189 delete [] savedColumnScale_;
190 if (columnScale_ == savedColumnScale_)
191 columnScale_ = NULL;
192 savedColumnScale_ = NULL;
193 delete [] rowScale_;
194 rowScale_ = NULL;
195 delete [] columnScale_;
196 columnScale_ = NULL;
197 delete [] integerType_;
198 integerType_ = NULL;
199 delete [] status_;
200 status_ = NULL;
201 delete eventHandler_;
202 eventHandler_ = NULL;
203 }
204 whatsChanged_ = 0;
205 delete matrix_;
206 matrix_ = NULL;
207 delete rowCopy_;
208 rowCopy_ = NULL;
209 delete scaledMatrix_;
210 scaledMatrix_ = NULL,
211 delete [] ray_;
212 ray_ = NULL;
213 specialOptions_ = 0;
214}
215void
216ClpModel::setRowScale(double * scale)
217{
218 if (!savedRowScale_) {
219 delete [] reinterpret_cast<double *> (rowScale_);
220 rowScale_ = scale;
221 } else {
222 assert (!scale);
223 rowScale_ = NULL;
224 }
225}
226void
227ClpModel::setColumnScale(double * scale)
228{
229 if (!savedColumnScale_) {
230 delete [] reinterpret_cast<double *> (columnScale_);
231 columnScale_ = scale;
232 } else {
233 assert (!scale);
234 columnScale_ = NULL;
235 }
236}
237//#############################################################################
238void ClpModel::setPrimalTolerance( double value)
239{
240 if (value > 0.0 && value < 1.0e10)
241 dblParam_[ClpPrimalTolerance] = value;
242}
243void ClpModel::setDualTolerance( double value)
244{
245 if (value > 0.0 && value < 1.0e10)
246 dblParam_[ClpDualTolerance] = value;
247}
248void ClpModel::setOptimizationDirection( double value)
249{
250 optimizationDirection_ = value;
251}
252void
253ClpModel::gutsOfLoadModel (int numberRows, int numberColumns,
254 const double* collb, const double* colub,
255 const double* obj,
256 const double* rowlb, const double* rowub,
257 const double * rowObjective)
258{
259 // save event handler in case already set
260 ClpEventHandler * handler = eventHandler_->clone();
261 // Save specialOptions
262 int saveOptions = specialOptions_;
263 gutsOfDelete(0);
264 specialOptions_ = saveOptions;
265 eventHandler_ = handler;
266 numberRows_ = numberRows;
267 numberColumns_ = numberColumns;
268 rowActivity_ = new double[numberRows_];
269 columnActivity_ = new double[numberColumns_];
270 dual_ = new double[numberRows_];
271 reducedCost_ = new double[numberColumns_];
272
273 CoinZeroN(dual_, numberRows_);
274 CoinZeroN(reducedCost_, numberColumns_);
275 int iRow, iColumn;
276
277 rowLower_ = ClpCopyOfArray(rowlb, numberRows_, -COIN_DBL_MAX);
278 rowUpper_ = ClpCopyOfArray(rowub, numberRows_, COIN_DBL_MAX);
279 double * objective = ClpCopyOfArray(obj, numberColumns_, 0.0);
280 objective_ = new ClpLinearObjective(objective, numberColumns_);
281 delete [] objective;
282 rowObjective_ = ClpCopyOfArray(rowObjective, numberRows_);
283 columnLower_ = ClpCopyOfArray(collb, numberColumns_, 0.0);
284 columnUpper_ = ClpCopyOfArray(colub, numberColumns_, COIN_DBL_MAX);
285 // set default solution and clean bounds
286 for (iRow = 0; iRow < numberRows_; iRow++) {
287 if (rowLower_[iRow] > 0.0) {
288 rowActivity_[iRow] = rowLower_[iRow];
289 } else if (rowUpper_[iRow] < 0.0) {
290 rowActivity_[iRow] = rowUpper_[iRow];
291 } else {
292 rowActivity_[iRow] = 0.0;
293 }
294 if (rowLower_[iRow] < -1.0e27)
295 rowLower_[iRow] = -COIN_DBL_MAX;
296 if (rowUpper_[iRow] > 1.0e27)
297 rowUpper_[iRow] = COIN_DBL_MAX;
298 }
299 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
300 if (columnLower_[iColumn] > 0.0) {
301 columnActivity_[iColumn] = columnLower_[iColumn];
302 } else if (columnUpper_[iColumn] < 0.0) {
303 columnActivity_[iColumn] = columnUpper_[iColumn];
304 } else {
305 columnActivity_[iColumn] = 0.0;
306 }
307 if (columnLower_[iColumn] < -1.0e27)
308 columnLower_[iColumn] = -COIN_DBL_MAX;
309 if (columnUpper_[iColumn] > 1.0e27)
310 columnUpper_[iColumn] = COIN_DBL_MAX;
311 }
312}
313// This just loads up a row objective
314void ClpModel::setRowObjective(const double * rowObjective)
315{
316 delete [] rowObjective_;
317 rowObjective_ = ClpCopyOfArray(rowObjective, numberRows_);
318 whatsChanged_ = 0;
319}
320void
321ClpModel::loadProblem ( const ClpMatrixBase& matrix,
322 const double* collb, const double* colub,
323 const double* obj,
324 const double* rowlb, const double* rowub,
325 const double * rowObjective)
326{
327 gutsOfLoadModel(matrix.getNumRows(), matrix.getNumCols(),
328 collb, colub, obj, rowlb, rowub, rowObjective);
329 if (matrix.isColOrdered()) {
330 matrix_ = matrix.clone();
331 } else {
332 // later may want to keep as unknown class
333 CoinPackedMatrix matrix2;
334 matrix2.setExtraGap(0.0);
335 matrix2.setExtraMajor(0.0);
336 matrix2.reverseOrderedCopyOf(*matrix.getPackedMatrix());
337 matrix.releasePackedMatrix();
338 matrix_ = new ClpPackedMatrix(matrix2);
339 }
340 matrix_->setDimensions(numberRows_, numberColumns_);
341}
342void
343ClpModel::loadProblem ( const CoinPackedMatrix& matrix,
344 const double* collb, const double* colub,
345 const double* obj,
346 const double* rowlb, const double* rowub,
347 const double * rowObjective)
348{
349 ClpPackedMatrix* clpMatrix =
350 dynamic_cast< ClpPackedMatrix*>(matrix_);
351 bool special = (clpMatrix) ? clpMatrix->wantsSpecialColumnCopy() : false;
352 gutsOfLoadModel(matrix.getNumRows(), matrix.getNumCols(),
353 collb, colub, obj, rowlb, rowub, rowObjective);
354 if (matrix.isColOrdered()) {
355 matrix_ = new ClpPackedMatrix(matrix);
356 if (special) {
357 clpMatrix = static_cast< ClpPackedMatrix*>(matrix_);
358 clpMatrix->makeSpecialColumnCopy();
359 }
360 } else {
361 CoinPackedMatrix matrix2;
362 matrix2.setExtraGap(0.0);
363 matrix2.setExtraMajor(0.0);
364 matrix2.reverseOrderedCopyOf(matrix);
365 matrix_ = new ClpPackedMatrix(matrix2);
366 }
367 matrix_->setDimensions(numberRows_, numberColumns_);
368}
369void
370ClpModel::loadProblem (
371 const int numcols, const int numrows,
372 const CoinBigIndex* start, const int* index,
373 const double* value,
374 const double* collb, const double* colub,
375 const double* obj,
376 const double* rowlb, const double* rowub,
377 const double * rowObjective)
378{
379 gutsOfLoadModel(numrows, numcols,
380 collb, colub, obj, rowlb, rowub, rowObjective);
381 int numberElements = start ? start[numcols] : 0;
382 CoinPackedMatrix matrix(true, numrows, numrows ? numcols : 0, numberElements,
383 value, index, start, NULL);
384 matrix_ = new ClpPackedMatrix(matrix);
385 matrix_->setDimensions(numberRows_, numberColumns_);
386}
387void
388ClpModel::loadProblem (
389 const int numcols, const int numrows,
390 const CoinBigIndex* start, const int* index,
391 const double* value, const int* length,
392 const double* collb, const double* colub,
393 const double* obj,
394 const double* rowlb, const double* rowub,
395 const double * rowObjective)
396{
397 gutsOfLoadModel(numrows, numcols,
398 collb, colub, obj, rowlb, rowub, rowObjective);
399 // Compute number of elements
400 int numberElements = 0;
401 int i;
402 for (i = 0; i < numcols; i++)
403 numberElements += length[i];
404 CoinPackedMatrix matrix(true, numrows, numcols, numberElements,
405 value, index, start, length);
406 matrix_ = new ClpPackedMatrix(matrix);
407}
408#ifndef SLIM_NOIO
409// This loads a model from a coinModel object - returns number of errors
410int
411ClpModel::loadProblem ( CoinModel & modelObject, bool tryPlusMinusOne)
412{
413 if (modelObject.numberColumns() == 0 && modelObject.numberRows() == 0)
414 return 0;
415 int numberErrors = 0;
416 // Set arrays for normal use
417 double * rowLower = modelObject.rowLowerArray();
418 double * rowUpper = modelObject.rowUpperArray();
419 double * columnLower = modelObject.columnLowerArray();
420 double * columnUpper = modelObject.columnUpperArray();
421 double * objective = modelObject.objectiveArray();
422 int * integerType = modelObject.integerTypeArray();
423 double * associated = modelObject.associatedArray();
424 // If strings then do copies
425 if (modelObject.stringsExist()) {
426 numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
427 objective, integerType, associated);
428 }
429 int numberRows = modelObject.numberRows();
430 int numberColumns = modelObject.numberColumns();
431 gutsOfLoadModel(numberRows, numberColumns,
432 columnLower, columnUpper, objective, rowLower, rowUpper, NULL);
433 setObjectiveOffset(modelObject.objectiveOffset());
434 CoinBigIndex * startPositive = NULL;
435 CoinBigIndex * startNegative = NULL;
436 delete matrix_;
437 if (tryPlusMinusOne) {
438 startPositive = new CoinBigIndex[numberColumns+1];
439 startNegative = new CoinBigIndex[numberColumns];
440 modelObject.countPlusMinusOne(startPositive, startNegative, associated);
441 if (startPositive[0] < 0) {
442 // no good
443 tryPlusMinusOne = false;
444 delete [] startPositive;
445 delete [] startNegative;
446 }
447 }
448#ifndef SLIM_CLP
449 if (!tryPlusMinusOne) {
450#endif
451 CoinPackedMatrix matrix;
452 modelObject.createPackedMatrix(matrix, associated);
453 matrix_ = new ClpPackedMatrix(matrix);
454#ifndef SLIM_CLP
455 } else {
456 // create +-1 matrix
457 CoinBigIndex size = startPositive[numberColumns];
458 int * indices = new int[size];
459 modelObject.createPlusMinusOne(startPositive, startNegative, indices,
460 associated);
461 // Get good object
462 ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
463 matrix->passInCopy(numberRows, numberColumns,
464 true, indices, startPositive, startNegative);
465 matrix_ = matrix;
466 }
467#endif
468#ifndef CLP_NO_STD
469 // Do names if wanted
470 int numberItems;
471 numberItems = modelObject.rowNames()->numberItems();
472 if (numberItems) {
473 const char *const * rowNames = modelObject.rowNames()->names();
474 copyRowNames(rowNames, 0, numberItems);
475 }
476 numberItems = modelObject.columnNames()->numberItems();
477 if (numberItems) {
478 const char *const * columnNames = modelObject.columnNames()->names();
479 copyColumnNames(columnNames, 0, numberItems);
480 }
481#endif
482 // Do integers if wanted
483 assert(integerType);
484 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
485 if (integerType[iColumn])
486 setInteger(iColumn);
487 }
488 if (rowLower != modelObject.rowLowerArray() ||
489 columnLower != modelObject.columnLowerArray()) {
490 delete [] rowLower;
491 delete [] rowUpper;
492 delete [] columnLower;
493 delete [] columnUpper;
494 delete [] objective;
495 delete [] integerType;
496 delete [] associated;
497 if (numberErrors)
498 handler_->message(CLP_BAD_STRING_VALUES, messages_)
499 << numberErrors
500 << CoinMessageEol;
501 }
502 matrix_->setDimensions(numberRows_, numberColumns_);
503 return numberErrors;
504}
505#endif
506void
507ClpModel::getRowBound(int iRow, double& lower, double& upper) const
508{
509 lower = -COIN_DBL_MAX;
510 upper = COIN_DBL_MAX;
511 if (rowUpper_)
512 upper = rowUpper_[iRow];
513 if (rowLower_)
514 lower = rowLower_[iRow];
515}
516//------------------------------------------------------------------
517#ifndef NDEBUG
518// For errors to make sure print to screen
519// only called in debug mode
520static void indexError(int index,
521 std::string methodName)
522{
523 std::cerr << "Illegal index " << index << " in ClpModel::" << methodName << std::endl;
524 throw CoinError("Illegal index", methodName, "ClpModel");
525}
526#endif
527/* Set an objective function coefficient */
528void
529ClpModel::setObjectiveCoefficient( int elementIndex, double elementValue )
530{
531#ifndef NDEBUG
532 if (elementIndex < 0 || elementIndex >= numberColumns_) {
533 indexError(elementIndex, "setObjectiveCoefficient");
534 }
535#endif
536 objective()[elementIndex] = elementValue;
537 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
538}
539/* Set a single row lower bound<br>
540 Use -DBL_MAX for -infinity. */
541void
542ClpModel::setRowLower( int elementIndex, double elementValue )
543{
544 if (elementValue < -1.0e27)
545 elementValue = -COIN_DBL_MAX;
546 rowLower_[elementIndex] = elementValue;
547 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
548}
549
550/* Set a single row upper bound<br>
551 Use DBL_MAX for infinity. */
552void
553ClpModel::setRowUpper( int elementIndex, double elementValue )
554{
555 if (elementValue > 1.0e27)
556 elementValue = COIN_DBL_MAX;
557 rowUpper_[elementIndex] = elementValue;
558 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
559}
560
561/* Set a single row lower and upper bound */
562void
563ClpModel::setRowBounds( int elementIndex,
564 double lower, double upper )
565{
566 if (lower < -1.0e27)
567 lower = -COIN_DBL_MAX;
568 if (upper > 1.0e27)
569 upper = COIN_DBL_MAX;
570 CoinAssert (upper >= lower);
571 rowLower_[elementIndex] = lower;
572 rowUpper_[elementIndex] = upper;
573 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
574}
575void ClpModel::setRowSetBounds(const int* indexFirst,
576 const int* indexLast,
577 const double* boundList)
578{
579#ifndef NDEBUG
580 int n = numberRows_;
581#endif
582 double * lower = rowLower_;
583 double * upper = rowUpper_;
584 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
585 while (indexFirst != indexLast) {
586 const int iRow = *indexFirst++;
587#ifndef NDEBUG
588 if (iRow < 0 || iRow >= n) {
589 indexError(iRow, "setRowSetBounds");
590 }
591#endif
592 lower[iRow] = *boundList++;
593 upper[iRow] = *boundList++;
594 if (lower[iRow] < -1.0e27)
595 lower[iRow] = -COIN_DBL_MAX;
596 if (upper[iRow] > 1.0e27)
597 upper[iRow] = COIN_DBL_MAX;
598 CoinAssert (upper[iRow] >= lower[iRow]);
599 }
600}
601//-----------------------------------------------------------------------------
602/* Set a single column lower bound<br>
603 Use -DBL_MAX for -infinity. */
604void
605ClpModel::setColumnLower( int elementIndex, double elementValue )
606{
607#ifndef NDEBUG
608 int n = numberColumns_;
609 if (elementIndex < 0 || elementIndex >= n) {
610 indexError(elementIndex, "setColumnLower");
611 }
612#endif
613 if (elementValue < -1.0e27)
614 elementValue = -COIN_DBL_MAX;
615 columnLower_[elementIndex] = elementValue;
616 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
617}
618
619/* Set a single column upper bound<br>
620 Use DBL_MAX for infinity. */
621void
622ClpModel::setColumnUpper( int elementIndex, double elementValue )
623{
624#ifndef NDEBUG
625 int n = numberColumns_;
626 if (elementIndex < 0 || elementIndex >= n) {
627 indexError(elementIndex, "setColumnUpper");
628 }
629#endif
630 if (elementValue > 1.0e27)
631 elementValue = COIN_DBL_MAX;
632 columnUpper_[elementIndex] = elementValue;
633 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
634}
635
636/* Set a single column lower and upper bound */
637void
638ClpModel::setColumnBounds( int elementIndex,
639 double lower, double upper )
640{
641#ifndef NDEBUG
642 int n = numberColumns_;
643 if (elementIndex < 0 || elementIndex >= n) {
644 indexError(elementIndex, "setColumnBounds");
645 }
646#endif
647 if (lower < -1.0e27)
648 lower = -COIN_DBL_MAX;
649 if (upper > 1.0e27)
650 upper = COIN_DBL_MAX;
651 columnLower_[elementIndex] = lower;
652 columnUpper_[elementIndex] = upper;
653 CoinAssert (upper >= lower);
654 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
655}
656void ClpModel::setColumnSetBounds(const int* indexFirst,
657 const int* indexLast,
658 const double* boundList)
659{
660 double * lower = columnLower_;
661 double * upper = columnUpper_;
662 whatsChanged_ = 0; // Can't be sure (use ClpSimplex to keep)
663#ifndef NDEBUG
664 int n = numberColumns_;
665#endif
666 while (indexFirst != indexLast) {
667 const int iColumn = *indexFirst++;
668#ifndef NDEBUG
669 if (iColumn < 0 || iColumn >= n) {
670 indexError(iColumn, "setColumnSetBounds");
671 }
672#endif
673 lower[iColumn] = *boundList++;
674 upper[iColumn] = *boundList++;
675 CoinAssert (upper[iColumn] >= lower[iColumn]);
676 if (lower[iColumn] < -1.0e27)
677 lower[iColumn] = -COIN_DBL_MAX;
678 if (upper[iColumn] > 1.0e27)
679 upper[iColumn] = COIN_DBL_MAX;
680 }
681}
682//-----------------------------------------------------------------------------
683//#############################################################################
684// Copy constructor.
685ClpModel::ClpModel(const ClpModel &rhs, int scalingMode) :
686 optimizationDirection_(rhs.optimizationDirection_),
687 numberRows_(rhs.numberRows_),
688 numberColumns_(rhs.numberColumns_),
689 specialOptions_(rhs.specialOptions_),
690 maximumColumns_(-1),
691 maximumRows_(-1),
692 maximumInternalColumns_(-1),
693 maximumInternalRows_(-1),
694 savedRowScale_(NULL),
695 savedColumnScale_(NULL)
696{
697 gutsOfCopy(rhs);
698 if (scalingMode >= 0 && matrix_ &&
699 matrix_->allElementsInRange(this, smallElement_, 1.0e20)) {
700 // really do scaling
701 scalingFlag_ = scalingMode;
702 setRowScale(NULL);
703 setColumnScale(NULL);
704 delete rowCopy_; // in case odd
705 rowCopy_ = NULL;
706 delete scaledMatrix_;
707 scaledMatrix_ = NULL;
708 if (scalingMode && !matrix_->scale(this)) {
709 // scaling worked - now apply
710 inverseRowScale_ = rowScale_ + numberRows_;
711 inverseColumnScale_ = columnScale_ + numberColumns_;
712 gutsOfScaling();
713 // pretend not scaled
714 scalingFlag_ = -scalingFlag_;
715 } else {
716 // not scaled
717 scalingFlag_ = 0;
718 }
719 }
720 randomNumberGenerator_.setSeed(1234567);
721}
722// Assignment operator. This copies the data
723ClpModel &
724ClpModel::operator=(const ClpModel & rhs)
725{
726 if (this != &rhs) {
727 if (defaultHandler_) {
728 //delete handler_;
729 //handler_ = NULL;
730 }
731 gutsOfDelete(1);
732 optimizationDirection_ = rhs.optimizationDirection_;
733 numberRows_ = rhs.numberRows_;
734 numberColumns_ = rhs.numberColumns_;
735 gutsOfCopy(rhs, -1);
736 }
737 return *this;
738}
739/* Does most of copying
740 If trueCopy 0 then just points to arrays
741 If -1 leaves as much as possible */
742void
743ClpModel::gutsOfCopy(const ClpModel & rhs, int trueCopy)
744{
745 defaultHandler_ = rhs.defaultHandler_;
746 if (trueCopy >= 0) {
747 if (defaultHandler_)
748 handler_ = new CoinMessageHandler(*rhs.handler_);
749 else
750 handler_ = rhs.handler_;
751 eventHandler_ = rhs.eventHandler_->clone();
752 randomNumberGenerator_ = rhs.randomNumberGenerator_;
753 messages_ = rhs.messages_;
754 coinMessages_ = rhs.coinMessages_;
755 } else {
756 if (!eventHandler_ && rhs.eventHandler_)
757 eventHandler_ = rhs.eventHandler_->clone();
758 }
759 intParam_[ClpMaxNumIteration] = rhs.intParam_[ClpMaxNumIteration];
760 intParam_[ClpMaxNumIterationHotStart] =
761 rhs.intParam_[ClpMaxNumIterationHotStart];
762 intParam_[ClpNameDiscipline] = rhs.intParam_[ClpNameDiscipline] ;
763
764 dblParam_[ClpDualObjectiveLimit] = rhs.dblParam_[ClpDualObjectiveLimit];
765 dblParam_[ClpPrimalObjectiveLimit] = rhs.dblParam_[ClpPrimalObjectiveLimit];
766 dblParam_[ClpDualTolerance] = rhs.dblParam_[ClpDualTolerance];
767 dblParam_[ClpPrimalTolerance] = rhs.dblParam_[ClpPrimalTolerance];
768 dblParam_[ClpObjOffset] = rhs.dblParam_[ClpObjOffset];
769 dblParam_[ClpMaxSeconds] = rhs.dblParam_[ClpMaxSeconds];
770 dblParam_[ClpPresolveTolerance] = rhs.dblParam_[ClpPresolveTolerance];
771#ifndef CLP_NO_STD
772
773 strParam_[ClpProbName] = rhs.strParam_[ClpProbName];
774#endif
775
776 optimizationDirection_ = rhs.optimizationDirection_;
777 objectiveValue_ = rhs.objectiveValue_;
778 smallElement_ = rhs.smallElement_;
779 objectiveScale_ = rhs.objectiveScale_;
780 rhsScale_ = rhs.rhsScale_;
781 numberIterations_ = rhs.numberIterations_;
782 solveType_ = rhs.solveType_;
783 whatsChanged_ = rhs.whatsChanged_;
784 problemStatus_ = rhs.problemStatus_;
785 secondaryStatus_ = rhs.secondaryStatus_;
786 numberRows_ = rhs.numberRows_;
787 numberColumns_ = rhs.numberColumns_;
788 userPointer_ = rhs.userPointer_;
789 trustedUserPointer_ = rhs.trustedUserPointer_;
790 scalingFlag_ = rhs.scalingFlag_;
791 specialOptions_ = rhs.specialOptions_;
792 if (trueCopy) {
793#ifndef CLP_NO_STD
794 lengthNames_ = rhs.lengthNames_;
795 if (lengthNames_) {
796 rowNames_ = rhs.rowNames_;
797 columnNames_ = rhs.columnNames_;
798 }
799#endif
800 numberThreads_ = rhs.numberThreads_;
801 if (maximumRows_ < 0) {
802 specialOptions_ &= ~65536;
803 savedRowScale_ = NULL;
804 savedColumnScale_ = NULL;
805 integerType_ = CoinCopyOfArray(rhs.integerType_, numberColumns_);
806 rowActivity_ = ClpCopyOfArray(rhs.rowActivity_, numberRows_);
807 columnActivity_ = ClpCopyOfArray(rhs.columnActivity_, numberColumns_);
808 dual_ = ClpCopyOfArray(rhs.dual_, numberRows_);
809 reducedCost_ = ClpCopyOfArray(rhs.reducedCost_, numberColumns_);
810 rowLower_ = ClpCopyOfArray ( rhs.rowLower_, numberRows_ );
811 rowUpper_ = ClpCopyOfArray ( rhs.rowUpper_, numberRows_ );
812 columnLower_ = ClpCopyOfArray ( rhs.columnLower_, numberColumns_ );
813 columnUpper_ = ClpCopyOfArray ( rhs.columnUpper_, numberColumns_ );
814 rowScale_ = ClpCopyOfArray(rhs.rowScale_, numberRows_ * 2);
815 columnScale_ = ClpCopyOfArray(rhs.columnScale_, numberColumns_ * 2);
816 if (rhs.objective_)
817 objective_ = rhs.objective_->clone();
818 else
819 objective_ = NULL;
820 rowObjective_ = ClpCopyOfArray ( rhs.rowObjective_, numberRows_ );
821 status_ = ClpCopyOfArray( rhs.status_, numberColumns_ + numberRows_);
822 ray_ = NULL;
823 if (problemStatus_ == 1)
824 ray_ = ClpCopyOfArray (rhs.ray_, numberRows_);
825 else if (problemStatus_ == 2)
826 ray_ = ClpCopyOfArray (rhs.ray_, numberColumns_);
827 if (rhs.rowCopy_) {
828 rowCopy_ = rhs.rowCopy_->clone();
829 } else {
830 rowCopy_ = NULL;
831 }
832 if (rhs.scaledMatrix_) {
833 scaledMatrix_ = new ClpPackedMatrix(*rhs.scaledMatrix_);
834 } else {
835 scaledMatrix_ = NULL;
836 }
837 matrix_ = NULL;
838 if (rhs.matrix_) {
839 matrix_ = rhs.matrix_->clone();
840 }
841 } else {
842 // This already has arrays - just copy
843 savedRowScale_ = NULL;
844 savedColumnScale_ = NULL;
845 startPermanentArrays();
846 if (rhs.integerType_) {
847 assert (integerType_);
848 ClpDisjointCopyN(rhs.integerType_, numberColumns_, integerType_);
849 } else {
850 integerType_ = NULL;
851 }
852 if (rhs.rowActivity_) {
853 ClpDisjointCopyN ( rhs.rowActivity_, numberRows_ ,
854 rowActivity_);
855 ClpDisjointCopyN ( rhs.columnActivity_, numberColumns_ ,
856 columnActivity_);
857 ClpDisjointCopyN ( rhs.dual_, numberRows_ ,
858 dual_);
859 ClpDisjointCopyN ( rhs.reducedCost_, numberColumns_ ,
860 reducedCost_);
861 } else {
862 rowActivity_ = NULL;
863 columnActivity_ = NULL;
864 dual_ = NULL;
865 reducedCost_ = NULL;
866 }
867 ClpDisjointCopyN ( rhs.rowLower_, numberRows_, rowLower_ );
868 ClpDisjointCopyN ( rhs.rowUpper_, numberRows_, rowUpper_ );
869 ClpDisjointCopyN ( rhs.columnLower_, numberColumns_, columnLower_ );
870 assert ((specialOptions_ & 131072) == 0);
871 abort();
872 ClpDisjointCopyN ( rhs.columnUpper_, numberColumns_, columnUpper_ );
873 if (rhs.objective_) {
874 abort(); //check if same
875 objective_ = rhs.objective_->clone();
876 } else {
877 objective_ = NULL;
878 }
879 assert (!rhs.rowObjective_);
880 ClpDisjointCopyN( rhs.status_, numberColumns_ + numberRows_, status_);
881 ray_ = NULL;
882 if (problemStatus_ == 1)
883 ray_ = ClpCopyOfArray (rhs.ray_, numberRows_);
884 else if (problemStatus_ == 2)
885 ray_ = ClpCopyOfArray (rhs.ray_, numberColumns_);
886 assert (!ray_);
887 delete rowCopy_;
888 if (rhs.rowCopy_) {
889 rowCopy_ = rhs.rowCopy_->clone();
890 } else {
891 rowCopy_ = NULL;
892 }
893 delete scaledMatrix_;
894 if (rhs.scaledMatrix_) {
895 scaledMatrix_ = new ClpPackedMatrix(*rhs.scaledMatrix_);
896 } else {
897 scaledMatrix_ = NULL;
898 }
899 delete matrix_;
900 matrix_ = NULL;
901 if (rhs.matrix_) {
902 matrix_ = rhs.matrix_->clone();
903 }
904 if (rhs.savedRowScale_) {
905 assert (savedRowScale_);
906 assert (!rowScale_);
907 ClpDisjointCopyN(rhs.savedRowScale_, 4 * maximumInternalRows_, savedRowScale_);
908 ClpDisjointCopyN(rhs.savedColumnScale_, 4 * maximumInternalColumns_, savedColumnScale_);
909 } else {
910 assert (!savedRowScale_);
911 if (rowScale_) {
912 ClpDisjointCopyN(rhs.rowScale_, numberRows_, rowScale_);
913 ClpDisjointCopyN(rhs.columnScale_, numberColumns_, columnScale_);
914 } else {
915 rowScale_ = NULL;
916 columnScale_ = NULL;
917 }
918 }
919 abort(); // look at resizeDouble and resize
920 }
921 } else {
922 savedRowScale_ = rhs.savedRowScale_;
923 assert (!savedRowScale_);
924 savedColumnScale_ = rhs.savedColumnScale_;
925 rowActivity_ = rhs.rowActivity_;
926 columnActivity_ = rhs.columnActivity_;
927 dual_ = rhs.dual_;
928 reducedCost_ = rhs.reducedCost_;
929 rowLower_ = rhs.rowLower_;
930 rowUpper_ = rhs.rowUpper_;
931 objective_ = rhs.objective_;
932 rowObjective_ = rhs.rowObjective_;
933 columnLower_ = rhs.columnLower_;
934 columnUpper_ = rhs.columnUpper_;
935 matrix_ = rhs.matrix_;
936 rowCopy_ = NULL;
937 scaledMatrix_ = NULL;
938 ray_ = rhs.ray_;
939 //rowScale_ = rhs.rowScale_;
940 //columnScale_ = rhs.columnScale_;
941 lengthNames_ = 0;
942 numberThreads_ = rhs.numberThreads_;
943#ifndef CLP_NO_STD
944 rowNames_ = std::vector<std::string> ();
945 columnNames_ = std::vector<std::string> ();
946#endif
947 integerType_ = NULL;
948 status_ = rhs.status_;
949 }
950 inverseRowScale_ = NULL;
951 inverseColumnScale_ = NULL;
952}
953// Copy contents - resizing if necessary - otherwise re-use memory
954void
955ClpModel::copy(const ClpMatrixBase * from, ClpMatrixBase * & to)
956{
957 assert (from);
958 const ClpPackedMatrix * matrixFrom = (dynamic_cast<const ClpPackedMatrix*>(from));
959 ClpPackedMatrix * matrixTo = (dynamic_cast< ClpPackedMatrix*>(to));
960 if (matrixFrom && matrixTo) {
961 matrixTo->copy(matrixFrom);
962 } else {
963 delete to;
964 to = from->clone();
965 }
966#if 0
967 delete modelPtr_->matrix_;
968 if (continuousModel_->matrix_) {
969 modelPtr_->matrix_ = continuousModel_->matrix_->clone();
970 } else {
971 modelPtr_->matrix_ = NULL;
972 }
973#endif
974}
975/* Borrow model. This is so we dont have to copy large amounts
976 of data around. It assumes a derived class wants to overwrite
977 an empty model with a real one - while it does an algorithm */
978void
979ClpModel::borrowModel(ClpModel & rhs)
980{
981 if (defaultHandler_) {
982 delete handler_;
983 handler_ = NULL;
984 }
985 gutsOfDelete(1);
986 optimizationDirection_ = rhs.optimizationDirection_;
987 numberRows_ = rhs.numberRows_;
988 numberColumns_ = rhs.numberColumns_;
989 delete [] rhs.ray_;
990 rhs.ray_ = NULL;
991 // make sure scaled matrix not copied
992 ClpPackedMatrix * save = rhs.scaledMatrix_;
993 rhs.scaledMatrix_ = NULL;
994 delete scaledMatrix_;
995 scaledMatrix_ = NULL;
996 gutsOfCopy(rhs, 0);
997 rhs.scaledMatrix_ = save;
998 specialOptions_ = rhs.specialOptions_ & ~65536;
999 savedRowScale_ = NULL;
1000 savedColumnScale_ = NULL;
1001 inverseRowScale_ = NULL;
1002 inverseColumnScale_ = NULL;
1003}
1004// Return model - nulls all arrays so can be deleted safely
1005void
1006ClpModel::returnModel(ClpModel & otherModel)
1007{
1008 otherModel.objectiveValue_ = objectiveValue_;
1009 otherModel.numberIterations_ = numberIterations_;
1010 otherModel.problemStatus_ = problemStatus_;
1011 otherModel.secondaryStatus_ = secondaryStatus_;
1012 rowActivity_ = NULL;
1013 columnActivity_ = NULL;
1014 dual_ = NULL;
1015 reducedCost_ = NULL;
1016 rowLower_ = NULL;
1017 rowUpper_ = NULL;
1018 objective_ = NULL;
1019 rowObjective_ = NULL;
1020 columnLower_ = NULL;
1021 columnUpper_ = NULL;
1022 matrix_ = NULL;
1023 if (rowCopy_ != otherModel.rowCopy_)
1024 delete rowCopy_;
1025 rowCopy_ = NULL;
1026 delete scaledMatrix_;
1027 scaledMatrix_ = NULL;
1028 delete [] otherModel.ray_;
1029 otherModel.ray_ = ray_;
1030 ray_ = NULL;
1031 if (rowScale_ && otherModel.rowScale_ != rowScale_) {
1032 delete [] rowScale_;
1033 delete [] columnScale_;
1034 }
1035 rowScale_ = NULL;
1036 columnScale_ = NULL;
1037 //rowScale_=NULL;
1038 //columnScale_=NULL;
1039 // do status
1040 if (otherModel.status_ != status_) {
1041 delete [] otherModel.status_;
1042 otherModel.status_ = status_;
1043 }
1044 status_ = NULL;
1045 if (defaultHandler_) {
1046 delete handler_;
1047 handler_ = NULL;
1048 }
1049 inverseRowScale_ = NULL;
1050 inverseColumnScale_ = NULL;
1051}
1052//#############################################################################
1053// Parameter related methods
1054//#############################################################################
1055
1056bool
1057ClpModel::setIntParam(ClpIntParam key, int value)
1058{
1059 switch (key) {
1060 case ClpMaxNumIteration:
1061 if (value < 0)
1062 return false;
1063 break;
1064 case ClpMaxNumIterationHotStart:
1065 if (value < 0)
1066 return false;
1067 break;
1068 case ClpNameDiscipline:
1069 if (value < 0)
1070 return false;
1071 break;
1072 default:
1073 return false;
1074 }
1075 intParam_[key] = value;
1076 return true;
1077}
1078
1079//-----------------------------------------------------------------------------
1080
1081bool
1082ClpModel::setDblParam(ClpDblParam key, double value)
1083{
1084
1085 switch (key) {
1086 case ClpDualObjectiveLimit:
1087 break;
1088
1089 case ClpPrimalObjectiveLimit:
1090 break;
1091
1092 case ClpDualTolerance:
1093 if (value <= 0.0 || value > 1.0e10)
1094 return false;
1095 break;
1096
1097 case ClpPrimalTolerance:
1098 if (value <= 0.0 || value > 1.0e10)
1099 return false;
1100 break;
1101
1102 case ClpObjOffset:
1103 break;
1104
1105 case ClpMaxSeconds:
1106 if(value >= 0)
1107 value += CoinCpuTime();
1108 else
1109 value = -1.0;
1110 break;
1111
1112 case ClpPresolveTolerance:
1113 if (value <= 0.0 || value > 1.0e10)
1114 return false;
1115 break;
1116
1117 default:
1118 return false;
1119 }
1120 dblParam_[key] = value;
1121 return true;
1122}
1123
1124//-----------------------------------------------------------------------------
1125#ifndef CLP_NO_STD
1126
1127bool
1128ClpModel::setStrParam(ClpStrParam key, const std::string & value)
1129{
1130
1131 switch (key) {
1132 case ClpProbName:
1133 break;
1134
1135 default:
1136 return false;
1137 }
1138 strParam_[key] = value;
1139 return true;
1140}
1141#endif
1142// Useful routines
1143// Returns resized array and deletes incoming
1144double * resizeDouble(double * array , int size, int newSize, double fill,
1145 bool createArray)
1146{
1147 if ((array || createArray) && size < newSize) {
1148 int i;
1149 double * newArray = new double[newSize];
1150 if (array)
1151 CoinMemcpyN(array, CoinMin(newSize, size), newArray);
1152 delete [] array;
1153 array = newArray;
1154 for (i = size; i < newSize; i++)
1155 array[i] = fill;
1156 }
1157 return array;
1158}
1159// Returns resized array and updates size
1160double * deleteDouble(double * array , int size,
1161 int number, const int * which, int & newSize)
1162{
1163 if (array) {
1164 int i ;
1165 char * deleted = new char[size];
1166 int numberDeleted = 0;
1167 CoinZeroN(deleted, size);
1168 for (i = 0; i < number; i++) {
1169 int j = which[i];
1170 if (j >= 0 && j < size && !deleted[j]) {
1171 numberDeleted++;
1172 deleted[j] = 1;
1173 }
1174 }
1175 newSize = size - numberDeleted;
1176 double * newArray = new double[newSize];
1177 int put = 0;
1178 for (i = 0; i < size; i++) {
1179 if (!deleted[i]) {
1180 newArray[put++] = array[i];
1181 }
1182 }
1183 delete [] array;
1184 array = newArray;
1185 delete [] deleted;
1186 }
1187 return array;
1188}
1189char * deleteChar(char * array , int size,
1190 int number, const int * which, int & newSize,
1191 bool ifDelete)
1192{
1193 if (array) {
1194 int i ;
1195 char * deleted = new char[size];
1196 int numberDeleted = 0;
1197 CoinZeroN(deleted, size);
1198 for (i = 0; i < number; i++) {
1199 int j = which[i];
1200 if (j >= 0 && j < size && !deleted[j]) {
1201 numberDeleted++;
1202 deleted[j] = 1;
1203 }
1204 }
1205 newSize = size - numberDeleted;
1206 char * newArray = new char[newSize];
1207 int put = 0;
1208 for (i = 0; i < size; i++) {
1209 if (!deleted[i]) {
1210 newArray[put++] = array[i];
1211 }
1212 }
1213 if (ifDelete)
1214 delete [] array;
1215 array = newArray;
1216 delete [] deleted;
1217 }
1218 return array;
1219}
1220// Create empty ClpPackedMatrix
1221void
1222ClpModel::createEmptyMatrix()
1223{
1224 delete matrix_;
1225 whatsChanged_ = 0;
1226 CoinPackedMatrix matrix2;
1227 matrix_ = new ClpPackedMatrix(matrix2);
1228}
1229/* Really clean up matrix.
1230 a) eliminate all duplicate AND small elements in matrix
1231 b) remove all gaps and set extraGap_ and extraMajor_ to 0.0
1232 c) reallocate arrays and make max lengths equal to lengths
1233 d) orders elements
1234 returns number of elements eliminated or -1 if not ClpMatrix
1235*/
1236int
1237ClpModel::cleanMatrix(double threshold)
1238{
1239 ClpPackedMatrix * matrix = (dynamic_cast< ClpPackedMatrix*>(matrix_));
1240 if (matrix) {
1241 return matrix->getPackedMatrix()->cleanMatrix(threshold);
1242 } else {
1243 return -1;
1244 }
1245}
1246// Resizes
1247void
1248ClpModel::resize (int newNumberRows, int newNumberColumns)
1249{
1250 if (newNumberRows == numberRows_ &&
1251 newNumberColumns == numberColumns_)
1252 return; // nothing to do
1253 whatsChanged_ = 0;
1254 int numberRows2 = newNumberRows;
1255 int numberColumns2 = newNumberColumns;
1256 if (numberRows2 < maximumRows_)
1257 numberRows2 = maximumRows_;
1258 if (numberColumns2 < maximumColumns_)
1259 numberColumns2 = maximumColumns_;
1260 if (numberRows2 > maximumRows_) {
1261 rowActivity_ = resizeDouble(rowActivity_, numberRows_,
1262 newNumberRows, 0.0, true);
1263 dual_ = resizeDouble(dual_, numberRows_,
1264 newNumberRows, 0.0, true);
1265 rowObjective_ = resizeDouble(rowObjective_, numberRows_,
1266 newNumberRows, 0.0, false);
1267 rowLower_ = resizeDouble(rowLower_, numberRows_,
1268 newNumberRows, -COIN_DBL_MAX, true);
1269 rowUpper_ = resizeDouble(rowUpper_, numberRows_,
1270 newNumberRows, COIN_DBL_MAX, true);
1271 }
1272 if (numberColumns2 > maximumColumns_) {
1273 columnActivity_ = resizeDouble(columnActivity_, numberColumns_,
1274 newNumberColumns, 0.0, true);
1275 reducedCost_ = resizeDouble(reducedCost_, numberColumns_,
1276 newNumberColumns, 0.0, true);
1277 }
1278 if (savedRowScale_ && numberRows2 > maximumInternalRows_) {
1279 double * temp;
1280 temp = new double [4*newNumberRows];
1281 CoinFillN(temp, 4 * newNumberRows, 1.0);
1282 CoinMemcpyN(savedRowScale_, numberRows_, temp);
1283 CoinMemcpyN(savedRowScale_ + maximumInternalRows_, numberRows_, temp + newNumberRows);
1284 CoinMemcpyN(savedRowScale_ + 2 * maximumInternalRows_, numberRows_, temp + 2 * newNumberRows);
1285 CoinMemcpyN(savedRowScale_ + 3 * maximumInternalRows_, numberRows_, temp + 3 * newNumberRows);
1286 delete [] savedRowScale_;
1287 savedRowScale_ = temp;
1288 }
1289 if (savedColumnScale_ && numberColumns2 > maximumInternalColumns_) {
1290 double * temp;
1291 temp = new double [4*newNumberColumns];
1292 CoinFillN(temp, 4 * newNumberColumns, 1.0);
1293 CoinMemcpyN(savedColumnScale_, numberColumns_, temp);
1294 CoinMemcpyN(savedColumnScale_ + maximumInternalColumns_, numberColumns_, temp + newNumberColumns);
1295 CoinMemcpyN(savedColumnScale_ + 2 * maximumInternalColumns_, numberColumns_, temp + 2 * newNumberColumns);
1296 CoinMemcpyN(savedColumnScale_ + 3 * maximumInternalColumns_, numberColumns_, temp + 3 * newNumberColumns);
1297 delete [] savedColumnScale_;
1298 savedColumnScale_ = temp;
1299 }
1300 if (objective_ && numberColumns2 > maximumColumns_)
1301 objective_->resize(newNumberColumns);
1302 else if (!objective_)
1303 objective_ = new ClpLinearObjective(NULL, newNumberColumns);
1304 if (numberColumns2 > maximumColumns_) {
1305 columnLower_ = resizeDouble(columnLower_, numberColumns_,
1306 newNumberColumns, 0.0, true);
1307 columnUpper_ = resizeDouble(columnUpper_, numberColumns_,
1308 newNumberColumns, COIN_DBL_MAX, true);
1309 }
1310 if (newNumberRows < numberRows_) {
1311 int * which = new int[numberRows_-newNumberRows];
1312 int i;
1313 for (i = newNumberRows; i < numberRows_; i++)
1314 which[i-newNumberRows] = i;
1315 matrix_->deleteRows(numberRows_ - newNumberRows, which);
1316 delete [] which;
1317 }
1318 if (numberRows_ != newNumberRows || numberColumns_ != newNumberColumns) {
1319 // set state back to unknown
1320 problemStatus_ = -1;
1321 secondaryStatus_ = 0;
1322 delete [] ray_;
1323 ray_ = NULL;
1324 }
1325 setRowScale(NULL);
1326 setColumnScale(NULL);
1327 if (status_) {
1328 if (newNumberColumns + newNumberRows) {
1329 if (newNumberColumns + newNumberRows > maximumRows_ + maximumColumns_) {
1330 unsigned char * tempC = new unsigned char [newNumberColumns+newNumberRows];
1331 unsigned char * tempR = tempC + newNumberColumns;
1332 memset(tempC, 3, newNumberColumns * sizeof(unsigned char));
1333 memset(tempR, 1, newNumberRows * sizeof(unsigned char));
1334 CoinMemcpyN(status_, CoinMin(newNumberColumns, numberColumns_), tempC);
1335 CoinMemcpyN(status_ + numberColumns_, CoinMin(newNumberRows, numberRows_), tempR);
1336 delete [] status_;
1337 status_ = tempC;
1338 } else if (newNumberColumns < numberColumns_) {
1339 memmove(status_ + newNumberColumns, status_ + numberColumns_,
1340 newNumberRows);
1341 } else if (newNumberColumns > numberColumns_) {
1342 memset(status_ + numberColumns_, 3, newNumberColumns - numberColumns_);
1343 memmove(status_ + newNumberColumns, status_ + numberColumns_,
1344 newNumberRows);
1345 }
1346 } else {
1347 // empty model - some systems don't like new [0]
1348 delete [] status_;
1349 status_ = NULL;
1350 }
1351 }
1352#ifndef CLP_NO_STD
1353 if (lengthNames_) {
1354 // redo row and column names
1355 if (numberRows_ < newNumberRows) {
1356 rowNames_.resize(newNumberRows);
1357 lengthNames_ = CoinMax(lengthNames_, 8);
1358 char name[9];
1359 for (int iRow = numberRows_; iRow < newNumberRows; iRow++) {
1360 sprintf(name, "R%7.7d", iRow);
1361 rowNames_[iRow] = name;
1362 }
1363 }
1364 if (numberColumns_ < newNumberColumns) {
1365 columnNames_.resize(newNumberColumns);
1366 lengthNames_ = CoinMax(lengthNames_, 8);
1367 char name[9];
1368 for (int iColumn = numberColumns_; iColumn < newNumberColumns; iColumn++) {
1369 sprintf(name, "C%7.7d", iColumn);
1370 columnNames_[iColumn] = name;
1371 }
1372 }
1373 }
1374#endif
1375 numberRows_ = newNumberRows;
1376 if (newNumberColumns < numberColumns_ && matrix_->getNumCols()) {
1377 int * which = new int[numberColumns_-newNumberColumns];
1378 int i;
1379 for (i = newNumberColumns; i < numberColumns_; i++)
1380 which[i-newNumberColumns] = i;
1381 matrix_->deleteCols(numberColumns_ - newNumberColumns, which);
1382 delete [] which;
1383 }
1384 if (integerType_ && numberColumns2 > maximumColumns_) {
1385 char * temp = new char [newNumberColumns];
1386 CoinZeroN(temp, newNumberColumns);
1387 CoinMemcpyN(integerType_,
1388 CoinMin(newNumberColumns, numberColumns_), temp);
1389 delete [] integerType_;
1390 integerType_ = temp;
1391 }
1392 numberColumns_ = newNumberColumns;
1393 if ((specialOptions_ & 65536) != 0) {
1394 // leave until next create rim to up numbers
1395 }
1396 if (maximumRows_ >= 0) {
1397 if (numberRows_ > maximumRows_)
1398 COIN_DETAIL_PRINT(printf("resize %d rows, %d old maximum rows\n",
1399 numberRows_, maximumRows_));
1400 maximumRows_ = CoinMax(maximumRows_, numberRows_);
1401 maximumColumns_ = CoinMax(maximumColumns_, numberColumns_);
1402 }
1403}
1404// Deletes rows
1405void
1406ClpModel::deleteRows(int number, const int * which)
1407{
1408 if (!number)
1409 return; // nothing to do
1410 whatsChanged_ &= ~(1 + 2 + 4 + 8 + 16 + 32); // all except columns changed
1411 int newSize = 0;
1412 if (maximumRows_ < 0) {
1413 rowActivity_ = deleteDouble(rowActivity_, numberRows_,
1414 number, which, newSize);
1415 dual_ = deleteDouble(dual_, numberRows_,
1416 number, which, newSize);
1417 rowObjective_ = deleteDouble(rowObjective_, numberRows_,
1418 number, which, newSize);
1419 rowLower_ = deleteDouble(rowLower_, numberRows_,
1420 number, which, newSize);
1421 rowUpper_ = deleteDouble(rowUpper_, numberRows_,
1422 number, which, newSize);
1423 if (matrix_->getNumRows())
1424 matrix_->deleteRows(number, which);
1425 //matrix_->removeGaps();
1426 // status
1427 if (status_) {
1428 if (numberColumns_ + newSize) {
1429 unsigned char * tempR = reinterpret_cast<unsigned char *>
1430 (deleteChar(reinterpret_cast<char *>(status_) + numberColumns_,
1431 numberRows_,
1432 number, which, newSize, false));
1433 unsigned char * tempC = new unsigned char [numberColumns_+newSize];
1434 CoinMemcpyN(status_, numberColumns_, tempC);
1435 CoinMemcpyN(tempR, newSize, tempC + numberColumns_);
1436 delete [] tempR;
1437 delete [] status_;
1438 status_ = tempC;
1439 } else {
1440 // empty model - some systems don't like new [0]
1441 delete [] status_;
1442 status_ = NULL;
1443 }
1444 }
1445 } else {
1446 char * deleted = new char [numberRows_];
1447 int i;
1448 int numberDeleted = 0;
1449 CoinZeroN(deleted, numberRows_);
1450 for (i = 0; i < number; i++) {
1451 int j = which[i];
1452 if (j >= 0 && j < numberRows_ && !deleted[j]) {
1453 numberDeleted++;
1454 deleted[j] = 1;
1455 }
1456 }
1457 assert (!rowObjective_);
1458 unsigned char * status2 = status_ + numberColumns_;
1459 for (i = 0; i < numberRows_; i++) {
1460 if (!deleted[i]) {
1461 rowActivity_[newSize] = rowActivity_[i];
1462 dual_[newSize] = dual_[i];
1463 rowLower_[newSize] = rowLower_[i];
1464 rowUpper_[newSize] = rowUpper_[i];
1465 status2[newSize] = status2[i];
1466 newSize++;
1467 }
1468 }
1469 if (matrix_->getNumRows())
1470 matrix_->deleteRows(number, which);
1471 //matrix_->removeGaps();
1472 delete [] deleted;
1473 }
1474#ifndef CLP_NO_STD
1475 // Now works if which out of order
1476 if (lengthNames_) {
1477 char * mark = new char [numberRows_];
1478 CoinZeroN(mark, numberRows_);
1479 int i;
1480 for (i = 0; i < number; i++)
1481 mark[which[i]] = 1;
1482 int k = 0;
1483 for ( i = 0; i < numberRows_; ++i) {
1484 if (!mark[i])
1485 rowNames_[k++] = rowNames_[i];
1486 }
1487 rowNames_.erase(rowNames_.begin() + k, rowNames_.end());
1488 delete [] mark;
1489 }
1490#endif
1491 numberRows_ = newSize;
1492 // set state back to unknown
1493 problemStatus_ = -1;
1494 secondaryStatus_ = 0;
1495 delete [] ray_;
1496 ray_ = NULL;
1497 if (savedRowScale_ != rowScale_) {
1498 delete [] rowScale_;
1499 delete [] columnScale_;
1500 }
1501 rowScale_ = NULL;
1502 columnScale_ = NULL;
1503 delete scaledMatrix_;
1504 scaledMatrix_ = NULL;
1505}
1506// Deletes columns
1507void
1508ClpModel::deleteColumns(int number, const int * which)
1509{
1510 if (!number)
1511 return; // nothing to do
1512 assert (maximumColumns_ < 0);
1513 whatsChanged_ &= ~(1 + 2 + 4 + 8 + 64 + 128 + 256); // all except rows changed
1514 int newSize = 0;
1515 columnActivity_ = deleteDouble(columnActivity_, numberColumns_,
1516 number, which, newSize);
1517 reducedCost_ = deleteDouble(reducedCost_, numberColumns_,
1518 number, which, newSize);
1519 objective_->deleteSome(number, which);
1520 columnLower_ = deleteDouble(columnLower_, numberColumns_,
1521 number, which, newSize);
1522 columnUpper_ = deleteDouble(columnUpper_, numberColumns_,
1523 number, which, newSize);
1524 // possible matrix is not full
1525 if (matrix_->getNumCols() < numberColumns_) {
1526 int * which2 = new int [number];
1527 int n = 0;
1528 int nMatrix = matrix_->getNumCols();
1529 for (int i = 0; i < number; i++) {
1530 if (which[i] < nMatrix)
1531 which2[n++] = which[i];
1532 }
1533 matrix_->deleteCols(n, which2);
1534 delete [] which2;
1535 } else {
1536 matrix_->deleteCols(number, which);
1537 }
1538 //matrix_->removeGaps();
1539 // status
1540 if (status_) {
1541 if (numberRows_ + newSize) {
1542 unsigned char * tempC = reinterpret_cast<unsigned char *>
1543 (deleteChar(reinterpret_cast<char *>(status_),
1544 numberColumns_,
1545 number, which, newSize, false));
1546 unsigned char * temp = new unsigned char [numberRows_+newSize];
1547 CoinMemcpyN(tempC, newSize, temp);
1548 CoinMemcpyN(status_ + numberColumns_, numberRows_, temp + newSize);
1549 delete [] tempC;
1550 delete [] status_;
1551 status_ = temp;
1552 } else {
1553 // empty model - some systems don't like new [0]
1554 delete [] status_;
1555 status_ = NULL;
1556 }
1557 }
1558 integerType_ = deleteChar(integerType_, numberColumns_,
1559 number, which, newSize, true);
1560#ifndef CLP_NO_STD
1561 // Now works if which out of order
1562 if (lengthNames_) {
1563 char * mark = new char [numberColumns_];
1564 CoinZeroN(mark, numberColumns_);
1565 int i;
1566 for (i = 0; i < number; i++)
1567 mark[which[i]] = 1;
1568 int k = 0;
1569 for ( i = 0; i < numberColumns_; ++i) {
1570 if (!mark[i])
1571 columnNames_[k++] = columnNames_[i];
1572 }
1573 columnNames_.erase(columnNames_.begin() + k, columnNames_.end());
1574 delete [] mark;
1575 }
1576#endif
1577 numberColumns_ = newSize;
1578 // set state back to unknown
1579 problemStatus_ = -1;
1580 secondaryStatus_ = 0;
1581 delete [] ray_;
1582 ray_ = NULL;
1583 setRowScale(NULL);
1584 setColumnScale(NULL);
1585}
1586// Add one row
1587void
1588ClpModel::addRow(int numberInRow, const int * columns,
1589 const double * elements, double rowLower, double rowUpper)
1590{
1591 CoinBigIndex starts[2];
1592 starts[0] = 0;
1593 starts[1] = numberInRow;
1594 addRows(1, &rowLower, &rowUpper, starts, columns, elements);
1595}
1596// Add rows
1597void
1598ClpModel::addRows(int number, const double * rowLower,
1599 const double * rowUpper,
1600 const CoinBigIndex * rowStarts, const int * columns,
1601 const double * elements)
1602{
1603 if (number) {
1604 whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed
1605 int numberRowsNow = numberRows_;
1606 resize(numberRowsNow + number, numberColumns_);
1607 double * lower = rowLower_ + numberRowsNow;
1608 double * upper = rowUpper_ + numberRowsNow;
1609 int iRow;
1610 if (rowLower) {
1611 for (iRow = 0; iRow < number; iRow++) {
1612 double value = rowLower[iRow];
1613 if (value < -1.0e20)
1614 value = -COIN_DBL_MAX;
1615 lower[iRow] = value;
1616 }
1617 } else {
1618 for (iRow = 0; iRow < number; iRow++) {
1619 lower[iRow] = -COIN_DBL_MAX;
1620 }
1621 }
1622 if (rowUpper) {
1623 for (iRow = 0; iRow < number; iRow++) {
1624 double value = rowUpper[iRow];
1625 if (value > 1.0e20)
1626 value = COIN_DBL_MAX;
1627 upper[iRow] = value;
1628 }
1629 } else {
1630 for (iRow = 0; iRow < number; iRow++) {
1631 upper[iRow] = COIN_DBL_MAX;
1632 }
1633 }
1634 // Deal with matrix
1635
1636 delete rowCopy_;
1637 rowCopy_ = NULL;
1638 delete scaledMatrix_;
1639 scaledMatrix_ = NULL;
1640 if (!matrix_)
1641 createEmptyMatrix();
1642 setRowScale(NULL);
1643 setColumnScale(NULL);
1644#ifndef CLP_NO_STD
1645 if (lengthNames_) {
1646 rowNames_.resize(numberRows_);
1647 }
1648#endif
1649 if (rowStarts) {
1650 // Make sure matrix has correct number of columns
1651 matrix_->getPackedMatrix()->reserve(numberColumns_, 0, true);
1652 matrix_->appendMatrix(number, 0, rowStarts, columns, elements);
1653 }
1654 }
1655}
1656// Add rows
1657void
1658ClpModel::addRows(int number, const double * rowLower,
1659 const double * rowUpper,
1660 const CoinBigIndex * rowStarts,
1661 const int * rowLengths, const int * columns,
1662 const double * elements)
1663{
1664 if (number) {
1665 CoinBigIndex numberElements = 0;
1666 int iRow;
1667 for (iRow = 0; iRow < number; iRow++)
1668 numberElements += rowLengths[iRow];
1669 int * newStarts = new int[number+1];
1670 int * newIndex = new int[numberElements];
1671 double * newElements = new double[numberElements];
1672 numberElements = 0;
1673 newStarts[0] = 0;
1674 for (iRow = 0; iRow < number; iRow++) {
1675 int iStart = rowStarts[iRow];
1676 int length = rowLengths[iRow];
1677 CoinMemcpyN(columns + iStart, length, newIndex + numberElements);
1678 CoinMemcpyN(elements + iStart, length, newElements + numberElements);
1679 numberElements += length;
1680 newStarts[iRow+1] = numberElements;
1681 }
1682 addRows(number, rowLower, rowUpper,
1683 newStarts, newIndex, newElements);
1684 delete [] newStarts;
1685 delete [] newIndex;
1686 delete [] newElements;
1687 }
1688}
1689#ifndef CLP_NO_VECTOR
1690void
1691ClpModel::addRows(int number, const double * rowLower,
1692 const double * rowUpper,
1693 const CoinPackedVectorBase * const * rows)
1694{
1695 if (!number)
1696 return;
1697 whatsChanged_ &= ~(1 + 2 + 8 + 16 + 32); // all except columns changed
1698 int numberRowsNow = numberRows_;
1699 resize(numberRowsNow + number, numberColumns_);
1700 double * lower = rowLower_ + numberRowsNow;
1701 double * upper = rowUpper_ + numberRowsNow;
1702 int iRow;
1703 if (rowLower) {
1704 for (iRow = 0; iRow < number; iRow++) {
1705 double value = rowLower[iRow];
1706 if (value < -1.0e20)
1707 value = -COIN_DBL_MAX;
1708 lower[iRow] = value;
1709 }
1710 } else {
1711 for (iRow = 0; iRow < number; iRow++) {
1712 lower[iRow] = -COIN_DBL_MAX;
1713 }
1714 }
1715 if (rowUpper) {
1716 for (iRow = 0; iRow < number; iRow++) {
1717 double value = rowUpper[iRow];
1718 if (value > 1.0e20)
1719 value = COIN_DBL_MAX;
1720 upper[iRow] = value;
1721 }
1722 } else {
1723 for (iRow = 0; iRow < number; iRow++) {
1724 upper[iRow] = COIN_DBL_MAX;
1725 }
1726 }
1727 // Deal with matrix
1728
1729 delete rowCopy_;
1730 rowCopy_ = NULL;
1731 delete scaledMatrix_;
1732 scaledMatrix_ = NULL;
1733 if (!matrix_)
1734 createEmptyMatrix();
1735 if (rows)
1736 matrix_->appendRows(number, rows);
1737 setRowScale(NULL);
1738 setColumnScale(NULL);
1739 if (lengthNames_) {
1740 rowNames_.resize(numberRows_);
1741 }
1742}
1743#endif
1744#ifndef SLIM_CLP
1745// Add rows from a build object
1746int
1747ClpModel::addRows(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates)
1748{
1749 CoinAssertHint (buildObject.type() == 0, "Looks as if both addRows and addCols being used"); // check correct
1750 int number = buildObject.numberRows();
1751 int numberErrors = 0;
1752 if (number) {
1753 CoinBigIndex size = 0;
1754 int iRow;
1755 double * lower = new double [number];
1756 double * upper = new double [number];
1757 if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) {
1758 // See if can be +-1
1759 for (iRow = 0; iRow < number; iRow++) {
1760 const int * columns;
1761 const double * elements;
1762 int numberElements = buildObject.row(iRow, lower[iRow],
1763 upper[iRow],
1764 columns, elements);
1765 for (int i = 0; i < numberElements; i++) {
1766 // allow for zero elements
1767 if (elements[i]) {
1768 if (fabs(elements[i]) == 1.0) {
1769 size++;
1770 } else {
1771 // bad
1772 tryPlusMinusOne = false;
1773 }
1774 }
1775 }
1776 if (!tryPlusMinusOne)
1777 break;
1778 }
1779 } else {
1780 // Will add to whatever sort of matrix exists
1781 tryPlusMinusOne = false;
1782 }
1783 if (!tryPlusMinusOne) {
1784 CoinBigIndex numberElements = buildObject.numberElements();
1785 CoinBigIndex * starts = new CoinBigIndex [number+1];
1786 int * column = new int[numberElements];
1787 double * element = new double[numberElements];
1788 starts[0] = 0;
1789 numberElements = 0;
1790 for (iRow = 0; iRow < number; iRow++) {
1791 const int * columns;
1792 const double * elements;
1793 int numberElementsThis = buildObject.row(iRow, lower[iRow], upper[iRow],
1794 columns, elements);
1795 CoinMemcpyN(columns, numberElementsThis, column + numberElements);
1796 CoinMemcpyN(elements, numberElementsThis, element + numberElements);
1797 numberElements += numberElementsThis;
1798 starts[iRow+1] = numberElements;
1799 }
1800 addRows(number, lower, upper, NULL);
1801 // make sure matrix has enough columns
1802 matrix_->setDimensions(-1, numberColumns_);
1803 numberErrors = matrix_->appendMatrix(number, 0, starts, column, element,
1804 checkDuplicates ? numberColumns_ : -1);
1805 delete [] starts;
1806 delete [] column;
1807 delete [] element;
1808 } else {
1809 char * which = NULL; // for duplicates
1810 if (checkDuplicates) {
1811 which = new char[numberColumns_];
1812 CoinZeroN(which, numberColumns_);
1813 }
1814 // build +-1 matrix
1815 // arrays already filled in
1816 addRows(number, lower, upper, NULL);
1817 CoinBigIndex * startPositive = new CoinBigIndex [numberColumns_+1];
1818 CoinBigIndex * startNegative = new CoinBigIndex [numberColumns_];
1819 int * indices = new int [size];
1820 CoinZeroN(startPositive, numberColumns_);
1821 CoinZeroN(startNegative, numberColumns_);
1822 int maxColumn = -1;
1823 // need two passes
1824 for (iRow = 0; iRow < number; iRow++) {
1825 const int * columns;
1826 const double * elements;
1827 int numberElements = buildObject.row(iRow, lower[iRow],
1828 upper[iRow],
1829 columns, elements);
1830 for (int i = 0; i < numberElements; i++) {
1831 int iColumn = columns[i];
1832 if (checkDuplicates) {
1833 if (iColumn >= numberColumns_) {
1834 if(which[iColumn])
1835 numberErrors++;
1836 else
1837 which[iColumn] = 1;
1838 } else {
1839 numberErrors++;
1840 // and may as well switch off
1841 checkDuplicates = false;
1842 }
1843 }
1844 maxColumn = CoinMax(maxColumn, iColumn);
1845 if (elements[i] == 1.0) {
1846 startPositive[iColumn]++;
1847 } else if (elements[i] == -1.0) {
1848 startNegative[iColumn]++;
1849 }
1850 }
1851 if (checkDuplicates) {
1852 for (int i = 0; i < numberElements; i++) {
1853 int iColumn = columns[i];
1854 which[iColumn] = 0;
1855 }
1856 }
1857 }
1858 // check size
1859 int numberColumns = maxColumn + 1;
1860 CoinAssertHint (numberColumns <= numberColumns_,
1861 "rows having column indices >= numberColumns_");
1862 size = 0;
1863 int iColumn;
1864 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1865 CoinBigIndex n = startPositive[iColumn];
1866 startPositive[iColumn] = size;
1867 size += n;
1868 n = startNegative[iColumn];
1869 startNegative[iColumn] = size;
1870 size += n;
1871 }
1872 startPositive[numberColumns_] = size;
1873 for (iRow = 0; iRow < number; iRow++) {
1874 const int * columns;
1875 const double * elements;
1876 int numberElements = buildObject.row(iRow, lower[iRow],
1877 upper[iRow],
1878 columns, elements);
1879 for (int i = 0; i < numberElements; i++) {
1880 int iColumn = columns[i];
1881 maxColumn = CoinMax(maxColumn, iColumn);
1882 if (elements[i] == 1.0) {
1883 CoinBigIndex position = startPositive[iColumn];
1884 indices[position] = iRow;
1885 startPositive[iColumn]++;
1886 } else if (elements[i] == -1.0) {
1887 CoinBigIndex position = startNegative[iColumn];
1888 indices[position] = iRow;
1889 startNegative[iColumn]++;
1890 }
1891 }
1892 }
1893 // and now redo starts
1894 for (iColumn = numberColumns_ - 1; iColumn >= 0; iColumn--) {
1895 startPositive[iColumn+1] = startNegative[iColumn];
1896 startNegative[iColumn] = startPositive[iColumn];
1897 }
1898 startPositive[0] = 0;
1899 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
1900 CoinBigIndex start = startPositive[iColumn];
1901 CoinBigIndex end = startNegative[iColumn];
1902 std::sort(indices + start, indices + end);
1903 start = startNegative[iColumn];
1904 end = startPositive[iColumn+1];
1905 std::sort(indices + start, indices + end);
1906 }
1907 // Get good object
1908 delete matrix_;
1909 ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
1910 matrix->passInCopy(numberRows_, numberColumns,
1911 true, indices, startPositive, startNegative);
1912 matrix_ = matrix;
1913 delete [] which;
1914 }
1915 delete [] lower;
1916 delete [] upper;
1917 // make sure matrix correct size
1918 matrix_->setDimensions(numberRows_, numberColumns_);
1919 }
1920 return numberErrors;
1921}
1922#endif
1923#ifndef SLIM_NOIO
1924// Add rows from a model object
1925int
1926ClpModel::addRows( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates)
1927{
1928 if (modelObject.numberElements() == 0)
1929 return 0;
1930 bool goodState = true;
1931 int numberErrors = 0;
1932 if (modelObject.columnLowerArray()) {
1933 // some column information exists
1934 int numberColumns2 = modelObject.numberColumns();
1935 const double * columnLower = modelObject.columnLowerArray();
1936 const double * columnUpper = modelObject.columnUpperArray();
1937 const double * objective = modelObject.objectiveArray();
1938 const int * integerType = modelObject.integerTypeArray();
1939 for (int i = 0; i < numberColumns2; i++) {
1940 if (columnLower[i] != 0.0)
1941 goodState = false;
1942 if (columnUpper[i] != COIN_DBL_MAX)
1943 goodState = false;
1944 if (objective[i] != 0.0)
1945 goodState = false;
1946 if (integerType[i] != 0)
1947 goodState = false;
1948 }
1949 }
1950 if (goodState) {
1951 // can do addRows
1952 // Set arrays for normal use
1953 double * rowLower = modelObject.rowLowerArray();
1954 double * rowUpper = modelObject.rowUpperArray();
1955 double * columnLower = modelObject.columnLowerArray();
1956 double * columnUpper = modelObject.columnUpperArray();
1957 double * objective = modelObject.objectiveArray();
1958 int * integerType = modelObject.integerTypeArray();
1959 double * associated = modelObject.associatedArray();
1960 // If strings then do copies
1961 if (modelObject.stringsExist()) {
1962 numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
1963 objective, integerType, associated);
1964 }
1965 int numberRows = numberRows_; // save number of rows
1966 int numberRows2 = modelObject.numberRows();
1967 if (numberRows2 && !numberErrors) {
1968 CoinBigIndex * startPositive = NULL;
1969 CoinBigIndex * startNegative = NULL;
1970 int numberColumns = modelObject.numberColumns();
1971 if ((!matrix_ || !matrix_->getNumElements()) && !numberRows && tryPlusMinusOne) {
1972 startPositive = new CoinBigIndex[numberColumns+1];
1973 startNegative = new CoinBigIndex[numberColumns];
1974 modelObject.countPlusMinusOne(startPositive, startNegative, associated);
1975 if (startPositive[0] < 0) {
1976 // no good
1977 tryPlusMinusOne = false;
1978 delete [] startPositive;
1979 delete [] startNegative;
1980 }
1981 } else {
1982 // Will add to whatever sort of matrix exists
1983 tryPlusMinusOne = false;
1984 }
1985 assert (rowLower);
1986 addRows(numberRows2, rowLower, rowUpper, NULL, NULL, NULL);
1987#ifndef SLIM_CLP
1988 if (!tryPlusMinusOne) {
1989#endif
1990 CoinPackedMatrix matrix;
1991 modelObject.createPackedMatrix(matrix, associated);
1992 assert (!matrix.getExtraGap());
1993 if (matrix_->getNumRows()) {
1994 // matrix by rows
1995 matrix.reverseOrdering();
1996 assert (!matrix.getExtraGap());
1997 const int * column = matrix.getIndices();
1998 //const int * rowLength = matrix.getVectorLengths();
1999 const CoinBigIndex * rowStart = matrix.getVectorStarts();
2000 const double * element = matrix.getElements();
2001 // make sure matrix has enough columns
2002 matrix_->setDimensions(-1, numberColumns_);
2003 numberErrors += matrix_->appendMatrix(numberRows2, 0, rowStart, column, element,
2004 checkDuplicates ? numberColumns_ : -1);
2005 } else {
2006 delete matrix_;
2007 matrix_ = new ClpPackedMatrix(matrix);
2008 }
2009#ifndef SLIM_CLP
2010 } else {
2011 // create +-1 matrix
2012 CoinBigIndex size = startPositive[numberColumns];
2013 int * indices = new int[size];
2014 modelObject.createPlusMinusOne(startPositive, startNegative, indices,
2015 associated);
2016 // Get good object
2017 ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2018 matrix->passInCopy(numberRows2, numberColumns,
2019 true, indices, startPositive, startNegative);
2020 delete matrix_;
2021 matrix_ = matrix;
2022 }
2023 // Do names if wanted
2024 if (modelObject.rowNames()->numberItems()) {
2025 const char *const * rowNames = modelObject.rowNames()->names();
2026 copyRowNames(rowNames, numberRows, numberRows_);
2027 }
2028#endif
2029 }
2030 if (rowLower != modelObject.rowLowerArray()) {
2031 delete [] rowLower;
2032 delete [] rowUpper;
2033 delete [] columnLower;
2034 delete [] columnUpper;
2035 delete [] objective;
2036 delete [] integerType;
2037 delete [] associated;
2038 if (numberErrors)
2039 handler_->message(CLP_BAD_STRING_VALUES, messages_)
2040 << numberErrors
2041 << CoinMessageEol;
2042 }
2043 return numberErrors;
2044 } else {
2045 // not suitable for addRows
2046 handler_->message(CLP_COMPLICATED_MODEL, messages_)
2047 << modelObject.numberRows()
2048 << modelObject.numberColumns()
2049 << CoinMessageEol;
2050 return -1;
2051 }
2052}
2053#endif
2054// Add one column
2055void
2056ClpModel::addColumn(int numberInColumn,
2057 const int * rows,
2058 const double * elements,
2059 double columnLower,
2060 double columnUpper,
2061 double objective)
2062{
2063 CoinBigIndex starts[2];
2064 starts[0] = 0;
2065 starts[1] = numberInColumn;
2066 addColumns(1, &columnLower, &columnUpper, &objective, starts, rows, elements);
2067}
2068// Add columns
2069void
2070ClpModel::addColumns(int number, const double * columnLower,
2071 const double * columnUpper,
2072 const double * objIn,
2073 const int * columnStarts, const int * rows,
2074 const double * elements)
2075{
2076 // Create a list of CoinPackedVectors
2077 if (number) {
2078 whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed
2079 int numberColumnsNow = numberColumns_;
2080 resize(numberRows_, numberColumnsNow + number);
2081 double * lower = columnLower_ + numberColumnsNow;
2082 double * upper = columnUpper_ + numberColumnsNow;
2083 double * obj = objective() + numberColumnsNow;
2084 int iColumn;
2085 if (columnLower) {
2086 for (iColumn = 0; iColumn < number; iColumn++) {
2087 double value = columnLower[iColumn];
2088 if (value < -1.0e20)
2089 value = -COIN_DBL_MAX;
2090 lower[iColumn] = value;
2091 }
2092 } else {
2093 for (iColumn = 0; iColumn < number; iColumn++) {
2094 lower[iColumn] = 0.0;
2095 }
2096 }
2097 if (columnUpper) {
2098 for (iColumn = 0; iColumn < number; iColumn++) {
2099 double value = columnUpper[iColumn];
2100 if (value > 1.0e20)
2101 value = COIN_DBL_MAX;
2102 upper[iColumn] = value;
2103 }
2104 } else {
2105 for (iColumn = 0; iColumn < number; iColumn++) {
2106 upper[iColumn] = COIN_DBL_MAX;
2107 }
2108 }
2109 if (objIn) {
2110 for (iColumn = 0; iColumn < number; iColumn++) {
2111 obj[iColumn] = objIn[iColumn];
2112 }
2113 } else {
2114 for (iColumn = 0; iColumn < number; iColumn++) {
2115 obj[iColumn] = 0.0;
2116 }
2117 }
2118 // Deal with matrix
2119
2120 delete rowCopy_;
2121 rowCopy_ = NULL;
2122 delete scaledMatrix_;
2123 scaledMatrix_ = NULL;
2124 if (!matrix_)
2125 createEmptyMatrix();
2126 setRowScale(NULL);
2127 setColumnScale(NULL);
2128#ifndef CLP_NO_STD
2129 if (lengthNames_) {
2130 columnNames_.resize(numberColumns_);
2131 }
2132#endif
2133 //if (elements)
2134 matrix_->appendMatrix(number, 1, columnStarts, rows, elements);
2135 }
2136}
2137// Add columns
2138void
2139ClpModel::addColumns(int number, const double * columnLower,
2140 const double * columnUpper,
2141 const double * objIn,
2142 const int * columnStarts,
2143 const int * columnLengths, const int * rows,
2144 const double * elements)
2145{
2146 if (number) {
2147 CoinBigIndex numberElements = 0;
2148 int iColumn;
2149 for (iColumn = 0; iColumn < number; iColumn++)
2150 numberElements += columnLengths[iColumn];
2151 int * newStarts = new int[number+1];
2152 int * newIndex = new int[numberElements];
2153 double * newElements = new double[numberElements];
2154 numberElements = 0;
2155 newStarts[0] = 0;
2156 for (iColumn = 0; iColumn < number; iColumn++) {
2157 int iStart = columnStarts[iColumn];
2158 int length = columnLengths[iColumn];
2159 CoinMemcpyN(rows + iStart, length, newIndex + numberElements);
2160 CoinMemcpyN(elements + iStart, length, newElements + numberElements);
2161 numberElements += length;
2162 newStarts[iColumn+1] = numberElements;
2163 }
2164 addColumns(number, columnLower, columnUpper, objIn,
2165 newStarts, newIndex, newElements);
2166 delete [] newStarts;
2167 delete [] newIndex;
2168 delete [] newElements;
2169 }
2170}
2171#ifndef CLP_NO_VECTOR
2172void
2173ClpModel::addColumns(int number, const double * columnLower,
2174 const double * columnUpper,
2175 const double * objIn,
2176 const CoinPackedVectorBase * const * columns)
2177{
2178 if (!number)
2179 return;
2180 whatsChanged_ &= ~(1 + 2 + 4 + 64 + 128 + 256); // all except rows changed
2181 int numberColumnsNow = numberColumns_;
2182 resize(numberRows_, numberColumnsNow + number);
2183 double * lower = columnLower_ + numberColumnsNow;
2184 double * upper = columnUpper_ + numberColumnsNow;
2185 double * obj = objective() + numberColumnsNow;
2186 int iColumn;
2187 if (columnLower) {
2188 for (iColumn = 0; iColumn < number; iColumn++) {
2189 double value = columnLower[iColumn];
2190 if (value < -1.0e20)
2191 value = -COIN_DBL_MAX;
2192 lower[iColumn] = value;
2193 }
2194 } else {
2195 for (iColumn = 0; iColumn < number; iColumn++) {
2196 lower[iColumn] = 0.0;
2197 }
2198 }
2199 if (columnUpper) {
2200 for (iColumn = 0; iColumn < number; iColumn++) {
2201 double value = columnUpper[iColumn];
2202 if (value > 1.0e20)
2203 value = COIN_DBL_MAX;
2204 upper[iColumn] = value;
2205 }
2206 } else {
2207 for (iColumn = 0; iColumn < number; iColumn++) {
2208 upper[iColumn] = COIN_DBL_MAX;
2209 }
2210 }
2211 if (objIn) {
2212 for (iColumn = 0; iColumn < number; iColumn++) {
2213 obj[iColumn] = objIn[iColumn];
2214 }
2215 } else {
2216 for (iColumn = 0; iColumn < number; iColumn++) {
2217 obj[iColumn] = 0.0;
2218 }
2219 }
2220 // Deal with matrix
2221
2222 delete rowCopy_;
2223 rowCopy_ = NULL;
2224 delete scaledMatrix_;
2225 scaledMatrix_ = NULL;
2226 if (!matrix_)
2227 createEmptyMatrix();
2228 if (columns)
2229 matrix_->appendCols(number, columns);
2230 setRowScale(NULL);
2231 setColumnScale(NULL);
2232 if (lengthNames_) {
2233 columnNames_.resize(numberColumns_);
2234 }
2235}
2236#endif
2237#ifndef SLIM_CLP
2238// Add columns from a build object
2239int
2240ClpModel::addColumns(const CoinBuild & buildObject, bool tryPlusMinusOne, bool checkDuplicates)
2241{
2242 CoinAssertHint (buildObject.type() == 1, "Looks as if both addRows and addCols being used"); // check correct
2243 int number = buildObject.numberColumns();
2244 int numberErrors = 0;
2245 if (number) {
2246 CoinBigIndex size = 0;
2247 int maximumLength = 0;
2248 double * lower = new double [number];
2249 double * upper = new double [number];
2250 int iColumn;
2251 double * objective = new double [number];
2252 if ((!matrix_ || !matrix_->getNumElements()) && tryPlusMinusOne) {
2253 // See if can be +-1
2254 for (iColumn = 0; iColumn < number; iColumn++) {
2255 const int * rows;
2256 const double * elements;
2257 int numberElements = buildObject.column(iColumn, lower[iColumn],
2258 upper[iColumn], objective[iColumn],
2259 rows, elements);
2260 maximumLength = CoinMax(maximumLength, numberElements);
2261 for (int i = 0; i < numberElements; i++) {
2262 // allow for zero elements
2263 if (elements[i]) {
2264 if (fabs(elements[i]) == 1.0) {
2265 size++;
2266 } else {
2267 // bad
2268 tryPlusMinusOne = false;
2269 }
2270 }
2271 }
2272 if (!tryPlusMinusOne)
2273 break;
2274 }
2275 } else {
2276 // Will add to whatever sort of matrix exists
2277 tryPlusMinusOne = false;
2278 }
2279 if (!tryPlusMinusOne) {
2280 CoinBigIndex numberElements = buildObject.numberElements();
2281 CoinBigIndex * starts = new CoinBigIndex [number+1];
2282 int * row = new int[numberElements];
2283 double * element = new double[numberElements];
2284 starts[0] = 0;
2285 numberElements = 0;
2286 for (iColumn = 0; iColumn < number; iColumn++) {
2287 const int * rows;
2288 const double * elements;
2289 int numberElementsThis = buildObject.column(iColumn, lower[iColumn], upper[iColumn],
2290 objective[iColumn], rows, elements);
2291 CoinMemcpyN(rows, numberElementsThis, row + numberElements);
2292 CoinMemcpyN(elements, numberElementsThis, element + numberElements);
2293 numberElements += numberElementsThis;
2294 starts[iColumn+1] = numberElements;
2295 }
2296 addColumns(number, lower, upper, objective, NULL);
2297 // make sure matrix has enough rows
2298 matrix_->setDimensions(numberRows_, -1);
2299 numberErrors = matrix_->appendMatrix(number, 1, starts, row, element,
2300 checkDuplicates ? numberRows_ : -1);
2301 delete [] starts;
2302 delete [] row;
2303 delete [] element;
2304 } else {
2305 // arrays already filled in
2306 addColumns(number, lower, upper, objective, NULL);
2307 char * which = NULL; // for duplicates
2308 if (checkDuplicates) {
2309 which = new char[numberRows_];
2310 CoinZeroN(which, numberRows_);
2311 }
2312 // build +-1 matrix
2313 CoinBigIndex * startPositive = new CoinBigIndex [number+1];
2314 CoinBigIndex * startNegative = new CoinBigIndex [number];
2315 int * indices = new int [size];
2316 int * neg = new int[maximumLength];
2317 startPositive[0] = 0;
2318 size = 0;
2319 int maxRow = -1;
2320 for (iColumn = 0; iColumn < number; iColumn++) {
2321 const int * rows;
2322 const double * elements;
2323 int numberElements = buildObject.column(iColumn, lower[iColumn],
2324 upper[iColumn], objective[iColumn],
2325 rows, elements);
2326 int nNeg = 0;
2327 CoinBigIndex start = size;
2328 for (int i = 0; i < numberElements; i++) {
2329 int iRow = rows[i];
2330 if (checkDuplicates) {
2331 if (iRow >= numberRows_) {
2332 if(which[iRow])
2333 numberErrors++;
2334 else
2335 which[iRow] = 1;
2336 } else {
2337 numberErrors++;
2338 // and may as well switch off
2339 checkDuplicates = false;
2340 }
2341 }
2342 maxRow = CoinMax(maxRow, iRow);
2343 if (elements[i] == 1.0) {
2344 indices[size++] = iRow;
2345 } else if (elements[i] == -1.0) {
2346 neg[nNeg++] = iRow;
2347 }
2348 }
2349 std::sort(indices + start, indices + size);
2350 std::sort(neg, neg + nNeg);
2351 startNegative[iColumn] = size;
2352 CoinMemcpyN(neg, nNeg, indices + size);
2353 size += nNeg;
2354 startPositive[iColumn+1] = size;
2355 }
2356 delete [] neg;
2357 // check size
2358 assert (maxRow + 1 <= numberRows_);
2359 // Get good object
2360 delete matrix_;
2361 ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2362 matrix->passInCopy(numberRows_, number, true, indices, startPositive, startNegative);
2363 matrix_ = matrix;
2364 delete [] which;
2365 }
2366 delete [] objective;
2367 delete [] lower;
2368 delete [] upper;
2369 }
2370 return 0;
2371}
2372#endif
2373#ifndef SLIM_NOIO
2374// Add columns from a model object
2375int
2376ClpModel::addColumns( CoinModel & modelObject, bool tryPlusMinusOne, bool checkDuplicates)
2377{
2378 if (modelObject.numberElements() == 0)
2379 return 0;
2380 bool goodState = true;
2381 if (modelObject.rowLowerArray()) {
2382 // some row information exists
2383 int numberRows2 = modelObject.numberRows();
2384 const double * rowLower = modelObject.rowLowerArray();
2385 const double * rowUpper = modelObject.rowUpperArray();
2386 for (int i = 0; i < numberRows2; i++) {
2387 if (rowLower[i] != -COIN_DBL_MAX)
2388 goodState = false;
2389 if (rowUpper[i] != COIN_DBL_MAX)
2390 goodState = false;
2391 }
2392 }
2393 if (goodState) {
2394 // can do addColumns
2395 int numberErrors = 0;
2396 // Set arrays for normal use
2397 double * rowLower = modelObject.rowLowerArray();
2398 double * rowUpper = modelObject.rowUpperArray();
2399 double * columnLower = modelObject.columnLowerArray();
2400 double * columnUpper = modelObject.columnUpperArray();
2401 double * objective = modelObject.objectiveArray();
2402 int * integerType = modelObject.integerTypeArray();
2403 double * associated = modelObject.associatedArray();
2404 // If strings then do copies
2405 if (modelObject.stringsExist()) {
2406 numberErrors = modelObject.createArrays(rowLower, rowUpper, columnLower, columnUpper,
2407 objective, integerType, associated);
2408 }
2409 int numberColumns = numberColumns_; // save number of columns
2410 int numberColumns2 = modelObject.numberColumns();
2411 if (numberColumns2 && !numberErrors) {
2412 CoinBigIndex * startPositive = NULL;
2413 CoinBigIndex * startNegative = NULL;
2414 if ((!matrix_ || !matrix_->getNumElements()) && !numberColumns && tryPlusMinusOne) {
2415 startPositive = new CoinBigIndex[numberColumns2+1];
2416 startNegative = new CoinBigIndex[numberColumns2];
2417 modelObject.countPlusMinusOne(startPositive, startNegative, associated);
2418 if (startPositive[0] < 0) {
2419 // no good
2420 tryPlusMinusOne = false;
2421 delete [] startPositive;
2422 delete [] startNegative;
2423 }
2424 } else {
2425 // Will add to whatever sort of matrix exists
2426 tryPlusMinusOne = false;
2427 }
2428 assert (columnLower);
2429 addColumns(numberColumns2, columnLower, columnUpper, objective, NULL, NULL, NULL);
2430#ifndef SLIM_CLP
2431 if (!tryPlusMinusOne) {
2432#endif
2433 CoinPackedMatrix matrix;
2434 modelObject.createPackedMatrix(matrix, associated);
2435 assert (!matrix.getExtraGap());
2436 if (matrix_->getNumCols()) {
2437 const int * row = matrix.getIndices();
2438 //const int * columnLength = matrix.getVectorLengths();
2439 const CoinBigIndex * columnStart = matrix.getVectorStarts();
2440 const double * element = matrix.getElements();
2441 // make sure matrix has enough rows
2442 matrix_->setDimensions(numberRows_, -1);
2443 numberErrors += matrix_->appendMatrix(numberColumns2, 1, columnStart, row, element,
2444 checkDuplicates ? numberRows_ : -1);
2445 } else {
2446 delete matrix_;
2447 matrix_ = new ClpPackedMatrix(matrix);
2448 }
2449#ifndef SLIM_CLP
2450 } else {
2451 // create +-1 matrix
2452 CoinBigIndex size = startPositive[numberColumns2];
2453 int * indices = new int[size];
2454 modelObject.createPlusMinusOne(startPositive, startNegative, indices,
2455 associated);
2456 // Get good object
2457 ClpPlusMinusOneMatrix * matrix = new ClpPlusMinusOneMatrix();
2458 matrix->passInCopy(numberRows_, numberColumns2,
2459 true, indices, startPositive, startNegative);
2460 delete matrix_;
2461 matrix_ = matrix;
2462 }
2463#endif
2464#ifndef CLP_NO_STD
2465 // Do names if wanted
2466 if (modelObject.columnNames()->numberItems()) {
2467 const char *const * columnNames = modelObject.columnNames()->names();
2468 copyColumnNames(columnNames, numberColumns, numberColumns_);
2469 }
2470#endif
2471 // Do integers if wanted
2472 assert(integerType);
2473 for (int iColumn = 0; iColumn < numberColumns2; iColumn++) {
2474 if (integerType[iColumn])
2475 setInteger(iColumn + numberColumns);
2476 }
2477 }
2478 if (columnLower != modelObject.columnLowerArray()) {
2479 delete [] rowLower;
2480 delete [] rowUpper;
2481 delete [] columnLower;
2482 delete [] columnUpper;
2483 delete [] objective;
2484 delete [] integerType;
2485 delete [] associated;
2486 if (numberErrors)
2487 handler_->message(CLP_BAD_STRING_VALUES, messages_)
2488 << numberErrors
2489 << CoinMessageEol;
2490 }
2491 return numberErrors;
2492 } else {
2493 // not suitable for addColumns
2494 handler_->message(CLP_COMPLICATED_MODEL, messages_)
2495 << modelObject.numberRows()
2496 << modelObject.numberColumns()
2497 << CoinMessageEol;
2498 return -1;
2499 }
2500}
2501#endif
2502// chgRowLower
2503void
2504ClpModel::chgRowLower(const double * rowLower)
2505{
2506 int numberRows = numberRows_;
2507 int iRow;
2508 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2509 if (rowLower) {
2510 for (iRow = 0; iRow < numberRows; iRow++) {
2511 double value = rowLower[iRow];
2512 if (value < -1.0e20)
2513 value = -COIN_DBL_MAX;
2514 rowLower_[iRow] = value;
2515 }
2516 } else {
2517 for (iRow = 0; iRow < numberRows; iRow++) {
2518 rowLower_[iRow] = -COIN_DBL_MAX;
2519 }
2520 }
2521}
2522// chgRowUpper
2523void
2524ClpModel::chgRowUpper(const double * rowUpper)
2525{
2526 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2527 int numberRows = numberRows_;
2528 int iRow;
2529 if (rowUpper) {
2530 for (iRow = 0; iRow < numberRows; iRow++) {
2531 double value = rowUpper[iRow];
2532 if (value > 1.0e20)
2533 value = COIN_DBL_MAX;
2534 rowUpper_[iRow] = value;
2535 }
2536 } else {
2537 for (iRow = 0; iRow < numberRows; iRow++) {
2538 rowUpper_[iRow] = COIN_DBL_MAX;
2539 }
2540 }
2541}
2542// chgColumnLower
2543void
2544ClpModel::chgColumnLower(const double * columnLower)
2545{
2546 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2547 int numberColumns = numberColumns_;
2548 int iColumn;
2549 if (columnLower) {
2550 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2551 double value = columnLower[iColumn];
2552 if (value < -1.0e20)
2553 value = -COIN_DBL_MAX;
2554 columnLower_[iColumn] = value;
2555 }
2556 } else {
2557 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2558 columnLower_[iColumn] = 0.0;
2559 }
2560 }
2561}
2562// chgColumnUpper
2563void
2564ClpModel::chgColumnUpper(const double * columnUpper)
2565{
2566 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2567 int numberColumns = numberColumns_;
2568 int iColumn;
2569 if (columnUpper) {
2570 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2571 double value = columnUpper[iColumn];
2572 if (value > 1.0e20)
2573 value = COIN_DBL_MAX;
2574 columnUpper_[iColumn] = value;
2575 }
2576 } else {
2577 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2578 columnUpper_[iColumn] = COIN_DBL_MAX;
2579 }
2580 }
2581}
2582// chgObjCoefficients
2583void
2584ClpModel::chgObjCoefficients(const double * objIn)
2585{
2586 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
2587 double * obj = objective();
2588 int numberColumns = numberColumns_;
2589 int iColumn;
2590 if (objIn) {
2591 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2592 obj[iColumn] = objIn[iColumn];
2593 }
2594 } else {
2595 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
2596 obj[iColumn] = 0.0;
2597 }
2598 }
2599}
2600// Infeasibility/unbounded ray (NULL returned if none/wrong)
2601double *
2602ClpModel::infeasibilityRay() const
2603{
2604 double * array = NULL;
2605 if (problemStatus_ == 1 && ray_) {
2606 array = ClpCopyOfArray(ray_, numberRows_);
2607#ifndef CLP_NO_SWAP_SIGN
2608 // swap signs to be consistent with norm
2609 for (int i = 0; i < numberRows_; i++)
2610 array[i] = -array[i];
2611#endif
2612#if 0
2613 // clean up
2614 double largest = 1.0e-30;
2615 double smallest = COIN_DBL_MAX;
2616 int i;
2617 for (i = 0; i < numberRows_; i++) {
2618 double value = fabs(array[i]);
2619 smallest = CoinMin(smallest, value);
2620 largest = CoinMax(largest, value);
2621 }
2622#endif
2623 }
2624 return array;
2625}
2626double *
2627ClpModel::unboundedRay() const
2628{
2629 double * array = NULL;
2630 if (problemStatus_ == 2)
2631 array = ClpCopyOfArray(ray_, numberColumns_);
2632 return array;
2633}
2634void
2635ClpModel::setMaximumIterations(int value)
2636{
2637 if(value >= 0)
2638 intParam_[ClpMaxNumIteration] = value;
2639}
2640void
2641ClpModel::setMaximumSeconds(double value)
2642{
2643 if(value >= 0)
2644 dblParam_[ClpMaxSeconds] = value + CoinCpuTime();
2645 else
2646 dblParam_[ClpMaxSeconds] = -1.0;
2647}
2648// Returns true if hit maximum iterations (or time)
2649bool
2650ClpModel::hitMaximumIterations() const
2651{
2652 // replaced - compiler error? bool hitMax= (numberIterations_>=maximumIterations());
2653 bool hitMax = (numberIterations_ >= intParam_[ClpMaxNumIteration]);
2654 if (dblParam_[ClpMaxSeconds] >= 0.0 && !hitMax) {
2655 hitMax = (CoinCpuTime() >= dblParam_[ClpMaxSeconds]);
2656 }
2657 return hitMax;
2658}
2659// On stopped - sets secondary status
2660void
2661ClpModel::onStopped()
2662{
2663 if (problemStatus_ == 3) {
2664 secondaryStatus_ = 0;
2665 if (CoinCpuTime() >= dblParam_[ClpMaxSeconds] && dblParam_[ClpMaxSeconds] >= 0.0)
2666 secondaryStatus_ = 9;
2667 }
2668}
2669// Pass in Message handler (not deleted at end)
2670void
2671ClpModel::passInMessageHandler(CoinMessageHandler * handler)
2672{
2673 if (defaultHandler_)
2674 delete handler_;
2675 defaultHandler_ = false;
2676 handler_ = handler;
2677}
2678// Pass in Message handler (not deleted at end) and return current
2679CoinMessageHandler *
2680ClpModel::pushMessageHandler(CoinMessageHandler * handler,
2681 bool & oldDefault)
2682{
2683 CoinMessageHandler * returnValue = handler_;
2684 oldDefault = defaultHandler_;
2685 defaultHandler_ = false;
2686 handler_ = handler;
2687 return returnValue;
2688}
2689// back to previous message handler
2690void
2691ClpModel::popMessageHandler(CoinMessageHandler * oldHandler, bool oldDefault)
2692{
2693 if (defaultHandler_)
2694 delete handler_;
2695 defaultHandler_ = oldDefault;
2696 handler_ = oldHandler;
2697}
2698// Set language
2699void
2700ClpModel::newLanguage(CoinMessages::Language language)
2701{
2702 messages_ = ClpMessage(language);
2703}
2704#ifndef SLIM_NOIO
2705// Read an mps file from the given filename
2706int
2707ClpModel::readMps(const char *fileName,
2708 bool keepNames,
2709 bool ignoreErrors)
2710{
2711 if (!strcmp(fileName, "-") || !strcmp(fileName, "stdin")) {
2712 // stdin
2713 } else {
2714 std::string name = fileName;
2715 bool readable = fileCoinReadable(name);
2716 if (!readable) {
2717 handler_->message(CLP_UNABLE_OPEN, messages_)
2718 << fileName << CoinMessageEol;
2719 return -1;
2720 }
2721 }
2722 CoinMpsIO m;
2723 m.passInMessageHandler(handler_);
2724 *m.messagesPointer() = coinMessages();
2725 bool savePrefix = m.messageHandler()->prefix();
2726 m.messageHandler()->setPrefix(handler_->prefix());
2727 m.setSmallElementValue(CoinMax(smallElement_, m.getSmallElementValue()));
2728 double time1 = CoinCpuTime(), time2;
2729 int status = 0;
2730 try {
2731 status = m.readMps(fileName, "");
2732 } catch (CoinError e) {
2733 e.print();
2734 status = -1;
2735 }
2736 m.messageHandler()->setPrefix(savePrefix);
2737 if (!status || (ignoreErrors && (status > 0 && status < 100000))) {
2738 loadProblem(*m.getMatrixByCol(),
2739 m.getColLower(), m.getColUpper(),
2740 m.getObjCoefficients(),
2741 m.getRowLower(), m.getRowUpper());
2742 if (m.integerColumns()) {
2743 integerType_ = new char[numberColumns_];
2744 CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_);
2745 } else {
2746 integerType_ = NULL;
2747 }
2748#ifndef SLIM_CLP
2749 // get quadratic part
2750 if (m.reader()->whichSection ( ) == COIN_QUAD_SECTION ) {
2751 int * start = NULL;
2752 int * column = NULL;
2753 double * element = NULL;
2754 status = m.readQuadraticMps(NULL, start, column, element, 2);
2755 if (!status || ignoreErrors)
2756 loadQuadraticObjective(numberColumns_, start, column, element);
2757 delete [] start;
2758 delete [] column;
2759 delete [] element;
2760 }
2761#endif
2762#ifndef CLP_NO_STD
2763 // set problem name
2764 setStrParam(ClpProbName, m.getProblemName());
2765 // do names
2766 if (keepNames) {
2767 unsigned int maxLength = 0;
2768 int iRow;
2769 rowNames_ = std::vector<std::string> ();
2770 columnNames_ = std::vector<std::string> ();
2771 rowNames_.reserve(numberRows_);
2772 for (iRow = 0; iRow < numberRows_; iRow++) {
2773 const char * name = m.rowName(iRow);
2774 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2775 rowNames_.push_back(name);
2776 }
2777
2778 int iColumn;
2779 columnNames_.reserve(numberColumns_);
2780 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2781 const char * name = m.columnName(iColumn);
2782 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2783 columnNames_.push_back(name);
2784 }
2785 lengthNames_ = static_cast<int> (maxLength);
2786 } else {
2787 lengthNames_ = 0;
2788 }
2789#endif
2790 setDblParam(ClpObjOffset, m.objectiveOffset());
2791 time2 = CoinCpuTime();
2792 handler_->message(CLP_IMPORT_RESULT, messages_)
2793 << fileName
2794 << time2 - time1 << CoinMessageEol;
2795 } else {
2796 // errors
2797 handler_->message(CLP_IMPORT_ERRORS, messages_)
2798 << status << fileName << CoinMessageEol;
2799 }
2800
2801 return status;
2802}
2803// Read GMPL files from the given filenames
2804int
2805ClpModel::readGMPL(const char *fileName, const char * dataName,
2806 bool keepNames)
2807{
2808 FILE *fp = fopen(fileName, "r");
2809 if (fp) {
2810 // can open - lets go for it
2811 fclose(fp);
2812 if (dataName) {
2813 fp = fopen(dataName, "r");
2814 if (fp) {
2815 fclose(fp);
2816 } else {
2817 handler_->message(CLP_UNABLE_OPEN, messages_)
2818 << dataName << CoinMessageEol;
2819 return -1;
2820 }
2821 }
2822 } else {
2823 handler_->message(CLP_UNABLE_OPEN, messages_)
2824 << fileName << CoinMessageEol;
2825 return -1;
2826 }
2827 CoinMpsIO m;
2828 m.passInMessageHandler(handler_);
2829 *m.messagesPointer() = coinMessages();
2830 bool savePrefix = m.messageHandler()->prefix();
2831 m.messageHandler()->setPrefix(handler_->prefix());
2832 double time1 = CoinCpuTime(), time2;
2833 int status = m.readGMPL(fileName, dataName, keepNames);
2834 m.messageHandler()->setPrefix(savePrefix);
2835 if (!status) {
2836 loadProblem(*m.getMatrixByCol(),
2837 m.getColLower(), m.getColUpper(),
2838 m.getObjCoefficients(),
2839 m.getRowLower(), m.getRowUpper());
2840 if (m.integerColumns()) {
2841 integerType_ = new char[numberColumns_];
2842 CoinMemcpyN(m.integerColumns(), numberColumns_, integerType_);
2843 } else {
2844 integerType_ = NULL;
2845 }
2846#ifndef CLP_NO_STD
2847 // set problem name
2848 setStrParam(ClpProbName, m.getProblemName());
2849 // do names
2850 if (keepNames) {
2851 unsigned int maxLength = 0;
2852 int iRow;
2853 rowNames_ = std::vector<std::string> ();
2854 columnNames_ = std::vector<std::string> ();
2855 rowNames_.reserve(numberRows_);
2856 for (iRow = 0; iRow < numberRows_; iRow++) {
2857 const char * name = m.rowName(iRow);
2858 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2859 rowNames_.push_back(name);
2860 }
2861
2862 int iColumn;
2863 columnNames_.reserve(numberColumns_);
2864 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2865 const char * name = m.columnName(iColumn);
2866 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name)));
2867 columnNames_.push_back(name);
2868 }
2869 lengthNames_ = static_cast<int> (maxLength);
2870 } else {
2871 lengthNames_ = 0;
2872 }
2873#endif
2874 setDblParam(ClpObjOffset, m.objectiveOffset());
2875 time2 = CoinCpuTime();
2876 handler_->message(CLP_IMPORT_RESULT, messages_)
2877 << fileName
2878 << time2 - time1 << CoinMessageEol;
2879 } else {
2880 // errors
2881 handler_->message(CLP_IMPORT_ERRORS, messages_)
2882 << status << fileName << CoinMessageEol;
2883 }
2884 return status;
2885}
2886#endif
2887bool ClpModel::isPrimalObjectiveLimitReached() const
2888{
2889 double limit = 0.0;
2890 getDblParam(ClpPrimalObjectiveLimit, limit);
2891 if (limit > 1e30) {
2892 // was not ever set
2893 return false;
2894 }
2895
2896 const double obj = objectiveValue();
2897 const double maxmin = optimizationDirection();
2898
2899 if (problemStatus_ == 0) // optimal
2900 return maxmin > 0 ? (obj < limit) /*minim*/ : (-obj < limit) /*maxim*/;
2901 else if (problemStatus_ == 2)
2902 return true;
2903 else
2904 return false;
2905}
2906
2907bool ClpModel::isDualObjectiveLimitReached() const
2908{
2909
2910 double limit = 0.0;
2911 getDblParam(ClpDualObjectiveLimit, limit);
2912 if (limit > 1e30) {
2913 // was not ever set
2914 return false;
2915 }
2916
2917 const double obj = objectiveValue();
2918 const double maxmin = optimizationDirection();
2919
2920 if (problemStatus_ == 0) // optimal
2921 return maxmin > 0 ? (obj > limit) /*minim*/ : (-obj > limit) /*maxim*/;
2922 else if (problemStatus_ == 1)
2923 return true;
2924 else
2925 return false;
2926
2927}
2928void
2929ClpModel::copyInIntegerInformation(const char * information)
2930{
2931 delete [] integerType_;
2932 if (information) {
2933 integerType_ = new char[numberColumns_];
2934 CoinMemcpyN(information, numberColumns_, integerType_);
2935 } else {
2936 integerType_ = NULL;
2937 }
2938}
2939void
2940ClpModel::setContinuous(int index)
2941{
2942
2943 if (integerType_) {
2944#ifndef NDEBUG
2945 if (index < 0 || index >= numberColumns_) {
2946 indexError(index, "setContinuous");
2947 }
2948#endif
2949 integerType_[index] = 0;
2950 }
2951}
2952//-----------------------------------------------------------------------------
2953void
2954ClpModel::setInteger(int index)
2955{
2956 if (!integerType_) {
2957 integerType_ = new char[numberColumns_];
2958 CoinZeroN ( integerType_, numberColumns_);
2959 }
2960#ifndef NDEBUG
2961 if (index < 0 || index >= numberColumns_) {
2962 indexError(index, "setInteger");
2963 }
2964#endif
2965 integerType_[index] = 1;
2966}
2967/* Return true if the index-th variable is an integer variable */
2968bool
2969ClpModel::isInteger(int index) const
2970{
2971 if (!integerType_) {
2972 return false;
2973 } else {
2974#ifndef NDEBUG
2975 if (index < 0 || index >= numberColumns_) {
2976 indexError(index, "isInteger");
2977 }
2978#endif
2979 return (integerType_[index] != 0);
2980 }
2981}
2982#ifndef CLP_NO_STD
2983// Drops names - makes lengthnames 0 and names empty
2984void
2985ClpModel::dropNames()
2986{
2987 lengthNames_ = 0;
2988 rowNames_ = std::vector<std::string> ();
2989 columnNames_ = std::vector<std::string> ();
2990}
2991#endif
2992// Drop integer informations
2993void
2994ClpModel::deleteIntegerInformation()
2995{
2996 delete [] integerType_;
2997 integerType_ = NULL;
2998}
2999/* Return copy of status array (char[numberRows+numberColumns]),
3000 use delete [] */
3001unsigned char *
3002ClpModel::statusCopy() const
3003{
3004 return ClpCopyOfArray(status_, numberRows_ + numberColumns_);
3005}
3006// Copy in status vector
3007void
3008ClpModel::copyinStatus(const unsigned char * statusArray)
3009{
3010 delete [] status_;
3011 if (statusArray) {
3012 status_ = new unsigned char [numberRows_+numberColumns_];
3013 CoinMemcpyN(statusArray, (numberRows_ + numberColumns_), status_);
3014 } else {
3015 status_ = NULL;
3016 }
3017}
3018#ifndef SLIM_CLP
3019// Load up quadratic objective
3020void
3021ClpModel::loadQuadraticObjective(const int numberColumns, const CoinBigIndex * start,
3022 const int * column, const double * element)
3023{
3024 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3025 CoinAssert (numberColumns == numberColumns_);
3026 assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
3027 double offset;
3028 ClpObjective * obj = new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false),
3029 numberColumns,
3030 start, column, element);
3031 delete objective_;
3032 objective_ = obj;
3033
3034}
3035void
3036ClpModel::loadQuadraticObjective ( const CoinPackedMatrix& matrix)
3037{
3038 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3039 CoinAssert (matrix.getNumCols() == numberColumns_);
3040 assert ((dynamic_cast< ClpLinearObjective*>(objective_)));
3041 double offset;
3042 ClpQuadraticObjective * obj =
3043 new ClpQuadraticObjective(objective_->gradient(NULL, NULL, offset, false),
3044 numberColumns_,
3045 NULL, NULL, NULL);
3046 delete objective_;
3047 objective_ = obj;
3048 obj->loadQuadraticObjective(matrix);
3049}
3050// Get rid of quadratic objective
3051void
3052ClpModel::deleteQuadraticObjective()
3053{
3054 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3055 ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3056 if (obj)
3057 obj->deleteQuadraticObjective();
3058}
3059#endif
3060void
3061ClpModel::setObjective(ClpObjective * objective)
3062{
3063 whatsChanged_ = 0; // Use ClpSimplex stuff to keep
3064 delete objective_;
3065 objective_ = objective->clone();
3066}
3067// Returns resized array and updates size
3068double * whichDouble(double * array , int number, const int * which)
3069{
3070 double * newArray = NULL;
3071 if (array && number) {
3072 int i ;
3073 newArray = new double[number];
3074 for (i = 0; i < number; i++)
3075 newArray[i] = array[which[i]];
3076 }
3077 return newArray;
3078}
3079char * whichChar(char * array , int number, const int * which)
3080{
3081 char * newArray = NULL;
3082 if (array && number) {
3083 int i ;
3084 newArray = new char[number];
3085 for (i = 0; i < number; i++)
3086 newArray[i] = array[which[i]];
3087 }
3088 return newArray;
3089}
3090unsigned char * whichUnsignedChar(unsigned char * array ,
3091 int number, const int * which)
3092{
3093 unsigned char * newArray = NULL;
3094 if (array && number) {
3095 int i ;
3096 newArray = new unsigned char[number];
3097 for (i = 0; i < number; i++)
3098 newArray[i] = array[which[i]];
3099 }
3100 return newArray;
3101}
3102// Replace Clp Matrix (current is not deleted)
3103void
3104ClpModel::replaceMatrix( ClpMatrixBase * matrix, bool deleteCurrent)
3105{
3106 if (deleteCurrent)
3107 delete matrix_;
3108 matrix_ = matrix;
3109 whatsChanged_ = 0; // Too big a change
3110}
3111// Subproblem constructor
3112ClpModel::ClpModel ( const ClpModel * rhs,
3113 int numberRows, const int * whichRow,
3114 int numberColumns, const int * whichColumn,
3115 bool dropNames, bool dropIntegers)
3116 : specialOptions_(rhs->specialOptions_),
3117 maximumColumns_(-1),
3118 maximumRows_(-1),
3119 maximumInternalColumns_(-1),
3120 maximumInternalRows_(-1),
3121 savedRowScale_(NULL),
3122 savedColumnScale_(NULL)
3123{
3124 defaultHandler_ = rhs->defaultHandler_;
3125 if (defaultHandler_)
3126 handler_ = new CoinMessageHandler(*rhs->handler_);
3127 else
3128 handler_ = rhs->handler_;
3129 eventHandler_ = rhs->eventHandler_->clone();
3130 randomNumberGenerator_ = rhs->randomNumberGenerator_;
3131 messages_ = rhs->messages_;
3132 coinMessages_ = rhs->coinMessages_;
3133 maximumColumns_ = -1;
3134 maximumRows_ = -1;
3135 maximumInternalColumns_ = -1;
3136 maximumInternalRows_ = -1;
3137 savedRowScale_ = NULL;
3138 savedColumnScale_ = NULL;
3139 intParam_[ClpMaxNumIteration] = rhs->intParam_[ClpMaxNumIteration];
3140 intParam_[ClpMaxNumIterationHotStart] =
3141 rhs->intParam_[ClpMaxNumIterationHotStart];
3142 intParam_[ClpNameDiscipline] = rhs->intParam_[ClpNameDiscipline] ;
3143
3144 dblParam_[ClpDualObjectiveLimit] = rhs->dblParam_[ClpDualObjectiveLimit];
3145 dblParam_[ClpPrimalObjectiveLimit] = rhs->dblParam_[ClpPrimalObjectiveLimit];
3146 dblParam_[ClpDualTolerance] = rhs->dblParam_[ClpDualTolerance];
3147 dblParam_[ClpPrimalTolerance] = rhs->dblParam_[ClpPrimalTolerance];
3148 dblParam_[ClpObjOffset] = rhs->dblParam_[ClpObjOffset];
3149 dblParam_[ClpMaxSeconds] = rhs->dblParam_[ClpMaxSeconds];
3150 dblParam_[ClpPresolveTolerance] = rhs->dblParam_[ClpPresolveTolerance];
3151#ifndef CLP_NO_STD
3152 strParam_[ClpProbName] = rhs->strParam_[ClpProbName];
3153#endif
3154 specialOptions_ = rhs->specialOptions_;
3155 optimizationDirection_ = rhs->optimizationDirection_;
3156 objectiveValue_ = rhs->objectiveValue_;
3157 smallElement_ = rhs->smallElement_;
3158 objectiveScale_ = rhs->objectiveScale_;
3159 rhsScale_ = rhs->rhsScale_;
3160 numberIterations_ = rhs->numberIterations_;
3161 solveType_ = rhs->solveType_;
3162 whatsChanged_ = 0; // Too big a change
3163 problemStatus_ = rhs->problemStatus_;
3164 secondaryStatus_ = rhs->secondaryStatus_;
3165 // check valid lists
3166 int numberBad = 0;
3167 int i;
3168 for (i = 0; i < numberRows; i++)
3169 if (whichRow[i] < 0 || whichRow[i] >= rhs->numberRows_)
3170 numberBad++;
3171 CoinAssertHint(!numberBad, "Bad row list for subproblem constructor");
3172 numberBad = 0;
3173 for (i = 0; i < numberColumns; i++)
3174 if (whichColumn[i] < 0 || whichColumn[i] >= rhs->numberColumns_)
3175 numberBad++;
3176 CoinAssertHint(!numberBad, "Bad Column list for subproblem constructor");
3177 numberRows_ = numberRows;
3178 numberColumns_ = numberColumns;
3179 userPointer_ = rhs->userPointer_;
3180 trustedUserPointer_ = rhs->trustedUserPointer_;
3181 numberThreads_ = 0;
3182#ifndef CLP_NO_STD
3183 if (!dropNames) {
3184 unsigned int maxLength = 0;
3185 int iRow;
3186 rowNames_ = std::vector<std::string> ();
3187 columnNames_ = std::vector<std::string> ();
3188 rowNames_.reserve(numberRows_);
3189 for (iRow = 0; iRow < numberRows_; iRow++) {
3190 rowNames_.push_back(rhs->rowNames_[whichRow[iRow]]);
3191 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow].c_str())));
3192 }
3193 int iColumn;
3194 columnNames_.reserve(numberColumns_);
3195 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3196 columnNames_.push_back(rhs->columnNames_[whichColumn[iColumn]]);
3197 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn].c_str())));
3198 }
3199 lengthNames_ = static_cast<int> (maxLength);
3200 } else {
3201 lengthNames_ = 0;
3202 rowNames_ = std::vector<std::string> ();
3203 columnNames_ = std::vector<std::string> ();
3204 }
3205#endif
3206 if (rhs->integerType_ && !dropIntegers) {
3207 integerType_ = whichChar(rhs->integerType_, numberColumns, whichColumn);
3208 } else {
3209 integerType_ = NULL;
3210 }
3211 if (rhs->rowActivity_) {
3212 rowActivity_ = whichDouble(rhs->rowActivity_, numberRows, whichRow);
3213 dual_ = whichDouble(rhs->dual_, numberRows, whichRow);
3214 columnActivity_ = whichDouble(rhs->columnActivity_, numberColumns,
3215 whichColumn);
3216 reducedCost_ = whichDouble(rhs->reducedCost_, numberColumns,
3217 whichColumn);
3218 } else {
3219 rowActivity_ = NULL;
3220 columnActivity_ = NULL;
3221 dual_ = NULL;
3222 reducedCost_ = NULL;
3223 }
3224 rowLower_ = whichDouble(rhs->rowLower_, numberRows, whichRow);
3225 rowUpper_ = whichDouble(rhs->rowUpper_, numberRows, whichRow);
3226 columnLower_ = whichDouble(rhs->columnLower_, numberColumns, whichColumn);
3227 columnUpper_ = whichDouble(rhs->columnUpper_, numberColumns, whichColumn);
3228 if (rhs->objective_)
3229 objective_ = rhs->objective_->subsetClone(numberColumns, whichColumn);
3230 else
3231 objective_ = NULL;
3232 rowObjective_ = whichDouble(rhs->rowObjective_, numberRows, whichRow);
3233 // status has to be done in two stages
3234 if (rhs->status_) {
3235 status_ = new unsigned char[numberColumns_+numberRows_];
3236 unsigned char * rowStatus = whichUnsignedChar(rhs->status_ + rhs->numberColumns_,
3237 numberRows_, whichRow);
3238 unsigned char * columnStatus = whichUnsignedChar(rhs->status_,
3239 numberColumns_, whichColumn);
3240 CoinMemcpyN(rowStatus, numberRows_, status_ + numberColumns_);
3241 delete [] rowStatus;
3242 CoinMemcpyN(columnStatus, numberColumns_, status_);
3243 delete [] columnStatus;
3244 } else {
3245 status_=NULL;
3246 }
3247 ray_ = NULL;
3248 if (problemStatus_ == 1)
3249 ray_ = whichDouble (rhs->ray_, numberRows, whichRow);
3250 else if (problemStatus_ == 2)
3251 ray_ = whichDouble (rhs->ray_, numberColumns, whichColumn);
3252 rowScale_ = NULL;
3253 columnScale_ = NULL;
3254 inverseRowScale_ = NULL;
3255 inverseColumnScale_ = NULL;
3256 scalingFlag_ = rhs->scalingFlag_;
3257 rowCopy_ = NULL;
3258 scaledMatrix_ = NULL;
3259 matrix_ = NULL;
3260 if (rhs->matrix_) {
3261 matrix_ = rhs->matrix_->subsetClone(numberRows, whichRow,
3262 numberColumns, whichColumn);
3263 }
3264 randomNumberGenerator_.setSeed(1234567);
3265}
3266#ifndef CLP_NO_STD
3267// Copies in names
3268void
3269ClpModel::copyNames(std::vector<std::string> & rowNames,
3270 std::vector<std::string> & columnNames)
3271{
3272 unsigned int maxLength = 0;
3273 int iRow;
3274 rowNames_ = std::vector<std::string> ();
3275 columnNames_ = std::vector<std::string> ();
3276 rowNames_.reserve(numberRows_);
3277 for (iRow = 0; iRow < numberRows_; iRow++) {
3278 rowNames_.push_back(rowNames[iRow]);
3279 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow].c_str())));
3280 }
3281 int iColumn;
3282 columnNames_.reserve(numberColumns_);
3283 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
3284 columnNames_.push_back(columnNames[iColumn]);
3285 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn].c_str())));
3286 }
3287 lengthNames_ = static_cast<int> (maxLength);
3288}
3289// Return name or Rnnnnnnn
3290std::string
3291ClpModel::getRowName(int iRow) const
3292{
3293#ifndef NDEBUG
3294 if (iRow < 0 || iRow >= numberRows_) {
3295 indexError(iRow, "getRowName");
3296 }
3297#endif
3298 int size = static_cast<int>(rowNames_.size());
3299 if (size > iRow) {
3300 return rowNames_[iRow];
3301 } else {
3302 char name[9];
3303 sprintf(name, "R%7.7d", iRow);
3304 std::string rowName(name);
3305 return rowName;
3306 }
3307}
3308// Set row name
3309void
3310ClpModel::setRowName(int iRow, std::string &name)
3311{
3312#ifndef NDEBUG
3313 if (iRow < 0 || iRow >= numberRows_) {
3314 indexError(iRow, "setRowName");
3315 }
3316#endif
3317 unsigned int maxLength = lengthNames_;
3318 int size = static_cast<int>(rowNames_.size());
3319 if (size <= iRow)
3320 rowNames_.resize(iRow + 1);
3321 rowNames_[iRow] = name;
3322 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name.c_str())));
3323 // May be too big - but we would have to check both rows and columns to be exact
3324 lengthNames_ = static_cast<int> (maxLength);
3325}
3326// Return name or Cnnnnnnn
3327std::string
3328ClpModel::getColumnName(int iColumn) const
3329{
3330#ifndef NDEBUG
3331 if (iColumn < 0 || iColumn >= numberColumns_) {
3332 indexError(iColumn, "getColumnName");
3333 }
3334#endif
3335 int size = static_cast<int>(columnNames_.size());
3336 if (size > iColumn) {
3337 return columnNames_[iColumn];
3338 } else {
3339 char name[9];
3340 sprintf(name, "C%7.7d", iColumn);
3341 std::string columnName(name);
3342 return columnName;
3343 }
3344}
3345// Set column name
3346void
3347ClpModel::setColumnName(int iColumn, std::string &name)
3348{
3349#ifndef NDEBUG
3350 if (iColumn < 0 || iColumn >= numberColumns_) {
3351 indexError(iColumn, "setColumnName");
3352 }
3353#endif
3354 unsigned int maxLength = lengthNames_;
3355 int size = static_cast<int>(columnNames_.size());
3356 if (size <= iColumn)
3357 columnNames_.resize(iColumn + 1);
3358 columnNames_[iColumn] = name;
3359 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(name.c_str())));
3360 // May be too big - but we would have to check both columns and columns to be exact
3361 lengthNames_ = static_cast<int> (maxLength);
3362}
3363// Copies in Row names - modifies names first .. last-1
3364void
3365ClpModel::copyRowNames(const std::vector<std::string> & rowNames, int first, int last)
3366{
3367 unsigned int maxLength = lengthNames_;
3368 int size = static_cast<int>(rowNames_.size());
3369 if (size != numberRows_)
3370 rowNames_.resize(numberRows_);
3371 int iRow;
3372 for (iRow = first; iRow < last; iRow++) {
3373 rowNames_[iRow] = rowNames[iRow-first];
3374 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames_[iRow-first].c_str())));
3375 }
3376 // May be too big - but we would have to check both rows and columns to be exact
3377 lengthNames_ = static_cast<int> (maxLength);
3378}
3379// Copies in Column names - modifies names first .. last-1
3380void
3381ClpModel::copyColumnNames(const std::vector<std::string> & columnNames, int first, int last)
3382{
3383 unsigned int maxLength = lengthNames_;
3384 int size = static_cast<int>(columnNames_.size());
3385 if (size != numberColumns_)
3386 columnNames_.resize(numberColumns_);
3387 int iColumn;
3388 for (iColumn = first; iColumn < last; iColumn++) {
3389 columnNames_[iColumn] = columnNames[iColumn-first];
3390 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames_[iColumn-first].c_str())));
3391 }
3392 // May be too big - but we would have to check both rows and columns to be exact
3393 lengthNames_ = static_cast<int> (maxLength);
3394}
3395// Copies in Row names - modifies names first .. last-1
3396void
3397ClpModel::copyRowNames(const char * const * rowNames, int first, int last)
3398{
3399 unsigned int maxLength = lengthNames_;
3400 int size = static_cast<int>(rowNames_.size());
3401 if (size != numberRows_)
3402 rowNames_.resize(numberRows_);
3403 int iRow;
3404 for (iRow = first; iRow < last; iRow++) {
3405 if (rowNames[iRow-first] && strlen(rowNames[iRow-first])) {
3406 rowNames_[iRow] = rowNames[iRow-first];
3407 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(rowNames[iRow-first])));
3408 } else {
3409 maxLength = CoinMax(maxLength, static_cast<unsigned int> (8));
3410 char name[9];
3411 sprintf(name, "R%7.7d", iRow);
3412 rowNames_[iRow] = name;
3413 }
3414 }
3415 // May be too big - but we would have to check both rows and columns to be exact
3416 lengthNames_ = static_cast<int> (maxLength);
3417}
3418// Copies in Column names - modifies names first .. last-1
3419void
3420ClpModel::copyColumnNames(const char * const * columnNames, int first, int last)
3421{
3422 unsigned int maxLength = lengthNames_;
3423 int size = static_cast<int>(columnNames_.size());
3424 if (size != numberColumns_)
3425 columnNames_.resize(numberColumns_);
3426 int iColumn;
3427 for (iColumn = first; iColumn < last; iColumn++) {
3428 if (columnNames[iColumn-first] && strlen(columnNames[iColumn-first])) {
3429 columnNames_[iColumn] = columnNames[iColumn-first];
3430 maxLength = CoinMax(maxLength, static_cast<unsigned int> (strlen(columnNames[iColumn-first])));
3431 } else {
3432 maxLength = CoinMax(maxLength, static_cast<unsigned int> (8));
3433 char name[9];
3434 sprintf(name, "C%7.7d", iColumn);
3435 columnNames_[iColumn] = name;
3436 }
3437 }
3438 // May be too big - but we would have to check both rows and columns to be exact
3439 lengthNames_ = static_cast<int> (maxLength);
3440}
3441#endif
3442// Primal objective limit
3443void
3444ClpModel::setPrimalObjectiveLimit(double value)
3445{
3446 dblParam_[ClpPrimalObjectiveLimit] = value;
3447}
3448// Dual objective limit
3449void
3450ClpModel::setDualObjectiveLimit(double value)
3451{
3452 dblParam_[ClpDualObjectiveLimit] = value;
3453}
3454// Objective offset
3455void
3456ClpModel::setObjectiveOffset(double value)
3457{
3458 dblParam_[ClpObjOffset] = value;
3459}
3460// Solve a problem with no elements - return status
3461int ClpModel::emptyProblem(int * infeasNumber, double * infeasSum, bool printMessage)
3462{
3463 secondaryStatus_ = 6; // so user can see something odd
3464 if (printMessage)
3465 handler_->message(CLP_EMPTY_PROBLEM, messages_)
3466 << numberRows_
3467 << numberColumns_
3468 << 0
3469 << CoinMessageEol;
3470 int returnCode = 0;
3471 if (numberRows_ || numberColumns_) {
3472 if (!status_) {
3473 status_ = new unsigned char[numberRows_+numberColumns_];
3474 CoinZeroN(status_, numberRows_ + numberColumns_);
3475 }
3476 }
3477 // status is set directly (as can be used by Interior methods)
3478 // check feasible
3479 int numberPrimalInfeasibilities = 0;
3480 double sumPrimalInfeasibilities = 0.0;
3481 int numberDualInfeasibilities = 0;
3482 double sumDualInfeasibilities = 0.0;
3483 if (numberRows_) {
3484 for (int i = 0; i < numberRows_; i++) {
3485 dual_[i] = 0.0;
3486 if (rowLower_[i] <= rowUpper_[i]) {
3487 if (rowLower_[i] > -1.0e30 || rowUpper_[i] < 1.0e30) {
3488 if (rowLower_[i] <= 0.0 && rowUpper_[i] >= 0.0) {
3489 if (fabs(rowLower_[i]) < fabs(rowUpper_[i]))
3490 rowActivity_[i] = rowLower_[i];
3491 else
3492 rowActivity_[i] = rowUpper_[i];
3493 } else {
3494 rowActivity_[i] = 0.0;
3495 numberPrimalInfeasibilities++;
3496 sumPrimalInfeasibilities += CoinMin(rowLower_[i], -rowUpper_[i]);
3497 returnCode = 1;
3498 }
3499 } else {
3500 rowActivity_[i] = 0.0;
3501 }
3502 } else {
3503 rowActivity_[i] = 0.0;
3504 numberPrimalInfeasibilities++;
3505 sumPrimalInfeasibilities += rowLower_[i] - rowUpper_[i];
3506 returnCode = 1;
3507 }
3508 status_[i+numberColumns_] = 1;
3509 }
3510 }
3511 objectiveValue_ = 0.0;
3512 if (numberColumns_) {
3513 const double * cost = objective();
3514 for (int i = 0; i < numberColumns_; i++) {
3515 reducedCost_[i] = cost[i];
3516 double objValue = cost[i] * optimizationDirection_;
3517 if (columnLower_[i] <= columnUpper_[i]) {
3518 if (columnLower_[i] > -1.0e30 || columnUpper_[i] < 1.0e30) {
3519 if (!objValue) {
3520 if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
3521 columnActivity_[i] = columnLower_[i];
3522 status_[i] = 3;
3523 } else {
3524 columnActivity_[i] = columnUpper_[i];
3525 status_[i] = 2;
3526 }
3527 } else if (objValue > 0.0) {
3528 if (columnLower_[i] > -1.0e30) {
3529 columnActivity_[i] = columnLower_[i];
3530 status_[i] = 3;
3531 } else {
3532 columnActivity_[i] = columnUpper_[i];
3533 status_[i] = 2;
3534 numberDualInfeasibilities++;
3535 sumDualInfeasibilities += fabs(objValue);
3536 returnCode |= 2;
3537 }
3538 objectiveValue_ += columnActivity_[i] * objValue;
3539 } else {
3540 if (columnUpper_[i] < 1.0e30) {
3541 columnActivity_[i] = columnUpper_[i];
3542 status_[i] = 2;
3543 } else {
3544 columnActivity_[i] = columnLower_[i];
3545 status_[i] = 3;
3546 numberDualInfeasibilities++;
3547 sumDualInfeasibilities += fabs(objValue);
3548 returnCode |= 2;
3549 }
3550 objectiveValue_ += columnActivity_[i] * objValue;
3551 }
3552 } else {
3553 columnActivity_[i] = 0.0;
3554 if (objValue) {
3555 numberDualInfeasibilities++;
3556 sumDualInfeasibilities += fabs(objValue);
3557 returnCode |= 2;
3558 }
3559 status_[i] = 0;
3560 }
3561 } else {
3562 if (fabs(columnLower_[i]) < fabs(columnUpper_[i])) {
3563 columnActivity_[i] = columnLower_[i];
3564 status_[i] = 3;
3565 } else {
3566 columnActivity_[i] = columnUpper_[i];
3567 status_[i] = 2;
3568 }
3569 numberPrimalInfeasibilities++;
3570 sumPrimalInfeasibilities += columnLower_[i] - columnUpper_[i];
3571 returnCode |= 1;
3572 }
3573 }
3574 }
3575 objectiveValue_ /= (objectiveScale_ * rhsScale_);
3576 if (infeasNumber) {
3577 infeasNumber[0] = numberDualInfeasibilities;
3578 infeasSum[0] = sumDualInfeasibilities;
3579 infeasNumber[1] = numberPrimalInfeasibilities;
3580 infeasSum[1] = sumPrimalInfeasibilities;
3581 }
3582 if (returnCode == 3)
3583 returnCode = 4;
3584 return returnCode;
3585}
3586#ifndef SLIM_NOIO
3587/* Write the problem in MPS format to the specified file.
3588
3589Row and column names may be null.
3590formatType is
3591<ul>
3592<li> 0 - normal
3593<li> 1 - extra accuracy
3594<li> 2 - IEEE hex (later)
3595</ul>
3596
3597Returns non-zero on I/O error
3598*/
3599int
3600ClpModel::writeMps(const char *filename,
3601 int formatType, int numberAcross,
3602 double objSense) const
3603{
3604 matrix_->setDimensions(numberRows_, numberColumns_);
3605
3606 // Get multiplier for objective function - default 1.0
3607 double * objective = new double[numberColumns_];
3608 CoinMemcpyN(getObjCoefficients(), numberColumns_, objective);
3609 if (objSense * getObjSense() < 0.0) {
3610 for (int i = 0; i < numberColumns_; ++i)
3611 objective [i] = - objective[i];
3612 }
3613 // get names
3614 const char * const * const rowNames = rowNamesAsChar();
3615 const char * const * const columnNames = columnNamesAsChar();
3616 CoinMpsIO writer;
3617 writer.passInMessageHandler(handler_);
3618 *writer.messagesPointer() = coinMessages();
3619 writer.setMpsData(*(matrix_->getPackedMatrix()), COIN_DBL_MAX,
3620 getColLower(), getColUpper(),
3621 objective,
3622 reinterpret_cast<const char*> (NULL) /*integrality*/,
3623 getRowLower(), getRowUpper(),
3624 columnNames, rowNames);
3625 // Pass in array saying if each variable integer
3626 writer.copyInIntegerInformation(integerInformation());
3627 writer.setObjectiveOffset(objectiveOffset());
3628 delete [] objective;
3629 CoinPackedMatrix * quadratic = NULL;
3630#ifndef SLIM_CLP
3631 // allow for quadratic objective
3632#ifndef NO_RTTI
3633 ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3634#else
3635 ClpQuadraticObjective * quadraticObj = NULL;
3636 if (objective_->type() == 2)
3637 quadraticObj = (static_cast< ClpQuadraticObjective*>(objective_));
3638#endif
3639 if (quadraticObj)
3640 quadratic = quadraticObj->quadraticObjective();
3641#endif
3642 int returnCode = writer.writeMps(filename, 0 /* do not gzip it*/, formatType, numberAcross,
3643 quadratic);
3644 if (rowNames) {
3645 deleteNamesAsChar(rowNames, numberRows_ + 1);
3646 deleteNamesAsChar(columnNames, numberColumns_);
3647 }
3648 return returnCode;
3649}
3650#ifndef CLP_NO_STD
3651// Create row names as char **
3652const char * const *
3653ClpModel::rowNamesAsChar() const
3654{
3655 char ** rowNames = NULL;
3656 if (lengthNames()) {
3657 rowNames = new char * [numberRows_+1];
3658 int numberNames = static_cast<int>(rowNames_.size());
3659 numberNames = CoinMin(numberRows_, numberNames);
3660 int iRow;
3661 for (iRow = 0; iRow < numberNames; iRow++) {
3662 if (rowName(iRow) != "") {
3663 rowNames[iRow] =
3664 CoinStrdup(rowName(iRow).c_str());
3665 } else {
3666 char name[9];
3667 sprintf(name, "R%7.7d", iRow);
3668 rowNames[iRow] = CoinStrdup(name);
3669 }
3670#ifdef STRIPBLANKS
3671 char * xx = rowNames[iRow];
3672 int i;
3673 int length = strlen(xx);
3674 int n = 0;
3675 for (i = 0; i < length; i++) {
3676 if (xx[i] != ' ')
3677 xx[n++] = xx[i];
3678 }
3679 xx[n] = '\0';
3680#endif
3681 }
3682 char name[9];
3683 for ( ; iRow < numberRows_; iRow++) {
3684 sprintf(name, "R%7.7d", iRow);
3685 rowNames[iRow] = CoinStrdup(name);
3686 }
3687 rowNames[numberRows_] = CoinStrdup("OBJROW");
3688 }
3689 return reinterpret_cast<const char * const *>(rowNames);
3690}
3691// Create column names as char **
3692const char * const *
3693ClpModel::columnNamesAsChar() const
3694{
3695 char ** columnNames = NULL;
3696 if (lengthNames()) {
3697 columnNames = new char * [numberColumns_];
3698 int numberNames = static_cast<int>(columnNames_.size());
3699 numberNames = CoinMin(numberColumns_, numberNames);
3700 int iColumn;
3701 for (iColumn = 0; iColumn < numberNames; iColumn++) {
3702 if (columnName(iColumn) != "") {
3703 columnNames[iColumn] =
3704 CoinStrdup(columnName(iColumn).c_str());
3705 } else {
3706 char name[9];
3707 sprintf(name, "C%7.7d", iColumn);
3708 columnNames[iColumn] = CoinStrdup(name);
3709 }
3710#ifdef STRIPBLANKS
3711 char * xx = columnNames[iColumn];
3712 int i;
3713 int length = strlen(xx);
3714 int n = 0;
3715 for (i = 0; i < length; i++) {
3716 if (xx[i] != ' ')
3717 xx[n++] = xx[i];
3718 }
3719 xx[n] = '\0';
3720#endif
3721 }
3722 char name[9];
3723 for ( ; iColumn < numberColumns_; iColumn++) {
3724 sprintf(name, "C%7.7d", iColumn);
3725 columnNames[iColumn] = CoinStrdup(name);
3726 }
3727 }
3728 return /*reinterpret_cast<const char * const *>*/(columnNames);
3729}
3730// Delete char * version of names
3731void
3732ClpModel::deleteNamesAsChar(const char * const * names, int number) const
3733{
3734 for (int i = 0; i < number; i++) {
3735 free(const_cast<char *>(names[i]));
3736 }
3737 delete [] const_cast<char **>(names);
3738}
3739#endif
3740#endif
3741// Pass in Event handler (cloned and deleted at end)
3742void
3743ClpModel::passInEventHandler(const ClpEventHandler * eventHandler)
3744{
3745 delete eventHandler_;
3746 eventHandler_ = eventHandler->clone();
3747}
3748// Sets or unsets scaling, 0 -off, 1 on, 2 dynamic(later)
3749void
3750ClpModel::scaling(int mode)
3751{
3752 // If mode changes then we treat as new matrix (need new row copy)
3753 if (mode != scalingFlag_) {
3754 whatsChanged_ &= ~(2 + 4 + 8);
3755 // Get rid of scaled matrix
3756 setClpScaledMatrix(NULL);
3757 }
3758 if (mode > 0 && mode < 6) {
3759 scalingFlag_ = mode;
3760 } else if (!mode) {
3761 scalingFlag_ = 0;
3762 setRowScale(NULL);
3763 setColumnScale(NULL);
3764 }
3765}
3766void
3767ClpModel::times(double scalar,
3768 const double * x, double * y) const
3769{
3770 if (!scaledMatrix_ || !rowScale_) {
3771 if (rowScale_)
3772 matrix_->times(scalar, x, y, rowScale_, columnScale_);
3773 else
3774 matrix_->times(scalar, x, y);
3775 } else {
3776 scaledMatrix_->times(scalar, x, y);
3777 }
3778}
3779void
3780ClpModel::transposeTimes(double scalar,
3781 const double * x, double * y) const
3782{
3783 if (!scaledMatrix_ || !rowScale_) {
3784 if (rowScale_)
3785 matrix_->transposeTimes(scalar, x, y, rowScale_, columnScale_, NULL);
3786 else
3787 matrix_->transposeTimes(scalar, x, y);
3788 } else {
3789 scaledMatrix_->transposeTimes(scalar, x, y);
3790 }
3791}
3792// Does much of scaling
3793void
3794ClpModel::gutsOfScaling()
3795{
3796 int i;
3797 if (rowObjective_) {
3798 for (i = 0; i < numberRows_; i++)
3799 rowObjective_[i] /= rowScale_[i];
3800 }
3801 for (i = 0; i < numberRows_; i++) {
3802 double multiplier = rowScale_[i];
3803 double inverseMultiplier = 1.0 / multiplier;
3804 rowActivity_[i] *= multiplier;
3805 dual_[i] *= inverseMultiplier;
3806 if (rowLower_[i] > -1.0e30)
3807 rowLower_[i] *= multiplier;
3808 else
3809 rowLower_[i] = -COIN_DBL_MAX;
3810 if (rowUpper_[i] < 1.0e30)
3811 rowUpper_[i] *= multiplier;
3812 else
3813 rowUpper_[i] = COIN_DBL_MAX;
3814 }
3815 for (i = 0; i < numberColumns_; i++) {
3816 double multiplier = 1.0 * inverseColumnScale_[i];
3817 columnActivity_[i] *= multiplier;
3818 reducedCost_[i] *= columnScale_[i];
3819 if (columnLower_[i] > -1.0e30)
3820 columnLower_[i] *= multiplier;
3821 else
3822 columnLower_[i] = -COIN_DBL_MAX;
3823 if (columnUpper_[i] < 1.0e30)
3824 columnUpper_[i] *= multiplier;
3825 else
3826 columnUpper_[i] = COIN_DBL_MAX;
3827
3828 }
3829 //now replace matrix
3830 //and objective
3831 matrix_->reallyScale(rowScale_, columnScale_);
3832 objective_->reallyScale(columnScale_);
3833}
3834/* If we constructed a "really" scaled model then this reverses the operation.
3835 Quantities may not be exactly as they were before due to rounding errors */
3836void
3837ClpModel::unscale()
3838{
3839 if (rowScale_) {
3840 int i;
3841 // reverse scaling
3842 for (i = 0; i < numberRows_; i++)
3843 rowScale_[i] = 1.0 * inverseRowScale_[i];
3844 for (i = 0; i < numberColumns_; i++)
3845 columnScale_[i] = 1.0 * inverseColumnScale_[i];
3846 gutsOfScaling();
3847 }
3848
3849 scalingFlag_ = 0;
3850 setRowScale(NULL);
3851 setColumnScale(NULL);
3852}
3853void
3854ClpModel::setSpecialOptions(unsigned int value)
3855{
3856 specialOptions_ = value;
3857}
3858/* This creates a coinModel object
3859 */
3860CoinModel *
3861ClpModel::createCoinModel() const
3862{
3863 CoinModel * coinModel = new CoinModel();
3864 CoinPackedMatrix matrixByRow;
3865 matrixByRow.setExtraGap(0.0);
3866 matrixByRow.setExtraMajor(0.0);
3867 matrixByRow.reverseOrderedCopyOf(*matrix());
3868 coinModel->setObjectiveOffset(objectiveOffset());
3869 coinModel->setProblemName(problemName().c_str());
3870
3871 // Build by row from scratch
3872 const double * element = matrixByRow.getElements();
3873 const int * column = matrixByRow.getIndices();
3874 const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
3875 const int * rowLength = matrixByRow.getVectorLengths();
3876 int i;
3877 for (i = 0; i < numberRows_; i++) {
3878 coinModel->addRow(rowLength[i], column + rowStart[i],
3879 element + rowStart[i], rowLower_[i], rowUpper_[i]);
3880 }
3881 // Now do column part
3882 const double * objective = this->objective();
3883 for (i = 0; i < numberColumns_; i++) {
3884 coinModel->setColumnBounds(i, columnLower_[i], columnUpper_[i]);
3885 coinModel->setColumnObjective(i, objective[i]);
3886 }
3887 for ( i = 0; i < numberColumns_; i++) {
3888 if (isInteger(i))
3889 coinModel->setColumnIsInteger(i, true);
3890 }
3891 // do names
3892 for (i = 0; i < numberRows_; i++) {
3893 char temp[30];
3894 strcpy(temp, rowName(i).c_str());
3895 size_t length = strlen(temp);
3896 for (size_t j = 0; j < length; j++) {
3897 if (temp[j] == '-')
3898 temp[j] = '_';
3899 }
3900 coinModel->setRowName(i, temp);
3901 }
3902 for (i = 0; i < numberColumns_; i++) {
3903 char temp[30];
3904 strcpy(temp, columnName(i).c_str());
3905 size_t length = strlen(temp);
3906 for (size_t j = 0; j < length; j++) {
3907 if (temp[j] == '-')
3908 temp[j] = '_';
3909 }
3910 coinModel->setColumnName(i, temp);
3911 }
3912 ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
3913 if (obj) {
3914 const CoinPackedMatrix * quadObj = obj->quadraticObjective();
3915 // add in quadratic
3916 const double * element = quadObj->getElements();
3917 const int * row = quadObj->getIndices();
3918 const CoinBigIndex * columnStart = quadObj->getVectorStarts();
3919 const int * columnLength = quadObj->getVectorLengths();
3920 for (i = 0; i < numberColumns_; i++) {
3921 int nels = columnLength[i];
3922 if (nels) {
3923 CoinBigIndex start = columnStart[i];
3924 double constant = coinModel->getColumnObjective(i);
3925 char temp[100000];
3926 char temp2[30];
3927 sprintf(temp, "%g", constant);
3928 for (CoinBigIndex k = start; k < start + nels; k++) {
3929 int kColumn = row[k];
3930 double value = element[k];
3931#if 1
3932 // ampl gives twice with assumed 0.5
3933 if (kColumn < i)
3934 continue;
3935 else if (kColumn == i)
3936 value *= 0.5;
3937#endif
3938 if (value == 1.0)
3939 sprintf(temp2, "+%s", coinModel->getColumnName(kColumn));
3940 else if (value == -1.0)
3941 sprintf(temp2, "-%s", coinModel->getColumnName(kColumn));
3942 else if (value > 0.0)
3943 sprintf(temp2, "+%g*%s", value, coinModel->getColumnName(kColumn));
3944 else
3945 sprintf(temp2, "%g*%s", value, coinModel->getColumnName(kColumn));
3946 strcat(temp, temp2);
3947 assert (strlen(temp) < 100000);
3948 }
3949 coinModel->setObjective(i, temp);
3950 if (logLevel() > 2)
3951 printf("el for objective column %s is %s\n", coinModel->getColumnName(i), temp);
3952 }
3953 }
3954 }
3955 return coinModel;
3956}
3957// Start or reset using maximumRows_ and Columns_
3958void
3959ClpModel::startPermanentArrays()
3960{
3961 COIN_DETAIL_PRINT(printf("startperm a %d rows, %d maximum rows\n",
3962 numberRows_, maximumRows_));
3963 if ((specialOptions_ & 65536) != 0) {
3964 if (numberRows_ > maximumRows_ || numberColumns_ > maximumColumns_) {
3965 if (numberRows_ > maximumRows_) {
3966 if (maximumRows_ > 0)
3967 maximumRows_ = numberRows_ + 10 + numberRows_ / 100;
3968 else
3969 maximumRows_ = numberRows_;
3970 }
3971 if (numberColumns_ > maximumColumns_) {
3972 if (maximumColumns_ > 0)
3973 maximumColumns_ = numberColumns_ + 10 + numberColumns_ / 100;
3974 else
3975 maximumColumns_ = numberColumns_;
3976 }
3977 // need to make sure numberRows_ OK and size of matrices
3978 resize(maximumRows_, maximumColumns_);
3979 COIN_DETAIL_PRINT(printf("startperm b %d rows, %d maximum rows\n",
3980 numberRows_, maximumRows_));
3981 } else {
3982 return;
3983 }
3984 } else {
3985 specialOptions_ |= 65536;
3986 maximumRows_ = numberRows_;
3987 maximumColumns_ = numberColumns_;
3988 baseMatrix_ = *matrix();
3989 baseMatrix_.cleanMatrix();
3990 baseRowCopy_.setExtraGap(0.0);
3991 baseRowCopy_.setExtraMajor(0.0);
3992 baseRowCopy_.reverseOrderedCopyOf(baseMatrix_);
3993 COIN_DETAIL_PRINT(printf("startperm c %d rows, %d maximum rows\n",
3994 numberRows_, maximumRows_));
3995 }
3996}
3997// Stop using maximumRows_ and Columns_
3998void
3999ClpModel::stopPermanentArrays()
4000{
4001 specialOptions_ &= ~65536;
4002 maximumRows_ = -1;
4003 maximumColumns_ = -1;
4004 if (rowScale_ != savedRowScale_) {
4005 delete [] savedRowScale_;
4006 delete [] savedColumnScale_;
4007 }
4008 savedRowScale_ = NULL;
4009 savedColumnScale_ = NULL;
4010}
4011// Set new row matrix
4012void
4013ClpModel::setNewRowCopy(ClpMatrixBase * newCopy)
4014{
4015 delete rowCopy_;
4016 rowCopy_ = newCopy;
4017}
4018/* Find a network subset.
4019 rotate array should be numberRows. On output
4020 -1 not in network
4021 0 in network as is
4022 1 in network with signs swapped
4023 Returns number of network rows (positive if exact network, negative if needs extra row)
4024 From Gulpinar, Gutin, Maros and Mitra
4025*/
4026int
4027ClpModel::findNetwork(char * rotate, double fractionNeeded)
4028{
4029 int * mapping = new int [numberRows_];
4030 // Get column copy
4031 CoinPackedMatrix * columnCopy = matrix();
4032 // Get a row copy in standard format
4033 CoinPackedMatrix * copy = new CoinPackedMatrix();
4034 copy->setExtraGap(0.0);
4035 copy->setExtraMajor(0.0);
4036 copy->reverseOrderedCopyOf(*columnCopy);
4037 // make sure ordered and no gaps
4038 copy->cleanMatrix();
4039 // get matrix data pointers
4040 const int * columnIn = copy->getIndices();
4041 const CoinBigIndex * rowStartIn = copy->getVectorStarts();
4042 const int * rowLength = copy->getVectorLengths();
4043 const double * elementByRowIn = copy->getElements();
4044 int iRow, iColumn;
4045 int numberEligible = 0;
4046 int numberIn = 0;
4047 int numberElements = 0;
4048 for (iRow = 0; iRow < numberRows_; iRow++) {
4049 bool possible = true;
4050 mapping[iRow] = -1;
4051 rotate[iRow] = -1;
4052 for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) {
4053 //int iColumn = column[j];
4054 double value = elementByRowIn[j];
4055 if (fabs(value) != 1.0) {
4056 possible = false;
4057 break;
4058 }
4059 }
4060 if (rowLength[iRow] && possible) {
4061 mapping[iRow] = numberEligible;
4062 numberEligible++;
4063 numberElements += rowLength[iRow];
4064 }
4065 }
4066 if (numberEligible < fractionNeeded * numberRows_) {
4067 delete [] mapping;
4068 delete copy;
4069 return 0;
4070 }
4071 // create arrays
4072 int * eligible = new int [numberRows_];
4073 int * column = new int [numberElements];
4074 CoinBigIndex * rowStart = new CoinBigIndex [numberEligible+1];
4075 char * elementByRow = new char [numberElements];
4076 numberEligible = 0;
4077 numberElements = 0;
4078 rowStart[0] = 0;
4079 for (iRow = 0; iRow < numberRows_; iRow++) {
4080 if (mapping[iRow] < 0)
4081 continue;
4082 assert (numberEligible == mapping[iRow]);
4083 rotate[numberEligible] = 0;
4084 for (CoinBigIndex j = rowStartIn[iRow]; j < rowStartIn[iRow] + rowLength[iRow]; j++) {
4085 column[numberElements] = columnIn[j];
4086 double value = elementByRowIn[j];
4087 if (value == 1.0)
4088 elementByRow[numberElements++] = 1;
4089 else
4090 elementByRow[numberElements++] = -1;
4091 }
4092 numberEligible++;
4093 rowStart[numberEligible] = numberElements;
4094 }
4095 // get rid of copy to save space
4096 delete copy;
4097 const int * rowIn = columnCopy->getIndices();
4098 const CoinBigIndex * columnStartIn = columnCopy->getVectorStarts();
4099 const int * columnLengthIn = columnCopy->getVectorLengths();
4100 const double * elementByColumnIn = columnCopy->getElements();
4101 int * columnLength = new int [numberColumns_];
4102 // May just be that is a network - worth checking
4103 bool isNetworkAlready = true;
4104 bool trueNetwork = true;
4105 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4106 double product = 1.0;
4107 int n = 0;
4108 for (CoinBigIndex j = columnStartIn[iColumn]; j < columnStartIn[iColumn] + columnLengthIn[iColumn]; j++) {
4109 iRow = mapping[rowIn[j]];
4110 if (iRow >= 0) {
4111 n++;
4112 product *= elementByColumnIn[j];
4113 }
4114 }
4115 if (n >= 2) {
4116 if (product != -1.0 || n > 2)
4117 isNetworkAlready = false;
4118 } else if (n == 1) {
4119 trueNetwork = false;
4120 }
4121 columnLength[iColumn] = n;
4122 }
4123 if (!isNetworkAlready) {
4124 // For sorting
4125 double * count = new double [numberRows_];
4126 int * which = new int [numberRows_];
4127 int numberLast = -1;
4128 // Count for columns
4129 char * columnCount = new char[numberColumns_];
4130 memset(columnCount, 0, numberColumns_);
4131 char * currentColumnCount = new char[numberColumns_];
4132 // Now do main loop
4133 while (numberIn > numberLast) {
4134 numberLast = numberIn;
4135 int numberLeft = 0;
4136 for (iRow = 0; iRow < numberEligible; iRow++) {
4137 if (rotate[iRow] == 0 && rowStart[iRow+1] > rowStart[iRow]) {
4138 which[numberLeft] = iRow;
4139 int merit = 0;
4140 bool OK = true;
4141 bool reflectionOK = true;
4142 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow+1]; j++) {
4143 iColumn = column[j];
4144 int iCount = columnCount[iColumn];
4145 int absCount = CoinAbs(iCount);
4146 if (absCount < 2) {
4147 merit = CoinMax(columnLength[iColumn] - absCount - 1, merit);
4148 if (elementByRow[j] == iCount)
4149 OK = false;
4150 else if (elementByRow[j] == -iCount)
4151 reflectionOK = false;
4152 } else {
4153 merit = -2;
4154 break;
4155 }
4156 }
4157 if (merit > -2 && (OK || reflectionOK) &&
4158 (!OK || !reflectionOK || !numberIn)) {
4159 //if (!numberLast) merit=1;
4160 count[numberLeft++] = (rowStart[iRow+1] - rowStart[iRow] - 1) *
4161 (static_cast<double>(merit));
4162 if (OK)
4163 rotate[iRow] = 0;
4164 else
4165 rotate[iRow] = 1;
4166 } else {
4167 // no good
4168 rotate[iRow] = -1;
4169 }
4170 }
4171 }
4172 CoinSort_2(count, count + numberLeft, which);
4173 // Get G
4174 memset(currentColumnCount, 0, numberColumns_);
4175 for (iRow = 0; iRow < numberLeft; iRow++) {
4176 int jRow = which[iRow];
4177 bool possible = true;
4178 for (int i = 0; i < numberIn; i++) {
4179 for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) {
4180 if (currentColumnCount[column[j]]) {
4181 possible = false;
4182 break;
4183 }
4184 }
4185 }
4186 if (possible) {
4187 rotate[jRow] = static_cast<char>(rotate[jRow] + 2);
4188 eligible[numberIn++] = jRow;
4189 char multiplier = static_cast<char>((rotate[jRow] == 2) ? 1 : -1);
4190 for (CoinBigIndex j = rowStart[jRow]; j < rowStart[jRow+1]; j++) {
4191 iColumn = column[j];
4192 currentColumnCount[iColumn]++;
4193 int iCount = columnCount[iColumn];
4194 int absCount = CoinAbs(iCount);
4195 if (!absCount) {
4196 columnCount[iColumn] = static_cast<char>(elementByRow[j] * multiplier);
4197 } else {
4198 columnCount[iColumn] = 2;
4199 }
4200 }
4201 }
4202 }
4203 }
4204#ifndef NDEBUG
4205 for (iRow = 0; iRow < numberIn; iRow++) {
4206 int kRow = eligible[iRow];
4207 assert (rotate[kRow] >= 2);
4208 }
4209#endif
4210 trueNetwork = true;
4211 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
4212 if (CoinAbs(static_cast<int>(columnCount[iColumn])) == 1) {
4213 trueNetwork = false;
4214 break;
4215 }
4216 }
4217 delete [] currentColumnCount;
4218 delete [] columnCount;
4219 delete [] which;
4220 delete [] count;
4221 } else {
4222 numberIn = numberEligible;
4223 for (iRow = 0; iRow < numberRows_; iRow++) {
4224 int kRow = mapping[iRow];
4225 if (kRow >= 0) {
4226 rotate[kRow] = 2;
4227 }
4228 }
4229 }
4230 if (!trueNetwork)
4231 numberIn = - numberIn;
4232 delete [] column;
4233 delete [] rowStart;
4234 delete [] elementByRow;
4235 delete [] columnLength;
4236 // redo rotate
4237 char * rotate2 = CoinCopyOfArray(rotate, numberEligible);
4238 for (iRow = 0; iRow < numberRows_; iRow++) {
4239 int kRow = mapping[iRow];
4240 if (kRow >= 0) {
4241 int iState = rotate2[kRow];
4242 if (iState > 1)
4243 iState -= 2;
4244 else
4245 iState = -1;
4246 rotate[iRow] = static_cast<char>(iState);
4247 } else {
4248 rotate[iRow] = -1;
4249 }
4250 }
4251 delete [] rotate2;
4252 delete [] eligible;
4253 delete [] mapping;
4254 return numberIn;
4255}
4256//#############################################################################
4257// Constructors / Destructor / Assignment
4258//#############################################################################
4259
4260//-------------------------------------------------------------------
4261// Default Constructor
4262//-------------------------------------------------------------------
4263ClpDataSave::ClpDataSave ()
4264{
4265 dualBound_ = 0.0;
4266 infeasibilityCost_ = 0.0;
4267 sparseThreshold_ = 0;
4268 pivotTolerance_ = 0.0;
4269 zeroFactorizationTolerance_ = 1.0e13;
4270 zeroSimplexTolerance_ = 1.0e-13;
4271 acceptablePivot_ = 0.0;
4272 objectiveScale_ = 1.0;
4273 perturbation_ = 0;
4274 forceFactorization_ = -1;
4275 scalingFlag_ = 0;
4276 specialOptions_ = 0;
4277}
4278
4279//-------------------------------------------------------------------
4280// Copy constructor
4281//-------------------------------------------------------------------
4282ClpDataSave::ClpDataSave (const ClpDataSave & rhs)
4283{
4284 dualBound_ = rhs.dualBound_;
4285 infeasibilityCost_ = rhs.infeasibilityCost_;
4286 pivotTolerance_ = rhs.pivotTolerance_;
4287 zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_;
4288 zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_;
4289 acceptablePivot_ = rhs.acceptablePivot_;
4290 objectiveScale_ = rhs.objectiveScale_;
4291 sparseThreshold_ = rhs.sparseThreshold_;
4292 perturbation_ = rhs.perturbation_;
4293 forceFactorization_ = rhs.forceFactorization_;
4294 scalingFlag_ = rhs.scalingFlag_;
4295 specialOptions_ = rhs.specialOptions_;
4296}
4297
4298//-------------------------------------------------------------------
4299// Destructor
4300//-------------------------------------------------------------------
4301ClpDataSave::~ClpDataSave ()
4302{
4303}
4304
4305//----------------------------------------------------------------
4306// Assignment operator
4307//-------------------------------------------------------------------
4308ClpDataSave &
4309ClpDataSave::operator=(const ClpDataSave& rhs)
4310{
4311 if (this != &rhs) {
4312 dualBound_ = rhs.dualBound_;
4313 infeasibilityCost_ = rhs.infeasibilityCost_;
4314 pivotTolerance_ = rhs.pivotTolerance_;
4315 zeroFactorizationTolerance_ = rhs.zeroFactorizationTolerance_;
4316 zeroSimplexTolerance_ = rhs.zeroSimplexTolerance_;
4317 acceptablePivot_ = rhs.acceptablePivot_;
4318 objectiveScale_ = rhs.objectiveScale_;
4319 sparseThreshold_ = rhs.sparseThreshold_;
4320 perturbation_ = rhs.perturbation_;
4321 forceFactorization_ = rhs.forceFactorization_;
4322 scalingFlag_ = rhs.scalingFlag_;
4323 specialOptions_ = rhs.specialOptions_;
4324 }
4325 return *this;
4326}
4327// Create C++ lines to get to current state
4328void
4329ClpModel::generateCpp( FILE * fp)
4330{
4331 // Stuff that can't be done easily
4332 if (!lengthNames_) {
4333 // no names
4334 fprintf(fp, " clpModel->dropNames();\n");
4335 }
4336 ClpModel defaultModel;
4337 ClpModel * other = &defaultModel;
4338 int iValue1, iValue2;
4339 double dValue1, dValue2;
4340 iValue1 = this->maximumIterations();
4341 iValue2 = other->maximumIterations();
4342 fprintf(fp, "%d int save_maximumIterations = clpModel->maximumIterations();\n", iValue1 == iValue2 ? 2 : 1);
4343 fprintf(fp, "%d clpModel->setMaximumIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4344 fprintf(fp, "%d clpModel->setMaximumIterations(save_maximumIterations);\n", iValue1 == iValue2 ? 7 : 6);
4345 dValue1 = this->primalTolerance();
4346 dValue2 = other->primalTolerance();
4347 fprintf(fp, "%d double save_primalTolerance = clpModel->primalTolerance();\n", dValue1 == dValue2 ? 2 : 1);
4348 fprintf(fp, "%d clpModel->setPrimalTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4349 fprintf(fp, "%d clpModel->setPrimalTolerance(save_primalTolerance);\n", dValue1 == dValue2 ? 7 : 6);
4350 dValue1 = this->dualTolerance();
4351 dValue2 = other->dualTolerance();
4352 fprintf(fp, "%d double save_dualTolerance = clpModel->dualTolerance();\n", dValue1 == dValue2 ? 2 : 1);
4353 fprintf(fp, "%d clpModel->setDualTolerance(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4354 fprintf(fp, "%d clpModel->setDualTolerance(save_dualTolerance);\n", dValue1 == dValue2 ? 7 : 6);
4355 iValue1 = this->numberIterations();
4356 iValue2 = other->numberIterations();
4357 fprintf(fp, "%d int save_numberIterations = clpModel->numberIterations();\n", iValue1 == iValue2 ? 2 : 1);
4358 fprintf(fp, "%d clpModel->setNumberIterations(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4359 fprintf(fp, "%d clpModel->setNumberIterations(save_numberIterations);\n", iValue1 == iValue2 ? 7 : 6);
4360 dValue1 = this->maximumSeconds();
4361 dValue2 = other->maximumSeconds();
4362 fprintf(fp, "%d double save_maximumSeconds = clpModel->maximumSeconds();\n", dValue1 == dValue2 ? 2 : 1);
4363 fprintf(fp, "%d clpModel->setMaximumSeconds(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4364 fprintf(fp, "%d clpModel->setMaximumSeconds(save_maximumSeconds);\n", dValue1 == dValue2 ? 7 : 6);
4365 dValue1 = this->optimizationDirection();
4366 dValue2 = other->optimizationDirection();
4367 fprintf(fp, "%d double save_optimizationDirection = clpModel->optimizationDirection();\n", dValue1 == dValue2 ? 2 : 1);
4368 fprintf(fp, "%d clpModel->setOptimizationDirection(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4369 fprintf(fp, "%d clpModel->setOptimizationDirection(save_optimizationDirection);\n", dValue1 == dValue2 ? 7 : 6);
4370 dValue1 = this->objectiveScale();
4371 dValue2 = other->objectiveScale();
4372 fprintf(fp, "%d double save_objectiveScale = clpModel->objectiveScale();\n", dValue1 == dValue2 ? 2 : 1);
4373 fprintf(fp, "%d clpModel->setObjectiveScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4374 fprintf(fp, "%d clpModel->setObjectiveScale(save_objectiveScale);\n", dValue1 == dValue2 ? 7 : 6);
4375 dValue1 = this->rhsScale();
4376 dValue2 = other->rhsScale();
4377 fprintf(fp, "%d double save_rhsScale = clpModel->rhsScale();\n", dValue1 == dValue2 ? 2 : 1);
4378 fprintf(fp, "%d clpModel->setRhsScale(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4379 fprintf(fp, "%d clpModel->setRhsScale(save_rhsScale);\n", dValue1 == dValue2 ? 7 : 6);
4380 iValue1 = this->scalingFlag();
4381 iValue2 = other->scalingFlag();
4382 fprintf(fp, "%d int save_scalingFlag = clpModel->scalingFlag();\n", iValue1 == iValue2 ? 2 : 1);
4383 fprintf(fp, "%d clpModel->scaling(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4384 fprintf(fp, "%d clpModel->scaling(save_scalingFlag);\n", iValue1 == iValue2 ? 7 : 6);
4385 dValue1 = this->getSmallElementValue();
4386 dValue2 = other->getSmallElementValue();
4387 fprintf(fp, "%d double save_getSmallElementValue = clpModel->getSmallElementValue();\n", dValue1 == dValue2 ? 2 : 1);
4388 fprintf(fp, "%d clpModel->setSmallElementValue(%g);\n", dValue1 == dValue2 ? 4 : 3, dValue1);
4389 fprintf(fp, "%d clpModel->setSmallElementValue(save_getSmallElementValue);\n", dValue1 == dValue2 ? 7 : 6);
4390 iValue1 = this->logLevel();
4391 iValue2 = other->logLevel();
4392 fprintf(fp, "%d int save_logLevel = clpModel->logLevel();\n", iValue1 == iValue2 ? 2 : 1);
4393 fprintf(fp, "%d clpModel->setLogLevel(%d);\n", iValue1 == iValue2 ? 4 : 3, iValue1);
4394 fprintf(fp, "%d clpModel->setLogLevel(save_logLevel);\n", iValue1 == iValue2 ? 7 : 6);
4395}
4396