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 | //############################################################################# |
69 | ClpModel::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 | |
150 | ClpModel::~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) |
159 | void |
160 | ClpModel::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 | } |
215 | void |
216 | ClpModel::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 | } |
226 | void |
227 | ClpModel::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 | //############################################################################# |
238 | void ClpModel::setPrimalTolerance( double value) |
239 | { |
240 | if (value > 0.0 && value < 1.0e10) |
241 | dblParam_[ClpPrimalTolerance] = value; |
242 | } |
243 | void ClpModel::setDualTolerance( double value) |
244 | { |
245 | if (value > 0.0 && value < 1.0e10) |
246 | dblParam_[ClpDualTolerance] = value; |
247 | } |
248 | void ClpModel::setOptimizationDirection( double value) |
249 | { |
250 | optimizationDirection_ = value; |
251 | } |
252 | void |
253 | ClpModel::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 |
314 | void ClpModel::setRowObjective(const double * rowObjective) |
315 | { |
316 | delete [] rowObjective_; |
317 | rowObjective_ = ClpCopyOfArray(rowObjective, numberRows_); |
318 | whatsChanged_ = 0; |
319 | } |
320 | void |
321 | ClpModel::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 | } |
342 | void |
343 | ClpModel::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 | } |
369 | void |
370 | ClpModel::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 | } |
387 | void |
388 | ClpModel::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 |
410 | int |
411 | ClpModel::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 |
506 | void |
507 | ClpModel::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 |
520 | static 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 */ |
528 | void |
529 | ClpModel::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. */ |
541 | void |
542 | ClpModel::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. */ |
552 | void |
553 | ClpModel::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 */ |
562 | void |
563 | ClpModel::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 | } |
575 | void 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. */ |
604 | void |
605 | ClpModel::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. */ |
621 | void |
622 | ClpModel::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 */ |
637 | void |
638 | ClpModel::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 | } |
656 | void 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. |
685 | ClpModel::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 |
723 | ClpModel & |
724 | ClpModel::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 */ |
742 | void |
743 | ClpModel::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 |
954 | void |
955 | ClpModel::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 */ |
978 | void |
979 | ClpModel::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 |
1005 | void |
1006 | ClpModel::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 | |
1056 | bool |
1057 | ClpModel::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 | |
1081 | bool |
1082 | ClpModel::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 | |
1127 | bool |
1128 | ClpModel::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 |
1144 | double * 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 |
1160 | double * 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 | } |
1189 | char * 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 |
1221 | void |
1222 | ClpModel::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 | */ |
1236 | int |
1237 | ClpModel::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 |
1247 | void |
1248 | ClpModel::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 |
1405 | void |
1406 | ClpModel::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 |
1507 | void |
1508 | ClpModel::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 |
1587 | void |
1588 | ClpModel::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 |
1597 | void |
1598 | ClpModel::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 |
1657 | void |
1658 | ClpModel::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 |
1690 | void |
1691 | ClpModel::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 |
1746 | int |
1747 | ClpModel::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 |
1925 | int |
1926 | ClpModel::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 |
2055 | void |
2056 | ClpModel::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 |
2069 | void |
2070 | ClpModel::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 |
2138 | void |
2139 | ClpModel::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 |
2172 | void |
2173 | ClpModel::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 |
2239 | int |
2240 | ClpModel::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 |
2375 | int |
2376 | ClpModel::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 |
2503 | void |
2504 | ClpModel::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 |
2523 | void |
2524 | ClpModel::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 |
2543 | void |
2544 | ClpModel::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 |
2563 | void |
2564 | ClpModel::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 |
2583 | void |
2584 | ClpModel::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) |
2601 | double * |
2602 | ClpModel::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 | } |
2626 | double * |
2627 | ClpModel::unboundedRay() const |
2628 | { |
2629 | double * array = NULL; |
2630 | if (problemStatus_ == 2) |
2631 | array = ClpCopyOfArray(ray_, numberColumns_); |
2632 | return array; |
2633 | } |
2634 | void |
2635 | ClpModel::setMaximumIterations(int value) |
2636 | { |
2637 | if(value >= 0) |
2638 | intParam_[ClpMaxNumIteration] = value; |
2639 | } |
2640 | void |
2641 | ClpModel::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) |
2649 | bool |
2650 | ClpModel::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 |
2660 | void |
2661 | ClpModel::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) |
2670 | void |
2671 | ClpModel::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 |
2679 | CoinMessageHandler * |
2680 | ClpModel::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 |
2690 | void |
2691 | ClpModel::popMessageHandler(CoinMessageHandler * oldHandler, bool oldDefault) |
2692 | { |
2693 | if (defaultHandler_) |
2694 | delete handler_; |
2695 | defaultHandler_ = oldDefault; |
2696 | handler_ = oldHandler; |
2697 | } |
2698 | // Set language |
2699 | void |
2700 | ClpModel::newLanguage(CoinMessages::Language language) |
2701 | { |
2702 | messages_ = ClpMessage(language); |
2703 | } |
2704 | #ifndef SLIM_NOIO |
2705 | // Read an mps file from the given filename |
2706 | int |
2707 | ClpModel::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 |
2804 | int |
2805 | ClpModel::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 |
2887 | bool 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 | |
2907 | bool 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 | } |
2928 | void |
2929 | ClpModel::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 | } |
2939 | void |
2940 | ClpModel::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 | //----------------------------------------------------------------------------- |
2953 | void |
2954 | ClpModel::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 */ |
2968 | bool |
2969 | ClpModel::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 |
2984 | void |
2985 | ClpModel::dropNames() |
2986 | { |
2987 | lengthNames_ = 0; |
2988 | rowNames_ = std::vector<std::string> (); |
2989 | columnNames_ = std::vector<std::string> (); |
2990 | } |
2991 | #endif |
2992 | // Drop integer informations |
2993 | void |
2994 | ClpModel::deleteIntegerInformation() |
2995 | { |
2996 | delete [] integerType_; |
2997 | integerType_ = NULL; |
2998 | } |
2999 | /* Return copy of status array (char[numberRows+numberColumns]), |
3000 | use delete [] */ |
3001 | unsigned char * |
3002 | ClpModel::statusCopy() const |
3003 | { |
3004 | return ClpCopyOfArray(status_, numberRows_ + numberColumns_); |
3005 | } |
3006 | // Copy in status vector |
3007 | void |
3008 | ClpModel::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 |
3020 | void |
3021 | ClpModel::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 | } |
3035 | void |
3036 | ClpModel::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 |
3051 | void |
3052 | ClpModel::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 |
3060 | void |
3061 | ClpModel::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 |
3068 | double * 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 | } |
3079 | char * 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 | } |
3090 | unsigned 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) |
3103 | void |
3104 | ClpModel::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 |
3112 | ClpModel::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 |
3268 | void |
3269 | ClpModel::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 |
3290 | std::string |
3291 | ClpModel::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 |
3309 | void |
3310 | ClpModel::(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 |
3327 | std::string |
3328 | ClpModel::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 |
3346 | void |
3347 | ClpModel::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 |
3364 | void |
3365 | ClpModel::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 |
3380 | void |
3381 | ClpModel::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 |
3396 | void |
3397 | ClpModel::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 |
3419 | void |
3420 | ClpModel::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 |
3443 | void |
3444 | ClpModel::setPrimalObjectiveLimit(double value) |
3445 | { |
3446 | dblParam_[ClpPrimalObjectiveLimit] = value; |
3447 | } |
3448 | // Dual objective limit |
3449 | void |
3450 | ClpModel::setDualObjectiveLimit(double value) |
3451 | { |
3452 | dblParam_[ClpDualObjectiveLimit] = value; |
3453 | } |
3454 | // Objective offset |
3455 | void |
3456 | ClpModel::setObjectiveOffset(double value) |
3457 | { |
3458 | dblParam_[ClpObjOffset] = value; |
3459 | } |
3460 | // Solve a problem with no elements - return status |
3461 | int 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 | |
3589 | Row and column names may be null. |
3590 | formatType is |
3591 | <ul> |
3592 | <li> 0 - normal |
3593 | <li> 1 - extra accuracy |
3594 | <li> 2 - IEEE hex (later) |
3595 | </ul> |
3596 | |
3597 | Returns non-zero on I/O error |
3598 | */ |
3599 | int |
3600 | ClpModel::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 ** |
3652 | const char * const * |
3653 | ClpModel::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 ** |
3692 | const char * const * |
3693 | ClpModel::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 |
3731 | void |
3732 | ClpModel::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) |
3742 | void |
3743 | ClpModel::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) |
3749 | void |
3750 | ClpModel::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 | } |
3766 | void |
3767 | ClpModel::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 | } |
3779 | void |
3780 | ClpModel::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 |
3793 | void |
3794 | ClpModel::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 */ |
3836 | void |
3837 | ClpModel::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 | } |
3853 | void |
3854 | ClpModel::setSpecialOptions(unsigned int value) |
3855 | { |
3856 | specialOptions_ = value; |
3857 | } |
3858 | /* This creates a coinModel object |
3859 | */ |
3860 | CoinModel * |
3861 | ClpModel::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_ |
3958 | void |
3959 | ClpModel::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_ |
3998 | void |
3999 | ClpModel::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 |
4012 | void |
4013 | ClpModel::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 | */ |
4026 | int |
4027 | ClpModel::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 | //------------------------------------------------------------------- |
4263 | ClpDataSave::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 | //------------------------------------------------------------------- |
4282 | ClpDataSave::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 | //------------------------------------------------------------------- |
4301 | ClpDataSave::~ClpDataSave () |
4302 | { |
4303 | } |
4304 | |
4305 | //---------------------------------------------------------------- |
4306 | // Assignment operator |
4307 | //------------------------------------------------------------------- |
4308 | ClpDataSave & |
4309 | ClpDataSave::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 |
4328 | void |
4329 | ClpModel::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 | |