1 | /* $Id: CoinSnapshot.cpp 1448 2011-06-19 15:34:41Z stefan $ */ |
2 | // Copyright (C) 2005, 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 | |
7 | #include "CoinUtilsConfig.h" |
8 | #include "CoinHelperFunctions.hpp" |
9 | #include "CoinSnapshot.hpp" |
10 | #include "CoinPackedMatrix.hpp" |
11 | #include "CoinFinite.hpp" |
12 | |
13 | //############################################################################# |
14 | // Constructors / Destructor / Assignment |
15 | //############################################################################# |
16 | |
17 | //------------------------------------------------------------------- |
18 | // Default Constructor |
19 | //------------------------------------------------------------------- |
20 | CoinSnapshot::CoinSnapshot () |
21 | { |
22 | gutsOfDestructor(13); |
23 | } |
24 | |
25 | //------------------------------------------------------------------- |
26 | // Copy constructor |
27 | //------------------------------------------------------------------- |
28 | CoinSnapshot::CoinSnapshot (const CoinSnapshot & rhs) |
29 | { |
30 | gutsOfDestructor(13); |
31 | gutsOfCopy(rhs); |
32 | } |
33 | |
34 | //------------------------------------------------------------------- |
35 | // Destructor |
36 | //------------------------------------------------------------------- |
37 | CoinSnapshot::~CoinSnapshot () |
38 | { |
39 | gutsOfDestructor(15); |
40 | } |
41 | |
42 | //---------------------------------------------------------------- |
43 | // Assignment operator |
44 | //------------------------------------------------------------------- |
45 | CoinSnapshot & |
46 | CoinSnapshot::operator=(const CoinSnapshot& rhs) |
47 | { |
48 | if (this != &rhs) { |
49 | gutsOfDestructor(15); |
50 | gutsOfCopy(rhs); |
51 | } |
52 | return *this; |
53 | } |
54 | // Does main work of destructor |
55 | void |
56 | CoinSnapshot::gutsOfDestructor(int type) |
57 | { |
58 | if ((type&2)!=0) { |
59 | if (owned_.colLower) |
60 | delete [] colLower_; |
61 | if (owned_.colUpper) |
62 | delete [] colUpper_; |
63 | if (owned_.rowLower) |
64 | delete [] rowLower_; |
65 | if (owned_.rowUpper) |
66 | delete [] rowUpper_; |
67 | if (owned_.rightHandSide) |
68 | delete [] rightHandSide_; |
69 | if (owned_.objCoefficients) |
70 | delete [] objCoefficients_; |
71 | if (owned_.colType) |
72 | delete [] colType_; |
73 | if (owned_.matrixByRow) |
74 | delete matrixByRow_; |
75 | if (owned_.matrixByCol) |
76 | delete matrixByCol_; |
77 | if (owned_.originalMatrixByRow) |
78 | delete originalMatrixByRow_; |
79 | if (owned_.originalMatrixByCol) |
80 | delete originalMatrixByCol_; |
81 | if (owned_.colSolution) |
82 | delete [] colSolution_; |
83 | if (owned_.rowPrice) |
84 | delete [] rowPrice_; |
85 | if (owned_.reducedCost) |
86 | delete [] reducedCost_; |
87 | if (owned_.rowActivity) |
88 | delete [] rowActivity_; |
89 | if (owned_.doNotSeparateThis) |
90 | delete [] doNotSeparateThis_; |
91 | } |
92 | if ((type&4)!=0) { |
93 | objSense_ = 1.0; |
94 | infinity_ = COIN_DBL_MAX; |
95 | dualTolerance_ = 1.0e-7; |
96 | primalTolerance_ = 1.0e-7; |
97 | integerTolerance_ = 1.0e-7; |
98 | } |
99 | if ((type&8)!=0) { |
100 | objValue_ = COIN_DBL_MAX; |
101 | objOffset_ = 0.0; |
102 | integerUpperBound_ = COIN_DBL_MAX; |
103 | integerLowerBound_ = -COIN_DBL_MAX; |
104 | } |
105 | if ((type&1)!=0) { |
106 | colLower_ = NULL; |
107 | colUpper_ = NULL; |
108 | rowLower_ = NULL; |
109 | rowUpper_ = NULL; |
110 | rightHandSide_ = NULL; |
111 | objCoefficients_ = NULL; |
112 | colType_ = NULL; |
113 | matrixByRow_ = NULL; |
114 | matrixByCol_ = NULL; |
115 | originalMatrixByRow_ = NULL; |
116 | originalMatrixByCol_ = NULL; |
117 | colSolution_ = NULL; |
118 | rowPrice_ = NULL; |
119 | reducedCost_ = NULL; |
120 | rowActivity_ = NULL; |
121 | doNotSeparateThis_ = NULL; |
122 | numCols_ = 0; |
123 | numRows_ = 0; |
124 | numElements_ = 0; |
125 | numIntegers_ = 0; |
126 | // say nothing owned |
127 | memset(&owned_,0,sizeof(owned_)); |
128 | } |
129 | } |
130 | // Does main work of copy |
131 | void |
132 | CoinSnapshot::gutsOfCopy(const CoinSnapshot & rhs) |
133 | { |
134 | objSense_ = rhs.objSense_; |
135 | infinity_ = rhs.infinity_; |
136 | objValue_ = rhs.objValue_; |
137 | objOffset_ = rhs.objOffset_; |
138 | dualTolerance_ = rhs.dualTolerance_; |
139 | primalTolerance_ = rhs.primalTolerance_; |
140 | integerTolerance_ = rhs.integerTolerance_; |
141 | integerUpperBound_ = rhs.integerUpperBound_; |
142 | integerLowerBound_ = rhs.integerLowerBound_; |
143 | numCols_ = rhs.numCols_; |
144 | numRows_ = rhs.numRows_; |
145 | numElements_ = rhs.numElements_; |
146 | numIntegers_ = rhs.numIntegers_; |
147 | owned_ = rhs.owned_; |
148 | if (owned_.colLower) |
149 | colLower_ = CoinCopyOfArray(rhs.colLower_,numCols_); |
150 | else |
151 | colLower_ = rhs.colLower_; |
152 | if (owned_.colUpper) |
153 | colUpper_ = CoinCopyOfArray(rhs.colUpper_,numCols_); |
154 | else |
155 | colUpper_ = rhs.colUpper_; |
156 | if (owned_.rowLower) |
157 | rowLower_ = CoinCopyOfArray(rhs.rowLower_,numRows_); |
158 | else |
159 | rowLower_ = rhs.rowLower_; |
160 | if (owned_.rowUpper) |
161 | rowUpper_ = CoinCopyOfArray(rhs.rowUpper_,numRows_); |
162 | else |
163 | rowUpper_ = rhs.rowUpper_; |
164 | if (owned_.rightHandSide) |
165 | rightHandSide_ = CoinCopyOfArray(rhs.rightHandSide_,numRows_); |
166 | else |
167 | rightHandSide_ = rhs.rightHandSide_; |
168 | if (owned_.objCoefficients) |
169 | objCoefficients_ = CoinCopyOfArray(rhs.objCoefficients_,numCols_); |
170 | else |
171 | objCoefficients_ = rhs.objCoefficients_; |
172 | if (owned_.colType) |
173 | colType_ = CoinCopyOfArray(rhs.colType_,numCols_); |
174 | else |
175 | colType_ = rhs.colType_; |
176 | if (owned_.colSolution) |
177 | colSolution_ = CoinCopyOfArray(rhs.colSolution_,numCols_); |
178 | else |
179 | colSolution_ = rhs.colSolution_; |
180 | if (owned_.rowPrice) |
181 | rowPrice_ = CoinCopyOfArray(rhs.rowPrice_,numRows_); |
182 | else |
183 | rowPrice_ = rhs.rowPrice_; |
184 | if (owned_.reducedCost) |
185 | reducedCost_ = CoinCopyOfArray(rhs.reducedCost_,numCols_); |
186 | else |
187 | reducedCost_ = rhs.reducedCost_; |
188 | if (owned_.rowActivity) |
189 | rowActivity_ = CoinCopyOfArray(rhs.rowActivity_,numRows_); |
190 | else |
191 | rowActivity_ = rhs.rowActivity_; |
192 | if (owned_.doNotSeparateThis) |
193 | doNotSeparateThis_ = CoinCopyOfArray(rhs.doNotSeparateThis_,numCols_); |
194 | else |
195 | doNotSeparateThis_ = rhs.doNotSeparateThis_; |
196 | if (owned_.matrixByRow) |
197 | matrixByRow_ = new CoinPackedMatrix(*rhs.matrixByRow_); |
198 | else |
199 | matrixByRow_ = rhs.matrixByRow_; |
200 | if (owned_.matrixByCol) |
201 | matrixByCol_ = new CoinPackedMatrix(*rhs.matrixByCol_); |
202 | else |
203 | matrixByCol_ = rhs.matrixByCol_; |
204 | if (owned_.originalMatrixByRow) |
205 | originalMatrixByRow_ = new CoinPackedMatrix(*rhs.originalMatrixByRow_); |
206 | else |
207 | originalMatrixByRow_ = rhs.originalMatrixByRow_; |
208 | if (owned_.originalMatrixByCol) |
209 | originalMatrixByCol_ = new CoinPackedMatrix(*rhs.originalMatrixByCol_); |
210 | else |
211 | originalMatrixByCol_ = rhs.originalMatrixByCol_; |
212 | } |
213 | /* Load in an problem by copying the arguments (the constraints on the |
214 | rows are given by lower and upper bounds). If a pointer is NULL then the |
215 | following values are the default: |
216 | <ul> |
217 | <li> <code>colub</code>: all columns have upper bound infinity |
218 | <li> <code>collb</code>: all columns have lower bound 0 |
219 | <li> <code>rowub</code>: all rows have upper bound infinity |
220 | <li> <code>rowlb</code>: all rows have lower bound -infinity |
221 | <li> <code>obj</code>: all variables have 0 objective coefficient |
222 | </ul> |
223 | */ |
224 | void |
225 | CoinSnapshot::loadProblem(const CoinPackedMatrix& matrix, |
226 | const double* collb, const double* colub, |
227 | const double* obj, |
228 | const double* rowlb, const double* rowub, |
229 | bool makeRowCopy) |
230 | { |
231 | // Keep scalars (apart from objective value etc) |
232 | gutsOfDestructor(3+8); |
233 | numRows_ = matrix.getNumRows(); |
234 | numCols_ = matrix.getNumCols(); |
235 | numElements_ = matrix.getNumElements(); |
236 | owned_.matrixByCol = 1; |
237 | matrixByCol_ = new CoinPackedMatrix(matrix); |
238 | if (makeRowCopy) { |
239 | owned_.matrixByRow = 1; |
240 | CoinPackedMatrix * matrixByRow = new CoinPackedMatrix(matrix); |
241 | matrixByRow->reverseOrdering(); |
242 | matrixByRow_ = matrixByRow; |
243 | } |
244 | colLower_ = CoinCopyOfArray(collb,numCols_,0.0); |
245 | colUpper_ = CoinCopyOfArray(colub,numCols_,infinity_); |
246 | objCoefficients_ = CoinCopyOfArray(obj,numCols_,0.0); |
247 | rowLower_ = CoinCopyOfArray(rowlb,numRows_,-infinity_); |
248 | rowUpper_ = CoinCopyOfArray(rowub,numRows_,infinity_); |
249 | // do rhs as well |
250 | createRightHandSide(); |
251 | } |
252 | |
253 | // Set pointer to array[getNumCols()] of column lower bounds |
254 | void |
255 | CoinSnapshot::setColLower(const double * array, bool copyIn) |
256 | { |
257 | if (owned_.colLower) |
258 | delete [] colLower_; |
259 | if (copyIn) { |
260 | owned_.colLower=1; |
261 | colLower_ = CoinCopyOfArray(array,numCols_); |
262 | } else { |
263 | owned_.colLower=0; |
264 | colLower_ = array; |
265 | } |
266 | } |
267 | // Set pointer to array[getNumCols()] of column upper bounds |
268 | void |
269 | CoinSnapshot::setColUpper(const double * array, bool copyIn) |
270 | { |
271 | if (owned_.colUpper) |
272 | delete [] colUpper_; |
273 | if (copyIn) { |
274 | owned_.colUpper=1; |
275 | colUpper_ = CoinCopyOfArray(array,numCols_); |
276 | } else { |
277 | owned_.colUpper=0; |
278 | colUpper_ = array; |
279 | } |
280 | } |
281 | // Set pointer to array[getNumRows()] of row lower bounds |
282 | void |
283 | CoinSnapshot::setRowLower(const double * array, bool copyIn) |
284 | { |
285 | if (owned_.rowLower) |
286 | delete [] rowLower_; |
287 | if (copyIn) { |
288 | owned_.rowLower=1; |
289 | rowLower_ = CoinCopyOfArray(array,numRows_); |
290 | } else { |
291 | owned_.rowLower=0; |
292 | rowLower_ = array; |
293 | } |
294 | } |
295 | // Set pointer to array[getNumRows()] of row upper bounds |
296 | void |
297 | CoinSnapshot::setRowUpper(const double * array, bool copyIn) |
298 | { |
299 | if (owned_.rowUpper) |
300 | delete [] rowUpper_; |
301 | if (copyIn) { |
302 | owned_.rowUpper=1; |
303 | rowUpper_ = CoinCopyOfArray(array,numRows_); |
304 | } else { |
305 | owned_.rowUpper=0; |
306 | rowUpper_ = array; |
307 | } |
308 | } |
309 | /* Set pointer to array[getNumRows()] of rhs side values |
310 | This gives same results as OsiSolverInterface for useful cases |
311 | If getRowUpper()[i] != infinity then |
312 | getRightHandSide()[i] == getRowUpper()[i] |
313 | else |
314 | getRightHandSide()[i] == getRowLower()[i] |
315 | */ |
316 | void |
317 | CoinSnapshot::setRightHandSide(const double * array, bool copyIn) |
318 | { |
319 | if (owned_.rightHandSide) |
320 | delete [] rightHandSide_; |
321 | if (copyIn) { |
322 | owned_.rightHandSide=1; |
323 | rightHandSide_ = CoinCopyOfArray(array,numRows_); |
324 | } else { |
325 | owned_.rightHandSide=0; |
326 | rightHandSide_ = array; |
327 | } |
328 | } |
329 | /* Create array[getNumRows()] of rhs side values |
330 | This gives same results as OsiSolverInterface for useful cases |
331 | If getRowUpper()[i] != infinity then |
332 | getRightHandSide()[i] == getRowUpper()[i] |
333 | else |
334 | getRightHandSide()[i] == getRowLower()[i] |
335 | */ |
336 | void |
337 | CoinSnapshot::createRightHandSide() |
338 | { |
339 | if (owned_.rightHandSide) |
340 | delete [] rightHandSide_; |
341 | owned_.rightHandSide=1; |
342 | assert (rowUpper_); |
343 | assert (rowLower_); |
344 | double * rightHandSide = CoinCopyOfArray(rowUpper_,numRows_); |
345 | for (int i=0;i<numRows_;i++) { |
346 | if (rightHandSide[i]==infinity_) |
347 | rightHandSide[i] = rowLower_[i]; |
348 | } |
349 | rightHandSide_ = rightHandSide; |
350 | } |
351 | // Set pointer to array[getNumCols()] of objective function coefficients |
352 | void |
353 | CoinSnapshot::setObjCoefficients(const double * array, bool copyIn) |
354 | { |
355 | if (owned_.objCoefficients) |
356 | delete [] objCoefficients_; |
357 | if (copyIn) { |
358 | owned_.objCoefficients=1; |
359 | objCoefficients_ = CoinCopyOfArray(array,numCols_); |
360 | } else { |
361 | owned_.objCoefficients=0; |
362 | objCoefficients_ = array; |
363 | } |
364 | } |
365 | // Set colType array ('B', 'I', or 'C' for Binary, Integer and Continuous) |
366 | void |
367 | CoinSnapshot::setColType(const char *array, bool copyIn) |
368 | { |
369 | if (owned_.colType) |
370 | delete [] colType_; |
371 | if (copyIn) { |
372 | owned_.colType=1; |
373 | colType_ = CoinCopyOfArray(array,numCols_); |
374 | } else { |
375 | owned_.colType=0; |
376 | colType_ = array; |
377 | } |
378 | int i; |
379 | numIntegers_=0; |
380 | for (i=0;i<numCols_;i++) { |
381 | if (colType_[i]=='B'||colType_[i]=='I') |
382 | numIntegers_++; |
383 | } |
384 | } |
385 | // Set pointer to row-wise copy of current matrix |
386 | void |
387 | CoinSnapshot::setMatrixByRow(const CoinPackedMatrix * matrix, bool copyIn) |
388 | { |
389 | if (owned_.matrixByRow) |
390 | delete matrixByRow_; |
391 | if (copyIn) { |
392 | owned_.matrixByRow=1; |
393 | matrixByRow_ = new CoinPackedMatrix(*matrix); |
394 | } else { |
395 | owned_.matrixByRow=0; |
396 | matrixByRow_ = matrix; |
397 | } |
398 | assert (matrixByRow_->getNumCols()==numCols_); |
399 | assert (matrixByRow_->getNumRows()==numRows_); |
400 | } |
401 | // Create row-wise copy from MatrixByCol |
402 | void |
403 | CoinSnapshot::createMatrixByRow() |
404 | { |
405 | if (owned_.matrixByRow) |
406 | delete matrixByRow_; |
407 | assert (matrixByCol_); |
408 | owned_.matrixByRow = 1; |
409 | CoinPackedMatrix * matrixByRow = new CoinPackedMatrix(*matrixByCol_); |
410 | matrixByRow->reverseOrdering(); |
411 | matrixByRow_ = matrixByRow; |
412 | } |
413 | // Set pointer to column-wise copy of current matrix |
414 | void |
415 | CoinSnapshot::setMatrixByCol(const CoinPackedMatrix * matrix, bool copyIn) |
416 | { |
417 | if (owned_.matrixByCol) |
418 | delete matrixByCol_; |
419 | if (copyIn) { |
420 | owned_.matrixByCol=1; |
421 | matrixByCol_ = new CoinPackedMatrix(*matrix); |
422 | } else { |
423 | owned_.matrixByCol=0; |
424 | matrixByCol_ = matrix; |
425 | } |
426 | assert (matrixByCol_->getNumCols()==numCols_); |
427 | assert (matrixByCol_->getNumRows()==numRows_); |
428 | } |
429 | // Set pointer to row-wise copy of "original" matrix |
430 | void |
431 | CoinSnapshot::setOriginalMatrixByRow(const CoinPackedMatrix * matrix, bool copyIn) |
432 | { |
433 | if (owned_.originalMatrixByRow) |
434 | delete originalMatrixByRow_; |
435 | if (copyIn) { |
436 | owned_.originalMatrixByRow=1; |
437 | originalMatrixByRow_ = new CoinPackedMatrix(*matrix); |
438 | } else { |
439 | owned_.originalMatrixByRow=0; |
440 | originalMatrixByRow_ = matrix; |
441 | } |
442 | assert (matrixByRow_->getNumCols()==numCols_); |
443 | } |
444 | // Set pointer to column-wise copy of "original" matrix |
445 | void |
446 | CoinSnapshot::setOriginalMatrixByCol(const CoinPackedMatrix * matrix, bool copyIn) |
447 | { |
448 | if (owned_.originalMatrixByCol) |
449 | delete originalMatrixByCol_; |
450 | if (copyIn) { |
451 | owned_.originalMatrixByCol=1; |
452 | originalMatrixByCol_ = new CoinPackedMatrix(*matrix); |
453 | } else { |
454 | owned_.originalMatrixByCol=0; |
455 | originalMatrixByCol_ = matrix; |
456 | } |
457 | assert (matrixByCol_->getNumCols()==numCols_); |
458 | } |
459 | // Set pointer to array[getNumCols()] of primal variable values |
460 | void |
461 | CoinSnapshot::setColSolution(const double * array, bool copyIn) |
462 | { |
463 | if (owned_.colSolution) |
464 | delete [] colSolution_; |
465 | if (copyIn) { |
466 | owned_.colSolution=1; |
467 | colSolution_ = CoinCopyOfArray(array,numCols_); |
468 | } else { |
469 | owned_.colSolution=0; |
470 | colSolution_ = array; |
471 | } |
472 | } |
473 | // Set pointer to array[getNumRows()] of dual variable values |
474 | void |
475 | CoinSnapshot::setRowPrice(const double * array, bool copyIn) |
476 | { |
477 | if (owned_.rowPrice) |
478 | delete [] rowPrice_; |
479 | if (copyIn) { |
480 | owned_.rowPrice=1; |
481 | rowPrice_ = CoinCopyOfArray(array,numRows_); |
482 | } else { |
483 | owned_.rowPrice=0; |
484 | rowPrice_ = array; |
485 | } |
486 | } |
487 | // Set a pointer to array[getNumCols()] of reduced costs |
488 | void |
489 | CoinSnapshot::setReducedCost(const double * array, bool copyIn) |
490 | { |
491 | if (owned_.reducedCost) |
492 | delete [] reducedCost_; |
493 | if (copyIn) { |
494 | owned_.reducedCost=1; |
495 | reducedCost_ = CoinCopyOfArray(array,numCols_); |
496 | } else { |
497 | owned_.reducedCost=0; |
498 | reducedCost_ = array; |
499 | } |
500 | } |
501 | // Set pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector). |
502 | void |
503 | CoinSnapshot::setRowActivity(const double * array, bool copyIn) |
504 | { |
505 | if (owned_.rowActivity) |
506 | delete [] rowActivity_; |
507 | if (copyIn) { |
508 | owned_.rowActivity=1; |
509 | rowActivity_ = CoinCopyOfArray(array,numRows_); |
510 | } else { |
511 | owned_.rowActivity=0; |
512 | rowActivity_ = array; |
513 | } |
514 | } |
515 | // Set pointer to array[getNumCols()] of primal variable values which should not be separated (for debug) |
516 | void |
517 | CoinSnapshot::setDoNotSeparateThis(const double * array, bool copyIn) |
518 | { |
519 | if (owned_.doNotSeparateThis) |
520 | delete [] doNotSeparateThis_; |
521 | if (copyIn) { |
522 | owned_.doNotSeparateThis=1; |
523 | doNotSeparateThis_ = CoinCopyOfArray(array,numCols_); |
524 | } else { |
525 | owned_.doNotSeparateThis=0; |
526 | doNotSeparateThis_ = array; |
527 | } |
528 | } |
529 | |