1 /* $Id: CoinFactorization1.cpp 2084 2019-01-09 14:17:08Z forrest $ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others. All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5
6 #if defined(_MSC_VER)
7 // Turn off compiler warning about long names
8 #pragma warning(disable : 4786)
9 #endif
10
11 #include "CoinUtilsConfig.h"
12
13 #include <cassert>
14 #include "CoinFactorization.hpp"
15 #include "CoinIndexedVector.hpp"
16 #include "CoinHelperFunctions.hpp"
17 #include "CoinPackedMatrix.hpp"
18 #include "CoinFinite.hpp"
19 #include "CoinTime.hpp"
20 #include <stdio.h>
21 /*
22 Somehow with some BLAS we get multithreaded by default
23 For 99.99% of problems this is not a good idea.
24 The openblas_set_num_threads(1) seems to work even with other blas
25 */
26 #if CLP_USE_OPENBLAS
27 static int blas_initialized = 0;
28 extern "C" {
29 void openblas_set_num_threads(int num_threads);
30 }
31 #endif
32 //:class CoinFactorization. Deals with Factorization and Updates
33 // CoinFactorization. Constructor
CoinFactorization()34 CoinFactorization::CoinFactorization()
35 {
36 persistenceFlag_ = 0;
37 gutsOfInitialize(7);
38 }
39
40 /// Copy constructor
CoinFactorization(const CoinFactorization & other)41 CoinFactorization::CoinFactorization(const CoinFactorization &other)
42 {
43 persistenceFlag_ = 0;
44 gutsOfInitialize(3);
45 persistenceFlag_ = other.persistenceFlag_;
46 gutsOfCopy(other);
47 }
48 /// The real work of constructors etc
49 /// Really really delete if type 2
gutsOfDestructor(int type)50 void CoinFactorization::gutsOfDestructor(int type)
51 {
52 delete[] denseArea_;
53 delete[] densePermute_;
54 if (type == 2) {
55 elementU_.switchOff();
56 startRowU_.switchOff();
57 convertRowToColumnU_.switchOff();
58 indexRowU_.switchOff();
59 indexColumnU_.switchOff();
60 startColumnU_.switchOff();
61 elementL_.switchOff();
62 indexRowL_.switchOff();
63 startColumnL_.switchOff();
64 startColumnR_.switchOff();
65 numberInRow_.switchOff();
66 numberInColumn_.switchOff();
67 numberInColumnPlus_.switchOff();
68 pivotColumn_.switchOff();
69 pivotColumnBack_.switchOff();
70 firstCount_.switchOff();
71 nextCount_.switchOff();
72 lastCount_.switchOff();
73 permute_.switchOff();
74 permuteBack_.switchOff();
75 nextColumn_.switchOff();
76 lastColumn_.switchOff();
77 nextRow_.switchOff();
78 lastRow_.switchOff();
79 saveColumn_.switchOff();
80 markRow_.switchOff();
81 pivotRowL_.switchOff();
82 pivotRegion_.switchOff();
83 elementByRowL_.switchOff();
84 startRowL_.switchOff();
85 indexColumnL_.switchOff();
86 sparse_.switchOff();
87 workArea_.switchOff();
88 workArea2_.switchOff();
89 }
90 elementU_.conditionalDelete();
91 startRowU_.conditionalDelete();
92 convertRowToColumnU_.conditionalDelete();
93 indexRowU_.conditionalDelete();
94 indexColumnU_.conditionalDelete();
95 startColumnU_.conditionalDelete();
96 elementL_.conditionalDelete();
97 indexRowL_.conditionalDelete();
98 startColumnL_.conditionalDelete();
99 startColumnR_.conditionalDelete();
100 numberInRow_.conditionalDelete();
101 numberInColumn_.conditionalDelete();
102 numberInColumnPlus_.conditionalDelete();
103 pivotColumn_.conditionalDelete();
104 pivotColumnBack_.conditionalDelete();
105 firstCount_.conditionalDelete();
106 nextCount_.conditionalDelete();
107 lastCount_.conditionalDelete();
108 permute_.conditionalDelete();
109 permuteBack_.conditionalDelete();
110 nextColumn_.conditionalDelete();
111 lastColumn_.conditionalDelete();
112 nextRow_.conditionalDelete();
113 lastRow_.conditionalDelete();
114 saveColumn_.conditionalDelete();
115 markRow_.conditionalDelete();
116 pivotRowL_.conditionalDelete();
117 pivotRegion_.conditionalDelete();
118 elementByRowL_.conditionalDelete();
119 startRowL_.conditionalDelete();
120 indexColumnL_.conditionalDelete();
121 sparse_.conditionalDelete();
122 workArea_.conditionalDelete();
123 workArea2_.conditionalDelete();
124 numberCompressions_ = 0;
125 biggerDimension_ = 0;
126 numberRows_ = 0;
127 numberRowsExtra_ = 0;
128 maximumRowsExtra_ = 0;
129 numberColumns_ = 0;
130 numberColumnsExtra_ = 0;
131 maximumColumnsExtra_ = 0;
132 numberGoodU_ = 0;
133 numberGoodL_ = 0;
134 totalElements_ = 0;
135 factorElements_ = 0;
136 status_ = -1;
137 numberSlacks_ = 0;
138 numberU_ = 0;
139 maximumU_ = 0;
140 lengthU_ = 0;
141 lengthAreaU_ = 0;
142 numberL_ = 0;
143 baseL_ = 0;
144 lengthL_ = 0;
145 lengthAreaL_ = 0;
146 numberR_ = 0;
147 lengthR_ = 0;
148 lengthAreaR_ = 0;
149 denseArea_ = NULL;
150 densePermute_ = NULL;
151 // next two offsets but this makes cleaner
152 elementR_ = NULL;
153 indexRowR_ = NULL;
154 numberDense_ = 0;
155 //persistenceFlag_=0;
156 ////denseThreshold_=0;
157 }
158 // type - 1 bit tolerances etc, 2 rest
gutsOfInitialize(int type)159 void CoinFactorization::gutsOfInitialize(int type)
160 {
161 #if CLP_USE_OPENBLAS
162 if (!blas_initialized) {
163 blas_initialized = 1;
164 openblas_set_num_threads(CLP_USE_OPENBLAS);
165 }
166 #endif
167 if ((type & 2) != 0) {
168 numberCompressions_ = 0;
169 biggerDimension_ = 0;
170 numberRows_ = 0;
171 numberRowsExtra_ = 0;
172 maximumRowsExtra_ = 0;
173 numberColumns_ = 0;
174 numberColumnsExtra_ = 0;
175 maximumColumnsExtra_ = 0;
176 numberGoodU_ = 0;
177 numberGoodL_ = 0;
178 totalElements_ = 0;
179 factorElements_ = 0;
180 status_ = -1;
181 numberPivots_ = 0;
182 numberSlacks_ = 0;
183 numberU_ = 0;
184 maximumU_ = 0;
185 lengthU_ = 0;
186 lengthAreaU_ = 0;
187 numberL_ = 0;
188 baseL_ = 0;
189 lengthL_ = 0;
190 lengthAreaL_ = 0;
191 numberR_ = 0;
192 lengthR_ = 0;
193 lengthAreaR_ = 0;
194 elementR_ = NULL;
195 indexRowR_ = NULL;
196 // always switch off sparse
197 sparseThreshold_ = 0;
198 sparseThreshold2_ = 0;
199 denseArea_ = NULL;
200 densePermute_ = NULL;
201 numberDense_ = 0;
202 if (!persistenceFlag_) {
203 workArea_ = CoinFactorizationDoubleArrayWithLength();
204 workArea2_ = CoinUnsignedIntArrayWithLength();
205 pivotColumn_ = CoinIntArrayWithLength();
206 }
207 }
208 // after 2 because of persistenceFlag_
209 if ((type & 1) != 0) {
210 areaFactor_ = 0.0;
211 pivotTolerance_ = 1.0e-1;
212 zeroTolerance_ = 1.0e-13;
213 #ifndef COIN_FAST_CODE
214 slackValue_ = -1.0;
215 #endif
216 messageLevel_ = 0;
217 maximumPivots_ = 200;
218 numberTrials_ = 4;
219 relaxCheck_ = 1.0;
220 #if COIN_FACTORIZATION_DENSE_CODE
221 denseThreshold_ = 31;
222 denseThreshold_ = 71;
223 #else
224 denseThreshold_ = 0;
225 #endif
226 biasLU_ = 2;
227 doForrestTomlin_ = true;
228 persistenceFlag_ = 0;
229 }
230 if ((type & 4) != 0) {
231 // we need to get 1 element arrays for any with length n+1 !!
232 startColumnL_.conditionalNew(1);
233 startColumnR_.conditionalNew(1);
234 startRowU_.conditionalNew(1);
235 numberInRow_.conditionalNew(1);
236 nextRow_.conditionalNew(1);
237 lastRow_.conditionalNew(1);
238 pivotRegion_.conditionalNew(1);
239 permuteBack_.conditionalNew(1);
240 permute_.conditionalNew(1);
241 pivotColumnBack_.conditionalNew(1);
242 startColumnU_.conditionalNew(1);
243 numberInColumn_.conditionalNew(1);
244 numberInColumnPlus_.conditionalNew(1);
245 pivotColumn_.conditionalNew(1);
246 nextColumn_.conditionalNew(1);
247 lastColumn_.conditionalNew(1);
248 #if 0
249 collectStatistics_=false;
250 #endif
251
252 // Below are all to collect
253 ftranCountInput_ = 0.0;
254 ftranCountAfterL_ = 0.0;
255 ftranCountAfterR_ = 0.0;
256 ftranCountAfterU_ = 0.0;
257 btranCountInput_ = 0.0;
258 btranCountAfterU_ = 0.0;
259 btranCountAfterR_ = 0.0;
260 btranCountAfterL_ = 0.0;
261
262 // We can roll over factorizations
263 numberFtranCounts_ = 0;
264 numberBtranCounts_ = 0;
265
266 // While these are averages collected over last
267 ftranAverageAfterL_ = 0;
268 ftranAverageAfterR_ = 0;
269 ftranAverageAfterU_ = 0;
270 btranAverageAfterU_ = 0;
271 btranAverageAfterR_ = 0;
272 btranAverageAfterL_ = 0;
273 #ifdef ZEROFAULT
274 startColumnL_.array()[0] = 0;
275 startColumnR_.array()[0] = 0;
276 startRowU_.array()[0] = 0;
277 numberInRow_.array()[0] = 0;
278 nextRow_.array()[0] = 0;
279 lastRow_.array()[0] = 0;
280 pivotRegion_.array()[0] = 0.0;
281 permuteBack_.array()[0] = 0;
282 permute_.array()[0] = 0;
283 pivotColumnBack_.array()[0] = 0;
284 startColumnU_.array()[0] = 0;
285 numberInColumn_.array()[0] = 0;
286 numberInColumnPlus_.array()[0] = 0;
287 pivotColumn_.array()[0] = 0;
288 nextColumn_.array()[0] = 0;
289 lastColumn_.array()[0] = 0;
290 #endif
291 }
292 }
293 //Part of LP
factorize(const CoinPackedMatrix & matrix,int rowIsBasic[],int columnIsBasic[],double areaFactor)294 int CoinFactorization::factorize(
295 const CoinPackedMatrix &matrix,
296 int rowIsBasic[],
297 int columnIsBasic[],
298 double areaFactor)
299 {
300 // maybe for speed will be better to leave as many regions as possible
301 gutsOfDestructor();
302 gutsOfInitialize(2);
303 // ? is this correct
304 //if (biasLU_==2)
305 //biasLU_=3;
306 if (areaFactor)
307 areaFactor_ = areaFactor;
308 const int *row = matrix.getIndices();
309 const CoinBigIndex *columnStart = matrix.getVectorStarts();
310 const int *columnLength = matrix.getVectorLengths();
311 const double *element = matrix.getElements();
312 int numberRows = matrix.getNumRows();
313 if (!numberRows)
314 return 0;
315 int numberColumns = matrix.getNumCols();
316 int numberBasic = 0;
317 int numberElements = 0;
318 int numberRowBasic = 0;
319
320 // compute how much in basis
321
322 int i;
323
324 for (i = 0; i < numberRows; i++) {
325 if (rowIsBasic[i] >= 0)
326 numberRowBasic++;
327 }
328
329 numberBasic = numberRowBasic;
330
331 for (i = 0; i < numberColumns; i++) {
332 if (columnIsBasic[i] >= 0) {
333 numberBasic++;
334 numberElements += columnLength[i];
335 }
336 }
337 if (numberBasic > numberRows) {
338 return -2; // say too many in basis
339 }
340 numberElements = 3 * numberBasic + 3 * numberElements + 20000;
341 getAreas(numberRows, numberBasic, numberElements,
342 2 * numberElements);
343 //fill
344 //copy
345 numberBasic = 0;
346 numberElements = 0;
347 int *indexColumnU = indexColumnU_.array();
348 int *indexRowU = indexRowU_.array();
349 CoinFactorizationDouble *elementU = elementU_.array();
350 for (i = 0; i < numberRows; i++) {
351 if (rowIsBasic[i] >= 0) {
352 indexRowU[numberElements] = i;
353 indexColumnU[numberElements] = numberBasic;
354 elementU[numberElements++] = slackValue_;
355 numberBasic++;
356 }
357 }
358 for (i = 0; i < numberColumns; i++) {
359 if (columnIsBasic[i] >= 0) {
360 CoinBigIndex j;
361 for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
362 indexRowU[numberElements] = row[j];
363 indexColumnU[numberElements] = numberBasic;
364 elementU[numberElements++] = element[j];
365 }
366 numberBasic++;
367 }
368 }
369 lengthU_ = numberElements;
370 maximumU_ = numberElements;
371
372 preProcess(0);
373 factor();
374 numberBasic = 0;
375 if (status_ == 0) {
376 int *permuteBack = permuteBack_.array();
377 int *back = pivotColumnBack();
378 for (i = 0; i < numberRows; i++) {
379 if (rowIsBasic[i] >= 0) {
380 rowIsBasic[i] = permuteBack[back[numberBasic++]];
381 }
382 }
383 for (i = 0; i < numberColumns; i++) {
384 if (columnIsBasic[i] >= 0) {
385 columnIsBasic[i] = permuteBack[back[numberBasic++]];
386 }
387 }
388 // Set up permutation vector
389 // these arrays start off as copies of permute
390 // (and we could use permute_ instead of pivotColumn (not back though))
391 CoinMemcpyN(permute_.array(), numberRows_, pivotColumn_.array());
392 CoinMemcpyN(permuteBack_.array(), numberRows_, pivotColumnBack());
393 } else if (status_ == -1) {
394 const int *pivotColumn = pivotColumn_.array();
395 // mark as basic or non basic
396 for (i = 0; i < numberRows_; i++) {
397 if (rowIsBasic[i] >= 0) {
398 if (pivotColumn[numberBasic] >= 0)
399 rowIsBasic[i] = pivotColumn[numberBasic];
400 else
401 rowIsBasic[i] = -1;
402 numberBasic++;
403 }
404 }
405 for (i = 0; i < numberColumns; i++) {
406 if (columnIsBasic[i] >= 0) {
407 if (pivotColumn[numberBasic] >= 0)
408 columnIsBasic[i] = pivotColumn[numberBasic];
409 else
410 columnIsBasic[i] = -1;
411 numberBasic++;
412 }
413 }
414 }
415
416 return status_;
417 }
418 //Given as triplets
factorize(int numberOfRows,int numberOfColumns,int numberOfElements,int maximumL,int maximumU,const int indicesRow[],const int indicesColumn[],const double elements[],int permutation[],double areaFactor)419 int CoinFactorization::factorize(
420 int numberOfRows,
421 int numberOfColumns,
422 int numberOfElements,
423 int maximumL,
424 int maximumU,
425 const int indicesRow[],
426 const int indicesColumn[],
427 const double elements[],
428 int permutation[],
429 double areaFactor)
430 {
431 gutsOfDestructor();
432 gutsOfInitialize(2);
433 if (areaFactor)
434 areaFactor_ = areaFactor;
435 getAreas(numberOfRows, numberOfColumns, maximumL, maximumU);
436 //copy
437 CoinMemcpyN(indicesRow, numberOfElements, indexRowU_.array());
438 CoinMemcpyN(indicesColumn, numberOfElements, indexColumnU_.array());
439 int i;
440 CoinFactorizationDouble *elementU = elementU_.array();
441 for (i = 0; i < numberOfElements; i++)
442 elementU[i] = elements[i];
443 lengthU_ = numberOfElements;
444 maximumU_ = numberOfElements;
445 preProcess(0);
446 factor();
447 //say which column is pivoting on which row
448 if (status_ == 0) {
449 int *permuteBack = permuteBack_.array();
450 int *back = pivotColumnBack();
451 // permute so slacks on own rows etc
452 for (i = 0; i < numberOfColumns; i++) {
453 permutation[i] = permuteBack[back[i]];
454 }
455 // Set up permutation vector
456 // these arrays start off as copies of permute
457 // (and we could use permute_ instead of pivotColumn (not back though))
458 CoinMemcpyN(permute_.array(), numberRows_, pivotColumn_.array());
459 CoinMemcpyN(permuteBack_.array(), numberRows_, pivotColumnBack());
460 } else if (status_ == -1) {
461 const int *pivotColumn = pivotColumn_.array();
462 // mark as basic or non basic
463 for (i = 0; i < numberOfColumns; i++) {
464 if (pivotColumn[i] >= 0) {
465 permutation[i] = pivotColumn[i];
466 } else {
467 permutation[i] = -1;
468 }
469 }
470 }
471
472 return status_;
473 }
474 /* Two part version for flexibility
475 This part creates arrays for user to fill.
476 maximumL is guessed maximum size of L part of
477 final factorization, maximumU of U part. These are multiplied by
478 areaFactor which can be computed by user or internally.
479 returns 0 -okay, -99 memory */
factorizePart1(int numberOfRows,int,int numberOfElements,int * indicesRow[],int * indicesColumn[],CoinFactorizationDouble * elements[],double areaFactor)480 int CoinFactorization::factorizePart1(int numberOfRows,
481 int,
482 int numberOfElements,
483 int *indicesRow[],
484 int *indicesColumn[],
485 CoinFactorizationDouble *elements[],
486 double areaFactor)
487 {
488 // maybe for speed will be better to leave as many regions as possible
489 gutsOfDestructor();
490 gutsOfInitialize(2);
491 if (areaFactor)
492 areaFactor_ = areaFactor;
493 int numberElements = 3 * numberOfRows + 3 * numberOfElements + 20000;
494 getAreas(numberOfRows, numberOfRows, numberElements,
495 2 * numberElements);
496 // need to trap memory for -99 code
497 *indicesRow = indexRowU_.array();
498 *indicesColumn = indexColumnU_.array();
499 *elements = elementU_.array();
500 lengthU_ = numberOfElements;
501 maximumU_ = numberElements;
502 return 0;
503 }
504 /* This is part two of factorization
505 Arrays belong to factorization and were returned by part 1
506 If status okay, permutation has pivot rows.
507 If status is singular, then basic variables have +1 and ones thrown out have -COIN_INT_MAX
508 to say thrown out.
509 returns 0 -okay, -1 singular, -99 memory */
factorizePart2(int permutation[],int exactNumberElements)510 int CoinFactorization::factorizePart2(int permutation[], int exactNumberElements)
511 {
512 lengthU_ = exactNumberElements;
513 preProcess(0);
514 factor();
515 //say which column is pivoting on which row
516 int i;
517 int *permuteBack = permuteBack_.array();
518 int *back = pivotColumnBack();
519 // permute so slacks on own rows etc
520 for (i = 0; i < numberColumns_; i++) {
521 permutation[i] = permuteBack[back[i]];
522 }
523 if (status_ == 0) {
524 // Set up permutation vector
525 // these arrays start off as copies of permute
526 // (and we could use permute_ instead of pivotColumn (not back though))
527 CoinMemcpyN(permute_.array(), numberRows_, pivotColumn_.array());
528 CoinMemcpyN(permuteBack_.array(), numberRows_, pivotColumnBack());
529 } else if (status_ == -1) {
530 const int *pivotColumn = pivotColumn_.array();
531 // mark as basic or non basic
532 for (i = 0; i < numberColumns_; i++) {
533 if (pivotColumn[i] >= 0) {
534 permutation[i] = pivotColumn[i];
535 } else {
536 permutation[i] = -1;
537 }
538 }
539 }
540
541 return status_;
542 }
543
544 // ~CoinFactorization. Destructor
~CoinFactorization()545 CoinFactorization::~CoinFactorization()
546 {
547 gutsOfDestructor(2);
548 }
549
550 // show_self. Debug show object
show_self() const551 void CoinFactorization::show_self() const
552 {
553 int i;
554
555 const int *pivotColumn = pivotColumn_.array();
556 for (i = 0; i < numberRows_; i++) {
557 std::cout << "r " << i << " " << pivotColumn[i];
558 if (pivotColumnBack())
559 std::cout << " " << pivotColumnBack()[i];
560 std::cout << " " << permute_.array()[i];
561 if (permuteBack_.array())
562 std::cout << " " << permuteBack_.array()[i];
563 std::cout << " " << pivotRegion_.array()[i];
564 std::cout << std::endl;
565 }
566 for (i = 0; i < numberRows_; i++) {
567 std::cout << "u " << i << " " << numberInColumn_.array()[i] << std::endl;
568 int j;
569 CoinSort_2(indexRowU_.array() + startColumnU_.array()[i],
570 indexRowU_.array() + startColumnU_.array()[i] + numberInColumn_.array()[i],
571 elementU_.array() + startColumnU_.array()[i]);
572 for (j = startColumnU_.array()[i]; j < startColumnU_.array()[i] + numberInColumn_.array()[i];
573 j++) {
574 assert(indexRowU_.array()[j] >= 0 && indexRowU_.array()[j] < numberRows_);
575 assert(elementU_.array()[j] > -1.0e50 && elementU_.array()[j] < 1.0e50);
576 std::cout << indexRowU_.array()[j] << " " << elementU_.array()[j] << std::endl;
577 }
578 }
579 for (i = 0; i < numberRows_; i++) {
580 std::cout << "l " << i << " " << startColumnL_.array()[i + 1] - startColumnL_.array()[i] << std::endl;
581 CoinSort_2(indexRowL_.array() + startColumnL_.array()[i],
582 indexRowL_.array() + startColumnL_.array()[i + 1],
583 elementL_.array() + startColumnL_.array()[i]);
584 int j;
585 for (j = startColumnL_.array()[i]; j < startColumnL_.array()[i + 1]; j++) {
586 std::cout << indexRowL_.array()[j] << " " << elementL_.array()[j] << std::endl;
587 }
588 }
589 }
590 // sort so can compare
sort() const591 void CoinFactorization::sort() const
592 {
593 int i;
594
595 for (i = 0; i < numberRows_; i++) {
596 CoinSort_2(indexRowU_.array() + startColumnU_.array()[i],
597 indexRowU_.array() + startColumnU_.array()[i] + numberInColumn_.array()[i],
598 elementU_.array() + startColumnU_.array()[i]);
599 }
600 for (i = 0; i < numberRows_; i++) {
601 CoinSort_2(indexRowL_.array() + startColumnL_.array()[i],
602 indexRowL_.array() + startColumnL_.array()[i + 1],
603 elementL_.array() + startColumnL_.array()[i]);
604 }
605 }
606
607 // getAreas. Gets space for a factorization
608 //called by constructors
getAreas(int numberOfRows,int numberOfColumns,int maximumL,int maximumU)609 void CoinFactorization::getAreas(int numberOfRows,
610 int numberOfColumns,
611 int maximumL,
612 int maximumU)
613 {
614
615 numberRows_ = numberOfRows;
616 numberColumns_ = numberOfColumns;
617 maximumRowsExtra_ = numberRows_ + maximumPivots_;
618 numberRowsExtra_ = numberRows_;
619 maximumColumnsExtra_ = numberColumns_ + maximumPivots_;
620 numberColumnsExtra_ = numberColumns_;
621 lengthAreaU_ = maximumU;
622 lengthAreaL_ = maximumL;
623 if (!areaFactor_) {
624 areaFactor_ = 1.0;
625 }
626 if (areaFactor_ != 1.0) {
627 if ((messageLevel_ & 16) != 0)
628 printf("Increasing factorization areas by %g\n", areaFactor_);
629 // but keep reasonable
630 if (areaFactor_ * lengthAreaU_ < COIN_INT_MAX)
631 lengthAreaU_ = static_cast< int >(areaFactor_ * lengthAreaU_);
632 else
633 lengthAreaU_ = COIN_INT_MAX;
634 if (areaFactor_ * lengthAreaL_ < COIN_INT_MAX)
635 lengthAreaL_ = static_cast< int >(areaFactor_ * lengthAreaL_);
636 else
637 lengthAreaL_ = COIN_INT_MAX;
638 }
639 int lengthU = lengthAreaU_ + EXTRA_U_SPACE;
640 elementU_.conditionalNew(lengthU);
641 indexRowU_.conditionalNew(lengthU);
642 indexColumnU_.conditionalNew(lengthU);
643 elementL_.conditionalNew(lengthAreaL_);
644 indexRowL_.conditionalNew(lengthAreaL_);
645 if (persistenceFlag_) {
646 // But we can use all we have if bigger
647 int length;
648 length = static_cast< int >(CoinMin(elementU_.getSize(), indexRowU_.getSize())) - lengthU;
649 if (length > lengthAreaU_) {
650 lengthAreaU_ = length;
651 assert(indexColumnU_.getSize() == indexRowU_.getSize());
652 }
653 length = static_cast< int >(CoinMin(elementL_.getSize(), indexRowL_.getSize()));
654 if (length > lengthAreaL_) {
655 lengthAreaL_ = length;
656 }
657 }
658 startColumnL_.conditionalNew(numberRows_ + 1);
659 startColumnL_.array()[0] = 0;
660 startRowU_.conditionalNew(maximumRowsExtra_ + 1);
661 // make sure this is valid
662 startRowU_.array()[maximumRowsExtra_] = 0;
663 numberInRow_.conditionalNew(maximumRowsExtra_ + 1);
664 markRow_.conditionalNew(numberRows_);
665 pivotRowL_.conditionalNew(numberRows_ + 1);
666 nextRow_.conditionalNew(maximumRowsExtra_ + 1);
667 lastRow_.conditionalNew(maximumRowsExtra_ + 1);
668 permute_.conditionalNew(maximumRowsExtra_ + 1);
669 pivotRegion_.conditionalNew(maximumRowsExtra_ + 1);
670 #ifdef ZEROFAULT
671 memset(elementU_.array(), 'a', lengthAreaU_ * sizeof(CoinFactorizationDouble));
672 memset(indexRowU_.array(), 'b', lengthAreaU_ * sizeof(int));
673 memset(indexColumnU_.array(), 'c', lengthAreaU_ * sizeof(int));
674 memset(elementL_.array(), 'd', lengthAreaL_ * sizeof(CoinFactorizationDouble));
675 memset(indexRowL_.array(), 'e', lengthAreaL_ * sizeof(int));
676 memset(startColumnL_.array() + 1, 'f', numberRows_ * sizeof(int));
677 memset(startRowU_.array(), 'g', maximumRowsExtra_ * sizeof(int));
678 memset(numberInRow_.array(), 'h', (maximumRowsExtra_ + 1) * sizeof(int));
679 memset(markRow_.array(), 'i', numberRows_ * sizeof(int));
680 memset(pivotRowL_.array(), 'j', (numberRows_ + 1) * sizeof(int));
681 memset(nextRow_.array(), 'k', (maximumRowsExtra_ + 1) * sizeof(int));
682 memset(lastRow_.array(), 'l', (maximumRowsExtra_ + 1) * sizeof(int));
683 memset(permute_.array(), 'l', (maximumRowsExtra_ + 1) * sizeof(int));
684 memset(pivotRegion_.array(), 'm', (maximumRowsExtra_ + 1) * sizeof(CoinFactorizationDouble));
685 #endif
686 startColumnU_.conditionalNew(maximumColumnsExtra_ + 1);
687 numberInColumn_.conditionalNew(maximumColumnsExtra_ + 1);
688 numberInColumnPlus_.conditionalNew(maximumColumnsExtra_ + 1);
689 pivotColumn_.conditionalNew(maximumColumnsExtra_ + 1);
690 nextColumn_.conditionalNew(maximumColumnsExtra_ + 1);
691 lastColumn_.conditionalNew(maximumColumnsExtra_ + 1);
692 saveColumn_.conditionalNew(numberColumns_);
693 #ifdef ZEROFAULT
694 memset(startColumnU_.array(), 'a', (maximumColumnsExtra_ + 1) * sizeof(int));
695 memset(numberInColumn_.array(), 'b', (maximumColumnsExtra_ + 1) * sizeof(int));
696 memset(numberInColumnPlus_.array(), 'c', (maximumColumnsExtra_ + 1) * sizeof(int));
697 memset(pivotColumn_.array(), 'd', (maximumColumnsExtra_ + 1) * sizeof(int));
698 memset(nextColumn_.array(), 'e', (maximumColumnsExtra_ + 1) * sizeof(int));
699 memset(lastColumn_.array(), 'f', (maximumColumnsExtra_ + 1) * sizeof(int));
700 #endif
701 if (numberRows_ + numberColumns_) {
702 if (numberRows_ > numberColumns_) {
703 biggerDimension_ = numberRows_;
704 } else {
705 biggerDimension_ = numberColumns_;
706 }
707 firstCount_.conditionalNew(CoinMax(biggerDimension_ + 2, maximumRowsExtra_ + 1));
708 nextCount_.conditionalNew(numberRows_ + numberColumns_);
709 lastCount_.conditionalNew(numberRows_ + numberColumns_);
710 #ifdef ZEROFAULT
711 memset(firstCount_.array(), 'g', (biggerDimension_ + 2) * sizeof(int));
712 memset(nextCount_.array(), 'h', (numberRows_ + numberColumns_) * sizeof(int));
713 memset(lastCount_.array(), 'i', (numberRows_ + numberColumns_) * sizeof(int));
714 #endif
715 } else {
716 firstCount_.conditionalNew(2);
717 nextCount_.conditionalNew(0);
718 lastCount_.conditionalNew(0);
719 #ifdef ZEROFAULT
720 memset(firstCount_.array(), 'g', 2 * sizeof(int));
721 #endif
722 biggerDimension_ = 0;
723 }
724 }
725
726 // preProcess. PreProcesses raw triplet data
727 //state is 0 - triplets, 1 - some counts etc , 2 - ..
preProcess(int state,int)728 void CoinFactorization::preProcess(int state,
729 int)
730 {
731 int *indexRow = indexRowU_.array();
732 int *indexColumn = indexColumnU_.array();
733 CoinFactorizationDouble *element = elementU_.array();
734 int numberElements = lengthU_;
735 int *numberInRow = numberInRow_.array();
736 int *numberInColumn = numberInColumn_.array();
737 int *numberInColumnPlus = numberInColumnPlus_.array();
738 int *startRow = startRowU_.array();
739 int *startColumn = startColumnU_.array();
740 int numberRows = numberRows_;
741 int numberColumns = numberColumns_;
742
743 if (state < 4)
744 totalElements_ = numberElements;
745 //state falls through to next state
746 switch (state) {
747 case 0: //counts
748 {
749 CoinZeroN(numberInRow, numberRows + 1);
750 CoinZeroN(numberInColumn, maximumColumnsExtra_ + 1);
751 int i;
752 for (i = 0; i < numberElements; i++) {
753 int iRow = indexRow[i];
754 int iColumn = indexColumn[i];
755
756 numberInRow[iRow]++;
757 numberInColumn[iColumn]++;
758 }
759 }
760 case -1: //sort
761 case 1: //sort
762 {
763 int i, k;
764
765 i = 0;
766 int iColumn;
767 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
768 //position after end of Column
769 i += numberInColumn[iColumn];
770 startColumn[iColumn] = i;
771 }
772 for (k = numberElements - 1; k >= 0; k--) {
773 int iColumn = indexColumn[k];
774
775 if (iColumn >= 0) {
776 CoinFactorizationDouble value = element[k];
777 int iRow = indexRow[k];
778
779 indexColumn[k] = -1;
780 while (true) {
781 int iLook = startColumn[iColumn] - 1;
782
783 startColumn[iColumn] = iLook;
784 CoinFactorizationDouble valueSave = element[iLook];
785 int iColumnSave = indexColumn[iLook];
786 int iRowSave = indexRow[iLook];
787
788 element[iLook] = value;
789 indexRow[iLook] = iRow;
790 indexColumn[iLook] = -1;
791 if (iColumnSave >= 0) {
792 iColumn = iColumnSave;
793 value = valueSave;
794 iRow = iRowSave;
795 } else {
796 break;
797 }
798 } /* endwhile */
799 }
800 }
801 }
802 case 2: //move largest in column to beginning
803 //and do row part
804 {
805 int i, k;
806
807 i = 0;
808 int iRow;
809 for (iRow = 0; iRow < numberRows; iRow++) {
810 startRow[iRow] = i;
811 i += numberInRow[iRow];
812 }
813 CoinZeroN(numberInRow, numberRows);
814 int iColumn;
815 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
816 int number = numberInColumn[iColumn];
817
818 if (number) {
819 int first = startColumn[iColumn];
820 int largest = first;
821 int iRowSave = indexRow[first];
822 CoinFactorizationDouble valueSave = element[first];
823 double valueLargest = fabs(valueSave);
824 int iLook = numberInRow[iRowSave];
825
826 numberInRow[iRowSave] = iLook + 1;
827 indexColumn[startRow[iRowSave] + iLook] = iColumn;
828 for (k = first + 1; k < first + number; k++) {
829 int iRow = indexRow[k];
830 int iLook = numberInRow[iRow];
831
832 numberInRow[iRow] = iLook + 1;
833 indexColumn[startRow[iRow] + iLook] = iColumn;
834 CoinFactorizationDouble value = element[k];
835 double valueAbs = fabs(value);
836
837 if (valueAbs > valueLargest) {
838 valueLargest = valueAbs;
839 largest = k;
840 }
841 }
842 indexRow[first] = indexRow[largest];
843 element[first] = element[largest];
844 indexRow[largest] = iRowSave;
845 element[largest] = valueSave;
846 }
847 }
848 }
849 case 3: //links and initialize pivots
850 {
851 int *lastRow = lastRow_.array();
852 int *nextRow = nextRow_.array();
853 int *lastColumn = lastColumn_.array();
854 int *nextColumn = nextColumn_.array();
855
856 CoinFillN(firstCount_.array(), biggerDimension_ + 2, -1);
857 CoinFillN(pivotColumn_.array(), numberColumns_, -1);
858 CoinZeroN(numberInColumnPlus, maximumColumnsExtra_ + 1);
859 int iRow;
860 for (iRow = 0; iRow < numberRows; iRow++) {
861 lastRow[iRow] = iRow - 1;
862 nextRow[iRow] = iRow + 1;
863 int number = numberInRow[iRow];
864
865 addLink(iRow, number);
866 }
867 lastRow[maximumRowsExtra_] = numberRows - 1;
868 nextRow[maximumRowsExtra_] = 0;
869 lastRow[0] = maximumRowsExtra_;
870 nextRow[numberRows - 1] = maximumRowsExtra_;
871 startRow[maximumRowsExtra_] = numberElements;
872 int iColumn;
873 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
874 lastColumn[iColumn] = iColumn - 1;
875 nextColumn[iColumn] = iColumn + 1;
876 int number = numberInColumn[iColumn];
877
878 addLink(iColumn + numberRows, number);
879 }
880 lastColumn[maximumColumnsExtra_] = numberColumns - 1;
881 nextColumn[maximumColumnsExtra_] = 0;
882 lastColumn[0] = maximumColumnsExtra_;
883 if (numberColumns)
884 nextColumn[numberColumns - 1] = maximumColumnsExtra_;
885 startColumn[maximumColumnsExtra_] = numberElements;
886 } break;
887 case 4: //move largest in column to beginning
888 {
889 int i, k;
890 CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
891 int iColumn;
892 int iRow;
893 for (iRow = 0; iRow < numberRows; iRow++) {
894 if (numberInRow[iRow] >= 0) {
895 // zero count
896 numberInRow[iRow] = 0;
897 } else {
898 // empty
899 //numberInRow[iRow]=-1; already that
900 }
901 }
902 //CoinZeroN ( numberInColumnPlus, maximumColumnsExtra_ + 1 );
903 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
904 int number = numberInColumn[iColumn];
905
906 if (number) {
907 // use pivotRegion and startRow for remaining elements
908 int first = startColumn[iColumn];
909 int largest = -1;
910
911 double valueLargest = -1.0;
912 int nOther = 0;
913 k = first;
914 int end = first + number;
915 for (; k < end; k++) {
916 int iRow = indexRow[k];
917 assert(iRow < numberRows_);
918 CoinFactorizationDouble value = element[k];
919 if (numberInRow[iRow] >= 0) {
920 numberInRow[iRow]++;
921 double valueAbs = fabs(value);
922 if (valueAbs > valueLargest) {
923 valueLargest = valueAbs;
924 largest = nOther;
925 }
926 startRow[nOther] = iRow;
927 pivotRegion[nOther++] = value;
928 } else {
929 indexRow[first] = iRow;
930 element[first++] = value;
931 }
932 }
933 numberInColumnPlus[iColumn] = first - startColumn[iColumn];
934 startColumn[iColumn] = first;
935 //largest
936 if (largest >= 0) {
937 indexRow[first] = startRow[largest];
938 element[first++] = pivotRegion[largest];
939 }
940 for (k = 0; k < nOther; k++) {
941 if (k != largest) {
942 indexRow[first] = startRow[k];
943 element[first++] = pivotRegion[k];
944 }
945 }
946 numberInColumn[iColumn] = first - startColumn[iColumn];
947 }
948 }
949 //and do row part
950 i = 0;
951 for (iRow = 0; iRow < numberRows; iRow++) {
952 startRow[iRow] = i;
953 int n = numberInRow[iRow];
954 if (n > 0) {
955 numberInRow[iRow] = 0;
956 i += n;
957 }
958 }
959 for (iColumn = 0; iColumn < numberColumns; iColumn++) {
960 int number = numberInColumn[iColumn];
961
962 if (number) {
963 int first = startColumn[iColumn];
964 for (k = first; k < first + number; k++) {
965 int iRow = indexRow[k];
966 int iLook = numberInRow[iRow];
967
968 numberInRow[iRow] = iLook + 1;
969 indexColumn[startRow[iRow] + iLook] = iColumn;
970 }
971 }
972 }
973 }
974 // modified 3
975 {
976 //set markRow so no rows updated
977 //CoinFillN ( markRow_.array(), numberRows_, -1 );
978 int *lastColumn = lastColumn_.array();
979 int *nextColumn = nextColumn_.array();
980 CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
981
982 int iRow;
983 int numberGood = 0;
984 startColumnL_.array()[0] = 0; //for luck
985 for (iRow = 0; iRow < numberRows; iRow++) {
986 int number = numberInRow[iRow];
987 if (number < 0) {
988 numberInRow[iRow] = 0;
989 pivotRegion[numberGood++] = slackValue_;
990 }
991 }
992 int iColumn;
993 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
994 lastColumn[iColumn] = iColumn - 1;
995 nextColumn[iColumn] = iColumn + 1;
996 int number = numberInColumn[iColumn];
997 deleteLink(iColumn + numberRows);
998 addLink(iColumn + numberRows, number);
999 }
1000 lastColumn[maximumColumnsExtra_] = numberColumns - 1;
1001 nextColumn[maximumColumnsExtra_] = 0;
1002 lastColumn[0] = maximumColumnsExtra_;
1003 if (numberColumns)
1004 nextColumn[numberColumns - 1] = maximumColumnsExtra_;
1005 startColumn[maximumColumnsExtra_] = numberElements;
1006 }
1007 } /* endswitch */
1008 }
1009 #ifdef CLP_FACTORIZATION_INSTRUMENT
1010 double externalTimeStart = 0.0;
1011 double timeInFactorize = 0.0;
1012 double timeInUpdate = 0.0;
1013 double timeInFactorizeFake = 0.0;
1014 double timeInUpdateFake1 = 0.0;
1015 double timeInUpdateFake2 = 0.0;
1016 double timeInUpdateTranspose = 0.0;
1017 double timeInUpdateFT = 0.0;
1018 double timeInUpdateTwoFT = 0.0;
1019 double timeInReplace = 0.0;
1020 double averageLengthR = 0.0;
1021 double averageLengthL = 0.0;
1022 double averageLengthU = 0.0;
1023 double scaledLengthDense = 0.0;
1024 double scaledLengthDenseSquared = 0.0;
1025 double scaledLengthL = 0.0;
1026 double scaledLengthR = 0.0;
1027 double scaledLengthU = 0.0;
1028 int numberUpdate = 1;
1029 int numberUpdateTranspose = 0;
1030 int numberUpdateFT = 0;
1031 int numberUpdateTwoFT = 0;
1032 int numberReplace = 0;
1033 int numberAdded = 0;
1034 int currentLengthR = 0;
1035 int currentLengthU = 0;
1036 int currentTakeoutU = 0;
1037 int startLengthU = 0;
1038 int endLengthU = 0;
1039 int endLengthU2 = 0;
1040 #endif
1041
1042 //Does most of factorization
factor()1043 int CoinFactorization::factor()
1044 {
1045 #ifdef CLP_FACTORIZATION_INSTRUMENT
1046 int nUse = numberUpdate + numberUpdateTranspose + numberUpdateFT + 2 * numberUpdateTwoFT + numberReplace;
1047 double dUse = timeInUpdate + timeInUpdateTranspose + timeInUpdateFT + timeInUpdateTwoFT + timeInReplace;
1048 printf("%.18g time in factorization, using %.18g (%d) -average %.18g\n",
1049 timeInFactorize, dUse, nUse, dUse / static_cast< double >(nUse));
1050 //collectStatistics_=true;
1051 int *startColumnU = startColumnU_.array();
1052 int numberSlacksX = 0;
1053 for (int i = 0; i < numberRows_; i++) {
1054 if (startColumnU[i + 1] != startColumnU[i] + 1)
1055 break;
1056 numberSlacksX++;
1057 }
1058 int numberInUX = startColumnU[numberRows_];
1059 printf("numberCompressions %d ftranInput %g ftranAfterL %g \
1060 ftranAfterR %g ftranAfterU %g btranInput %g \
1061 btranAfterU %g btranAfterR %g btranAfterL %g \
1062 numberFtrans %d numberBtrans %d ftranAvAfterL %g \
1063 ftranAvAfterR %g ftranAvAfterU %g btranAvAfterU %g \
1064 btranAvAfterR %g btranAvAfterL %g\n",
1065 numberCompressions_, ftranCountInput_, ftranCountAfterL_,
1066 ftranCountAfterR_, ftranCountAfterU_, btranCountInput_,
1067 btranCountAfterU_, btranCountAfterR_, btranCountAfterL_,
1068 numberFtranCounts_, numberBtranCounts_, ftranAverageAfterL_,
1069 ftranAverageAfterR_, ftranAverageAfterU_, btranAverageAfterU_,
1070 btranAverageAfterR_, btranAverageAfterL_);
1071 printf("lengthRend %d lengthUend %d takeoutU %d\n",
1072 currentLengthR, currentLengthU, currentTakeoutU);
1073 double timeStart = externalTimeStart;
1074 timeInFactorize = 0.0;
1075 timeInUpdate = 0.0;
1076 timeInUpdateTranspose = 0.0;
1077 timeInUpdateFT = 0.0;
1078 timeInUpdateTwoFT = 0.0;
1079 timeInReplace = 0.0;
1080 numberUpdate = 1;
1081 numberUpdateTranspose = 0;
1082 numberUpdateFT = 0;
1083 numberUpdateTwoFT = 0;
1084 numberReplace = 0;
1085 numberAdded = 0;
1086 currentLengthR = 0;
1087 currentLengthU = 0;
1088 currentTakeoutU = 0;
1089 #endif
1090 int *lastColumn = lastColumn_.array();
1091 int *lastRow = lastRow_.array();
1092 //sparse
1093 status_ = factorSparse();
1094 switch (status_) {
1095 case 0: //finished
1096 totalElements_ = 0;
1097 {
1098 int *pivotColumn = pivotColumn_.array();
1099 if (numberGoodU_ < numberRows_) {
1100 int i, k;
1101 // Clean out unset nextRow
1102 int *nextRow = nextRow_.array();
1103 //int nSing =0;
1104 k = nextRow[maximumRowsExtra_];
1105 while (k != maximumRowsExtra_ && k >= 0) {
1106 int iRow = k;
1107 k = nextRow[k];
1108 //nSing++;
1109 nextRow[iRow] = -1;
1110 }
1111 //assert (nSing);
1112 //printf("%d singularities - good %d rows %d\n",nSing,
1113 // numberGoodU_,numberRows_);
1114 // Now nextRow has -1 or sequence into numberGoodU_;
1115 int *permuteA = permute_.array();
1116 for (i = 0; i < numberRows_; i++) {
1117 int iGood = nextRow[i];
1118 if (iGood >= 0)
1119 permuteA[iGood] = i;
1120 }
1121
1122 // swap arrays
1123 permute_.swap(nextRow_);
1124 int *permute = permute_.array();
1125 for (i = 0; i < numberRows_; i++) {
1126 lastRow[i] = -1;
1127 }
1128 for (i = 0; i < numberColumns_; i++) {
1129 lastColumn[i] = -1;
1130 }
1131 for (i = 0; i < numberGoodU_; i++) {
1132 int goodRow = permuteA[i]; //valid pivot row
1133 int goodColumn = pivotColumn[i];
1134
1135 lastRow[goodRow] = goodColumn; //will now have -1 or column sequence
1136 lastColumn[goodColumn] = goodRow; //will now have -1 or row sequence
1137 }
1138 nextRow_.conditionalDelete();
1139 k = 0;
1140 //copy back and count
1141 for (i = 0; i < numberRows_; i++) {
1142 permute[i] = lastRow[i];
1143 if (permute[i] < 0) {
1144 //std::cout << i << " " <<permute[i] << std::endl;
1145 } else {
1146 k++;
1147 }
1148 }
1149 for (i = 0; i < numberColumns_; i++) {
1150 pivotColumn[i] = lastColumn[i];
1151 }
1152 if ((messageLevel_ & 4) != 0)
1153 std::cout << "Factorization has " << numberRows_ - k
1154 << " singularities" << std::endl;
1155 status_ = -1;
1156 }
1157 }
1158 break;
1159 // dense
1160 case 2:
1161 status_ = factorDense();
1162 if (!status_)
1163 break;
1164 default:
1165 //singular ? or some error
1166 if ((messageLevel_ & 4) != 0)
1167 std::cout << "Error " << status_ << std::endl;
1168 break;
1169 } /* endswitch */
1170 //clean up
1171 if (!status_) {
1172 if ((messageLevel_ & 16) && numberCompressions_)
1173 std::cout << " Factorization did " << numberCompressions_
1174 << " compressions" << std::endl;
1175 if (numberCompressions_ > 10) {
1176 areaFactor_ *= 1.1;
1177 }
1178 numberCompressions_ = 0;
1179 cleanup();
1180 }
1181 #ifdef CLP_FACTORIZATION_INSTRUMENT
1182 timeInFactorize = CoinCpuTime() - timeStart;
1183 printf("%d slacks, startU %d, endL %d, endU %d + %d dense (squared)\n",
1184 numberSlacksX, numberInUX, lengthL_, lengthU_,
1185 numberDense_ * numberDense_);
1186 currentLengthR = 0;
1187 // remember pivots not included in counts
1188 endLengthU = totalElements_ - numberDense_ * numberDense_ - lengthL_;
1189 endLengthU2 = lengthU_;
1190 currentLengthU = lengthU_;
1191 currentTakeoutU = 0;
1192 #endif
1193 return status_;
1194 }
1195
1196 // pivotRowSingleton. Does one pivot on Row Singleton in factorization
pivotRowSingleton(int pivotRow,int pivotColumn)1197 bool CoinFactorization::pivotRowSingleton(int pivotRow,
1198 int pivotColumn)
1199 {
1200 //store pivot columns (so can easily compress)
1201 int *startColumnU = startColumnU_.array();
1202 int startColumn = startColumnU[pivotColumn];
1203 int *numberInRow = numberInRow_.array();
1204 int *numberInColumn = numberInColumn_.array();
1205 int numberDoColumn = numberInColumn[pivotColumn] - 1;
1206 int endColumn = startColumn + numberDoColumn + 1;
1207 int pivotRowPosition = startColumn;
1208 int *indexRowU = indexRowU_.array();
1209 int iRow = indexRowU[pivotRowPosition];
1210 int *startRowU = startRowU_.array();
1211 int *nextRow = nextRow_.array();
1212 int *lastRow = lastRow_.array();
1213
1214 while (iRow != pivotRow) {
1215 pivotRowPosition++;
1216 iRow = indexRowU[pivotRowPosition];
1217 } /* endwhile */
1218 assert(pivotRowPosition < endColumn);
1219 //store column in L, compress in U and take column out
1220 int l = lengthL_;
1221
1222 if (l + numberDoColumn > lengthAreaL_) {
1223 //need more memory
1224 if ((messageLevel_ & 4) != 0)
1225 std::cout << "more memory needed in middle of invert" << std::endl;
1226 return false;
1227 }
1228 int *startColumnL = startColumnL_.array();
1229 CoinFactorizationDouble *elementL = elementL_.array();
1230 int *indexRowL = indexRowL_.array();
1231 startColumnL[numberGoodL_] = l; //for luck and first time
1232 numberGoodL_++;
1233 startColumnL[numberGoodL_] = l + numberDoColumn;
1234 lengthL_ += numberDoColumn;
1235 CoinFactorizationDouble *elementU = elementU_.array();
1236 CoinFactorizationDouble pivotElement = elementU[pivotRowPosition];
1237 CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
1238
1239 pivotRegion_.array()[numberGoodU_] = pivotMultiplier;
1240 int i;
1241
1242 int *indexColumnU = indexColumnU_.array();
1243 for (i = startColumn; i < pivotRowPosition; i++) {
1244 int iRow = indexRowU[i];
1245
1246 indexRowL[l] = iRow;
1247 elementL[l] = elementU[i] * pivotMultiplier;
1248 l++;
1249 //take out of row list
1250 int start = startRowU[iRow];
1251 int iNumberInRow = numberInRow[iRow];
1252 int end = start + iNumberInRow;
1253 int where = start;
1254
1255 while (indexColumnU[where] != pivotColumn) {
1256 where++;
1257 } /* endwhile */
1258 assert(where < end);
1259 indexColumnU[where] = indexColumnU[end - 1];
1260 iNumberInRow--;
1261 numberInRow[iRow] = iNumberInRow;
1262 deleteLink(iRow);
1263 addLink(iRow, iNumberInRow);
1264 }
1265 for (i = pivotRowPosition + 1; i < endColumn; i++) {
1266 int iRow = indexRowU[i];
1267
1268 indexRowL[l] = iRow;
1269 elementL[l] = elementU[i] * pivotMultiplier;
1270 l++;
1271 //take out of row list
1272 int start = startRowU[iRow];
1273 int iNumberInRow = numberInRow[iRow];
1274 int end = start + iNumberInRow;
1275 int where = start;
1276
1277 while (indexColumnU[where] != pivotColumn) {
1278 where++;
1279 } /* endwhile */
1280 assert(where < end);
1281 indexColumnU[where] = indexColumnU[end - 1];
1282 iNumberInRow--;
1283 numberInRow[iRow] = iNumberInRow;
1284 deleteLink(iRow);
1285 addLink(iRow, iNumberInRow);
1286 }
1287 numberInColumn[pivotColumn] = 0;
1288 //modify linked list for pivots
1289 numberInRow[pivotRow] = 0;
1290 deleteLink(pivotRow);
1291 deleteLink(pivotColumn + numberRows_);
1292 //take out this bit of indexColumnU
1293 int next = nextRow[pivotRow];
1294 int last = lastRow[pivotRow];
1295
1296 nextRow[last] = next;
1297 lastRow[next] = last;
1298 lastRow[pivotRow] = -2;
1299 nextRow[pivotRow] = numberGoodU_; //use for permute
1300 return true;
1301 }
1302
1303 // pivotColumnSingleton. Does one pivot on Column Singleton in factorization
pivotColumnSingleton(int pivotRow,int pivotColumn)1304 bool CoinFactorization::pivotColumnSingleton(int pivotRow,
1305 int pivotColumn)
1306 {
1307 int *numberInRow = numberInRow_.array();
1308 int *numberInColumn = numberInColumn_.array();
1309 int *numberInColumnPlus = numberInColumnPlus_.array();
1310 //store pivot columns (so can easily compress)
1311 int numberDoRow = numberInRow[pivotRow] - 1;
1312 int *startColumnU = startColumnU_.array();
1313 int startColumn = startColumnU[pivotColumn];
1314 int put = 0;
1315 int *startRowU = startRowU_.array();
1316 int startRow = startRowU[pivotRow];
1317 int endRow = startRow + numberDoRow + 1;
1318 int *indexColumnU = indexColumnU_.array();
1319 int *indexRowU = indexRowU_.array();
1320 int *saveColumn = saveColumn_.array();
1321 int i;
1322
1323 for (i = startRow; i < endRow; i++) {
1324 int iColumn = indexColumnU[i];
1325
1326 if (iColumn != pivotColumn) {
1327 saveColumn[put++] = iColumn;
1328 }
1329 }
1330 int *nextRow = nextRow_.array();
1331 int *lastRow = lastRow_.array();
1332 //take out this bit of indexColumnU
1333 int next = nextRow[pivotRow];
1334 int last = lastRow[pivotRow];
1335
1336 nextRow[last] = next;
1337 lastRow[next] = last;
1338 nextRow[pivotRow] = numberGoodU_; //use for permute
1339 lastRow[pivotRow] = -2; //mark
1340 //clean up counts
1341 CoinFactorizationDouble *elementU = elementU_.array();
1342 CoinFactorizationDouble pivotElement = elementU[startColumn];
1343
1344 pivotRegion_.array()[numberGoodU_] = 1.0 / pivotElement;
1345 numberInColumn[pivotColumn] = 0;
1346 //totalElements_ --;
1347 //numberInColumnPlus[pivotColumn]++;
1348 //move pivot row in other columns to safe zone
1349 for (i = 0; i < numberDoRow; i++) {
1350 int iColumn = saveColumn[i];
1351
1352 if (numberInColumn[iColumn]) {
1353 int number = numberInColumn[iColumn] - 1;
1354
1355 //modify linked list
1356 deleteLink(iColumn + numberRows_);
1357 addLink(iColumn + numberRows_, number);
1358 //move pivot row element
1359 if (number) {
1360 int start = startColumnU[iColumn];
1361 int pivot = start;
1362 int iRow = indexRowU[pivot];
1363 while (iRow != pivotRow) {
1364 pivot++;
1365 iRow = indexRowU[pivot];
1366 }
1367 assert(pivot < startColumnU[iColumn] + numberInColumn[iColumn]);
1368 if (pivot != start) {
1369 //move largest one up
1370 CoinFactorizationDouble value = elementU[start];
1371
1372 iRow = indexRowU[start];
1373 elementU[start] = elementU[pivot];
1374 indexRowU[start] = indexRowU[pivot];
1375 elementU[pivot] = elementU[start + 1];
1376 indexRowU[pivot] = indexRowU[start + 1];
1377 elementU[start + 1] = value;
1378 indexRowU[start + 1] = iRow;
1379 } else {
1380 //find new largest element
1381 int iRowSave = indexRowU[start + 1];
1382 CoinFactorizationDouble valueSave = elementU[start + 1];
1383 double valueLargest = fabs(valueSave);
1384 int end = start + numberInColumn[iColumn];
1385 int largest = start + 1;
1386
1387 int k;
1388 for (k = start + 2; k < end; k++) {
1389 CoinFactorizationDouble value = elementU[k];
1390 double valueAbs = fabs(value);
1391
1392 if (valueAbs > valueLargest) {
1393 valueLargest = valueAbs;
1394 largest = k;
1395 }
1396 }
1397 indexRowU[start + 1] = indexRowU[largest];
1398 elementU[start + 1] = elementU[largest];
1399 indexRowU[largest] = iRowSave;
1400 elementU[largest] = valueSave;
1401 }
1402 }
1403 //clean up counts
1404 numberInColumn[iColumn]--;
1405 numberInColumnPlus[iColumn]++;
1406 startColumnU[iColumn]++;
1407 //totalElements_--;
1408 }
1409 }
1410 //modify linked list for pivots
1411 deleteLink(pivotRow);
1412 deleteLink(pivotColumn + numberRows_);
1413 numberInRow[pivotRow] = 0;
1414 //put in dummy pivot in L
1415 int l = lengthL_;
1416
1417 int *startColumnL = startColumnL_.array();
1418 startColumnL[numberGoodL_] = l; //for luck and first time
1419 numberGoodL_++;
1420 startColumnL[numberGoodL_] = l;
1421 return true;
1422 }
1423
1424 // getColumnSpace. Gets space for one Column with given length
1425 //may have to do compression (returns true)
1426 //also moves existing vector
getColumnSpace(int iColumn,int extraNeeded)1427 bool CoinFactorization::getColumnSpace(int iColumn,
1428 int extraNeeded)
1429 {
1430 int *numberInColumn = numberInColumn_.array();
1431 int *numberInColumnPlus = numberInColumnPlus_.array();
1432 int *nextColumn = nextColumn_.array();
1433 int *lastColumn = lastColumn_.array();
1434 int number = numberInColumnPlus[iColumn] + numberInColumn[iColumn];
1435 int *startColumnU = startColumnU_.array();
1436 int space = lengthAreaU_ - startColumnU[maximumColumnsExtra_];
1437 CoinFactorizationDouble *elementU = elementU_.array();
1438 int *indexRowU = indexRowU_.array();
1439
1440 if (space < extraNeeded + number + 4) {
1441 //compression
1442 int iColumn = nextColumn[maximumColumnsExtra_];
1443 int put = 0;
1444
1445 while (iColumn != maximumColumnsExtra_) {
1446 //move
1447 int get;
1448 int getEnd;
1449
1450 if (startColumnU[iColumn] >= 0) {
1451 get = startColumnU[iColumn]
1452 - numberInColumnPlus[iColumn];
1453 getEnd = startColumnU[iColumn] + numberInColumn[iColumn];
1454 startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
1455 } else {
1456 get = -startColumnU[iColumn];
1457 getEnd = get + numberInColumn[iColumn];
1458 startColumnU[iColumn] = -put;
1459 }
1460 int i;
1461 for (i = get; i < getEnd; i++) {
1462 indexRowU[put] = indexRowU[i];
1463 elementU[put] = elementU[i];
1464 put++;
1465 }
1466 iColumn = nextColumn[iColumn];
1467 } /* endwhile */
1468 numberCompressions_++;
1469 startColumnU[maximumColumnsExtra_] = put;
1470 space = lengthAreaU_ - put;
1471 if (extraNeeded == COIN_INT_MAX >> 1) {
1472 return true;
1473 }
1474 if (space < extraNeeded + number + 2) {
1475 //need more space
1476 //if we can allocate bigger then do so and copy
1477 //if not then return so code can start again
1478 status_ = -99;
1479 return false;
1480 }
1481 }
1482 int put = startColumnU[maximumColumnsExtra_];
1483 int next = nextColumn[iColumn];
1484 int last = lastColumn[iColumn];
1485
1486 if (extraNeeded || next != maximumColumnsExtra_) {
1487 //out
1488 nextColumn[last] = next;
1489 lastColumn[next] = last;
1490 //in at end
1491 last = lastColumn[maximumColumnsExtra_];
1492 nextColumn[last] = iColumn;
1493 lastColumn[maximumColumnsExtra_] = iColumn;
1494 lastColumn[iColumn] = last;
1495 nextColumn[iColumn] = maximumColumnsExtra_;
1496 //move
1497 int get = startColumnU[iColumn]
1498 - numberInColumnPlus[iColumn];
1499
1500 startColumnU[iColumn] = put + numberInColumnPlus[iColumn];
1501 if (number < 50) {
1502 int *indexRow = indexRowU;
1503 CoinFactorizationDouble *element = elementU;
1504 int i = 0;
1505
1506 if ((number & 1) != 0) {
1507 element[put] = element[get];
1508 indexRow[put] = indexRow[get];
1509 i = 1;
1510 }
1511 for (; i < number; i += 2) {
1512 CoinFactorizationDouble value0 = element[get + i];
1513 CoinFactorizationDouble value1 = element[get + i + 1];
1514 int index0 = indexRow[get + i];
1515 int index1 = indexRow[get + i + 1];
1516
1517 element[put + i] = value0;
1518 element[put + i + 1] = value1;
1519 indexRow[put + i] = index0;
1520 indexRow[put + i + 1] = index1;
1521 }
1522 } else {
1523 CoinMemcpyN(&indexRowU[get], number, &indexRowU[put]);
1524 CoinMemcpyN(&elementU[get], number, &elementU[put]);
1525 }
1526 put += number;
1527 get += number;
1528 //add 2 for luck
1529 startColumnU[maximumColumnsExtra_] = put + extraNeeded + 2;
1530 if (startColumnU[maximumColumnsExtra_] > lengthAreaU_) {
1531 // get more memory
1532 #ifdef CLP_DEVELOP
1533 printf("put %d, needed %d, start %d, length %d\n",
1534 put, extraNeeded, startColumnU[maximumColumnsExtra_],
1535 lengthAreaU_);
1536 #endif
1537 return false;
1538 }
1539 } else {
1540 //take off space
1541 startColumnU[maximumColumnsExtra_] = startColumnU[last] + numberInColumn[last];
1542 }
1543 return true;
1544 }
1545
1546 // getRowSpace. Gets space for one Row with given length
1547 //may have to do compression (returns true)
1548 //also moves existing vector
getRowSpace(int iRow,int extraNeeded)1549 bool CoinFactorization::getRowSpace(int iRow,
1550 int extraNeeded)
1551 {
1552 int *numberInRow = numberInRow_.array();
1553 int number = numberInRow[iRow];
1554 int *startRowU = startRowU_.array();
1555 int space = lengthAreaU_ - startRowU[maximumRowsExtra_];
1556 int *nextRow = nextRow_.array();
1557 int *lastRow = lastRow_.array();
1558 int *indexColumnU = indexColumnU_.array();
1559
1560 if (space < extraNeeded + number + 2) {
1561 //compression
1562 int iRow = nextRow[maximumRowsExtra_];
1563 int put = 0;
1564
1565 while (iRow != maximumRowsExtra_) {
1566 //move
1567 int get = startRowU[iRow];
1568 int getEnd = startRowU[iRow] + numberInRow[iRow];
1569
1570 startRowU[iRow] = put;
1571 int i;
1572 for (i = get; i < getEnd; i++) {
1573 indexColumnU[put] = indexColumnU[i];
1574 put++;
1575 }
1576 iRow = nextRow[iRow];
1577 } /* endwhile */
1578 numberCompressions_++;
1579 startRowU[maximumRowsExtra_] = put;
1580 space = lengthAreaU_ - put;
1581 if (space < extraNeeded + number + 2) {
1582 //need more space
1583 //if we can allocate bigger then do so and copy
1584 //if not then return so code can start again
1585 status_ = -99;
1586 return false;
1587 ;
1588 }
1589 }
1590 int put = startRowU[maximumRowsExtra_];
1591 int next = nextRow[iRow];
1592 int last = lastRow[iRow];
1593
1594 //out
1595 nextRow[last] = next;
1596 lastRow[next] = last;
1597 //in at end
1598 last = lastRow[maximumRowsExtra_];
1599 nextRow[last] = iRow;
1600 lastRow[maximumRowsExtra_] = iRow;
1601 lastRow[iRow] = last;
1602 nextRow[iRow] = maximumRowsExtra_;
1603 //move
1604 int get = startRowU[iRow];
1605
1606 startRowU[iRow] = put;
1607 while (number) {
1608 number--;
1609 indexColumnU[put] = indexColumnU[get];
1610 put++;
1611 get++;
1612 } /* endwhile */
1613 //add 4 for luck
1614 startRowU[maximumRowsExtra_] = put + extraNeeded + 4;
1615 return true;
1616 }
1617
1618 #if COIN_ONE_ETA_COPY
1619 /* Reorders U so contiguous and in order (if there is space)
1620 Returns true if it could */
reorderU()1621 bool CoinFactorization::reorderU()
1622 {
1623 #if 1
1624 return false;
1625 #else
1626 if (numberRows_ != numberColumns_)
1627 return false;
1628 int *startColumnU = startColumnU_.array();
1629 int *numberInColumn = numberInColumn_.array();
1630 int *numberInColumnPlus = numberInColumnPlus_.array();
1631 int iColumn;
1632 int put = 0;
1633 for (iColumn = 0; iColumn < numberRows_; iColumn++)
1634 put += numberInColumnPlus[iColumn];
1635 int space = lengthAreaU_ - startColumnU[maximumColumnsExtra_];
1636 if (space < put) {
1637 //printf("Space %d out of %d - needed %d\n",
1638 // space,lengthAreaU_,put);
1639 return false;
1640 }
1641 int *indexRowU = indexRowU_.array();
1642 CoinFactorizationDouble *elementU = elementU_.array();
1643 int *pivotColumn = pivotColumn_.array();
1644 put = startColumnU[maximumColumnsExtra_];
1645 for (int jColumn = 0; jColumn < numberRows_; jColumn++) {
1646 iColumn = pivotColumn[jColumn];
1647 int n = numberInColumnPlus[iColumn];
1648 int getEnd = startColumnU[iColumn];
1649 int get = getEnd - n;
1650 startColumnU[iColumn] = put;
1651 numberInColumn[jColumn] = n;
1652 int i;
1653 for (i = get; i < getEnd; i++) {
1654 indexRowU[put] = indexRowU[i];
1655 elementU[put] = elementU[i];
1656 put++;
1657 }
1658 }
1659 // and pack down
1660 put = 0;
1661 for (int jColumn = 0; jColumn < numberRows_; jColumn++) {
1662 iColumn = pivotColumn[jColumn];
1663 int n = numberInColumn[jColumn];
1664 int get = startColumnU[iColumn];
1665 int getEnd = get + n;
1666 int i;
1667 for (i = get; i < getEnd; i++) {
1668 indexRowU[put] = indexRowU[i];
1669 elementU[put] = elementU[i];
1670 put++;
1671 }
1672 }
1673 put = 0;
1674 for (iColumn = 0; iColumn < numberRows_; iColumn++) {
1675 int n = numberInColumn[iColumn];
1676 startColumnU[iColumn] = put;
1677 put += n;
1678 //numberInColumnPlus[iColumn]=n;
1679 //numberInColumn[iColumn]=0; // necessary?
1680 //pivotColumn[iColumn]=iColumn;
1681 }
1682 #if 0
1683 // reset nextColumn - probably not necessary
1684 int * nextColumn = nextColumn_.array();
1685 nextColumn[maximumColumnsExtra_]=0;
1686 nextColumn[numberRows_-1] = maximumColumnsExtra_;
1687 for (iColumn=0;iColumn<numberRows_-1;iColumn++)
1688 nextColumn[iColumn]=iColumn+1;
1689 // swap arrays
1690 numberInColumn_.swap(numberInColumnPlus_);
1691 #endif
1692 //return false;
1693 return true;
1694 #endif
1695 }
1696 #endif
1697 // cleanup. End of factorization
cleanup()1698 void CoinFactorization::cleanup()
1699 {
1700 #if COIN_ONE_ETA_COPY
1701 bool compressDone = reorderU();
1702 if (!compressDone) {
1703 getColumnSpace(0, COIN_INT_MAX >> 1); //compress
1704 // swap arrays
1705 numberInColumn_.swap(numberInColumnPlus_);
1706 }
1707 #else
1708 getColumnSpace(0, COIN_INT_MAX >> 1); //compress
1709 // swap arrays
1710 numberInColumn_.swap(numberInColumnPlus_);
1711 #endif
1712 int *startColumnU = startColumnU_.array();
1713 int lastU = startColumnU[maximumColumnsExtra_];
1714
1715 //free some memory here
1716 saveColumn_.conditionalDelete();
1717 markRow_.conditionalDelete();
1718 //firstCount_.conditionalDelete() ;
1719 nextCount_.conditionalDelete();
1720 lastCount_.conditionalDelete();
1721 int *numberInRow = numberInRow_.array();
1722 int *numberInColumn = numberInColumn_.array();
1723 int *numberInColumnPlus = numberInColumnPlus_.array();
1724 //make column starts OK
1725 //for best cache behavior get in order (last pivot at bottom of space)
1726 //that will need thinking about
1727 //use nextRow for permutation (as that is what it is)
1728 int i;
1729
1730 #ifndef NDEBUG
1731 {
1732 if (numberGoodU_ < numberRows_)
1733 abort();
1734 char *mark = new char[numberRows_];
1735 memset(mark, 0, numberRows_);
1736 int *array;
1737 array = nextRow_.array();
1738 for (i = 0; i < numberRows_; i++) {
1739 int k = array[i];
1740 if (k < 0 || k >= numberRows_)
1741 printf("Bad a %d %d\n", i, k);
1742 assert(k >= 0 && k < numberRows_);
1743 if (mark[k] == 1)
1744 printf("Bad a %d %d\n", i, k);
1745 mark[k] = 1;
1746 }
1747 for (i = 0; i < numberRows_; i++) {
1748 assert(mark[i] == 1);
1749 if (mark[i] != 1)
1750 printf("Bad b %d\n", i);
1751 }
1752 delete[] mark;
1753 }
1754 #endif
1755 // swap arrays
1756 permute_.swap(nextRow_);
1757 //safety feature
1758 int *permute = permute_.array();
1759 permute[numberRows_] = 0;
1760 permuteBack_.conditionalNew(maximumRowsExtra_ + 1);
1761 int *permuteBack = permuteBack_.array();
1762 #ifdef ZEROFAULT
1763 memset(permuteBack_.array(), 'w', (maximumRowsExtra_ + 1) * sizeof(int));
1764 #endif
1765 for (i = 0; i < numberRows_; i++) {
1766 int iRow = permute[i];
1767
1768 permuteBack[iRow] = i;
1769 }
1770 //redo nextRow_
1771
1772 #ifndef NDEBUG
1773 for (i = 0; i < numberRows_; i++) {
1774 assert(permute[i] >= 0 && permute[i] < numberRows_);
1775 assert(permuteBack[i] >= 0 && permuteBack[i] < numberRows_);
1776 }
1777 #endif
1778 #if COIN_ONE_ETA_COPY
1779 if (!compressDone) {
1780 #endif
1781 // Redo total elements
1782 totalElements_ = 0;
1783 for (i = 0; i < numberColumns_; i++) {
1784 int number = numberInColumn[i];
1785 totalElements_ += number;
1786 startColumnU[i] -= number;
1787 }
1788 #if COIN_ONE_ETA_COPY
1789 }
1790 #endif
1791 int numberU = 0;
1792
1793 pivotColumnBack_.conditionalNew(maximumRowsExtra_ + 1);
1794 #ifdef ZEROFAULT
1795 memset(pivotColumnBack(), 'q', (maximumRowsExtra_ + 1) * sizeof(int));
1796 #endif
1797 const int *pivotColumn = pivotColumn_.array();
1798 int *pivotColumnB = pivotColumnBack();
1799 int *indexColumnU = indexColumnU_.array();
1800 int *startColumn = startColumnU;
1801 int *indexRowU = indexRowU_.array();
1802 CoinFactorizationDouble *elementU = elementU_.array();
1803 #if COIN_ONE_ETA_COPY
1804 if (!compressDone) {
1805 #endif
1806 for (i = 0; i < numberColumns_; i++) {
1807 int iColumn = pivotColumn[i];
1808
1809 pivotColumnB[iColumn] = i;
1810 if (iColumn >= 0) {
1811 //wanted
1812 if (numberU != iColumn) {
1813 numberInColumnPlus[iColumn] = numberU;
1814 } else {
1815 numberInColumnPlus[iColumn] = -1; //already in correct place
1816 }
1817 numberU++;
1818 }
1819 }
1820 for (i = 0; i < numberColumns_; i++) {
1821 int number = numberInColumn[i]; //always 0?
1822 int where = numberInColumnPlus[i];
1823
1824 numberInColumnPlus[i] = -1;
1825 int start = startColumnU[i];
1826
1827 while (where >= 0) {
1828 //put where it should be
1829 int numberNext = numberInColumn[where]; //always 0?
1830 int whereNext = numberInColumnPlus[where];
1831 int startNext = startColumnU[where];
1832
1833 numberInColumn[where] = number;
1834 numberInColumnPlus[where] = -1;
1835 startColumnU[where] = start;
1836 number = numberNext;
1837 where = whereNext;
1838 start = startNext;
1839 } /* endwhile */
1840 }
1841 //sort - using indexColumn
1842 CoinFillN(indexColumnU_.array(), lastU, -1);
1843 int k = 0;
1844
1845 for (i = numberSlacks_; i < numberRows_; i++) {
1846 int start = startColumn[i];
1847 int end = start + numberInColumn[i];
1848
1849 int j;
1850 for (j = start; j < end; j++) {
1851 indexColumnU[j] = k++;
1852 }
1853 }
1854 for (i = numberSlacks_; i < numberRows_; i++) {
1855 int start = startColumn[i];
1856 int end = start + numberInColumn[i];
1857
1858 int j;
1859 for (j = start; j < end; j++) {
1860 int k = indexColumnU[j];
1861 int iRow = indexRowU[j];
1862 CoinFactorizationDouble element = elementU[j];
1863
1864 while (k != -1) {
1865 int kNext = indexColumnU[k];
1866 int iRowNext = indexRowU[k];
1867 CoinFactorizationDouble elementNext = elementU[k];
1868
1869 indexColumnU[k] = -1;
1870 indexRowU[k] = iRow;
1871 elementU[k] = element;
1872 k = kNext;
1873 iRow = iRowNext;
1874 element = elementNext;
1875 } /* endwhile */
1876 }
1877 }
1878 CoinZeroN(startColumnU, numberSlacks_);
1879 k = 0;
1880 for (i = numberSlacks_; i < numberRows_; i++) {
1881 startColumnU[i] = k;
1882 k += numberInColumn[i];
1883 }
1884 maximumU_ = k;
1885 #if COIN_ONE_ETA_COPY
1886 } else {
1887 // U already OK
1888 for (i = 0; i < numberColumns_; i++) {
1889 int iColumn = pivotColumn[i];
1890 pivotColumnB[iColumn] = i;
1891 }
1892 maximumU_ = startColumnU[numberRows_ - 1] + numberInColumn[numberRows_ - 1];
1893 numberU = numberRows_;
1894 }
1895 #endif
1896 if ((messageLevel_ & 8)) {
1897 std::cout << " length of U " << totalElements_ << ", length of L " << lengthL_;
1898 if (numberDense_)
1899 std::cout << " plus " << numberDense_ * numberDense_ << " from " << numberDense_ << " dense rows";
1900 std::cout << std::endl;
1901 }
1902 // and add L and dense
1903 totalElements_ += numberDense_ * numberDense_ + lengthL_;
1904 int *nextColumn = nextColumn_.array();
1905 int *lastColumn = lastColumn_.array();
1906 // See whether to have extra copy of R
1907 #ifndef ABC_USE_COIN_FACTORIZATION
1908 if (maximumU_ > 10 * numberRows_ || numberRows_ < 200) {
1909 // NO
1910 numberInColumnPlus_.conditionalDelete();
1911 } else {
1912 #endif
1913 for (i = 0; i < numberColumns_; i++) {
1914 lastColumn[i] = i - 1;
1915 nextColumn[i] = i + 1;
1916 numberInColumnPlus[i] = 0;
1917 }
1918 nextColumn[numberColumns_ - 1] = maximumColumnsExtra_;
1919 lastColumn[maximumColumnsExtra_] = numberColumns_ - 1;
1920 nextColumn[maximumColumnsExtra_] = 0;
1921 lastColumn[0] = maximumColumnsExtra_;
1922 #ifndef ABC_USE_COIN_FACTORIZATION
1923 }
1924 #endif
1925 numberU_ = numberU;
1926 numberGoodU_ = numberU;
1927 numberL_ = numberGoodL_;
1928 #if COIN_DEBUG
1929 for (i = 0; i < numberRows_; i++) {
1930 if (permute[i] < 0) {
1931 std::cout << i << std::endl;
1932 abort();
1933 }
1934 }
1935 #endif
1936 CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
1937 for (i = numberSlacks_; i < numberU; i++) {
1938 int start = startColumnU[i];
1939 int end = start + numberInColumn[i];
1940
1941 totalElements_ += numberInColumn[i];
1942 int j;
1943
1944 for (j = start; j < end; j++) {
1945 int iRow = indexRowU[j];
1946 iRow = permute[iRow];
1947 indexRowU[j] = iRow;
1948 numberInRow[iRow]++;
1949 }
1950 }
1951 #if COIN_ONE_ETA_COPY
1952 if (numberRows_ >= COIN_ONE_ETA_COPY) {
1953 #endif
1954 //space for cross reference
1955 int lengthU = lengthAreaU_ + EXTRA_U_SPACE;
1956 convertRowToColumnU_.conditionalNew(lengthU);
1957 int *convertRowToColumn = convertRowToColumnU_.array();
1958 int j = 0;
1959 int *startRow = startRowU_.array();
1960
1961 int iRow;
1962 for (iRow = 0; iRow < numberRows_; iRow++) {
1963 startRow[iRow] = j;
1964 j += numberInRow[iRow];
1965 }
1966 int numberInU = j;
1967
1968 CoinZeroN(numberInRow_.array(), numberRows_);
1969
1970 for (i = numberSlacks_; i < numberRows_; i++) {
1971 int start = startColumnU[i];
1972 int end = start + numberInColumn[i];
1973
1974 CoinFactorizationDouble pivotValue = pivotRegion[i];
1975
1976 int j;
1977 for (j = start; j < end; j++) {
1978 int iRow = indexRowU[j];
1979 int iLook = numberInRow[iRow];
1980
1981 numberInRow[iRow] = iLook + 1;
1982 int k = startRow[iRow] + iLook;
1983
1984 indexColumnU[k] = i;
1985 convertRowToColumn[k] = j;
1986 //multiply by pivot
1987 elementU[j] *= pivotValue;
1988 }
1989 }
1990 int *nextRow = nextRow_.array();
1991 int *lastRow = lastRow_.array();
1992 for (j = 0; j < numberRows_; j++) {
1993 lastRow[j] = j - 1;
1994 nextRow[j] = j + 1;
1995 }
1996 nextRow[numberRows_ - 1] = maximumRowsExtra_;
1997 lastRow[maximumRowsExtra_] = numberRows_ - 1;
1998 nextRow[maximumRowsExtra_] = 0;
1999 lastRow[0] = maximumRowsExtra_;
2000 startRow[maximumRowsExtra_] = numberInU;
2001 #if COIN_ONE_ETA_COPY
2002 } else {
2003 // no row copy
2004 for (i = numberSlacks_; i < numberU; i++) {
2005 int start = startColumnU[i];
2006 int end = start + numberInColumn[i];
2007
2008 int j;
2009 CoinFactorizationDouble pivotValue = pivotRegion[i];
2010
2011 for (j = start; j < end; j++) {
2012 //multiply by pivot
2013 elementU[j] *= pivotValue;
2014 }
2015 }
2016 }
2017 #endif
2018
2019 int firstReal = numberRows_;
2020
2021 int *startColumnL = startColumnL_.array();
2022 int *indexRowL = indexRowL_.array();
2023 for (i = numberRows_ - 1; i >= 0; i--) {
2024 int start = startColumnL[i];
2025 int end = startColumnL[i + 1];
2026
2027 totalElements_ += end - start;
2028 if (end > start) {
2029 firstReal = i;
2030 int j;
2031 for (j = start; j < end; j++) {
2032 int iRow = indexRowL[j];
2033 iRow = permute[iRow];
2034 assert(iRow > firstReal);
2035 indexRowL[j] = iRow;
2036 }
2037 }
2038 }
2039 baseL_ = firstReal;
2040 numberL_ -= firstReal;
2041 factorElements_ = totalElements_;
2042 //can delete pivotRowL_ as not used
2043 pivotRowL_.conditionalDelete();
2044 //use L for R if room
2045 int space = lengthAreaL_ - lengthL_;
2046 int spaceUsed = lengthL_ + lengthU_;
2047
2048 int needed = (spaceUsed + numberRows_ - 1) / numberRows_;
2049
2050 needed = needed * 2 * maximumPivots_;
2051 if (needed < 2 * numberRows_) {
2052 needed = 2 * numberRows_;
2053 }
2054 if (numberInColumnPlus_.array()) {
2055 // Need double the space for R
2056 space = space / 2;
2057 startColumnR_.conditionalNew(maximumPivots_ + 1 + maximumColumnsExtra_ + 1);
2058 int *startR = startColumnR_.array() + maximumPivots_ + 1;
2059 CoinZeroN(startR, (maximumColumnsExtra_ + 1));
2060 } else {
2061 startColumnR_.conditionalNew(maximumPivots_ + 1);
2062 }
2063 #ifdef ZEROFAULT
2064 memset(startColumnR_.array(), 'z', (maximumPivots_ + 1) * sizeof(int));
2065 #endif
2066 if (space >= needed) {
2067 lengthR_ = 0;
2068 lengthAreaR_ = space;
2069 elementR_ = elementL_.array() + lengthL_;
2070 indexRowR_ = indexRowL_.array() + lengthL_;
2071 } else {
2072 lengthR_ = 0;
2073 lengthAreaR_ = space;
2074 elementR_ = elementL_.array() + lengthL_;
2075 indexRowR_ = indexRowL_.array() + lengthL_;
2076 if ((messageLevel_ & 4))
2077 std::cout << "Factorization may need some increasing area space"
2078 << std::endl;
2079 if (areaFactor_) {
2080 areaFactor_ *= 1.1;
2081 } else {
2082 areaFactor_ = 1.1;
2083 }
2084 }
2085 numberR_ = 0;
2086 }
2087 // Returns areaFactor but adjusted for dense
2088 double
adjustedAreaFactor() const2089 CoinFactorization::adjustedAreaFactor() const
2090 {
2091 double factor = areaFactor_;
2092 if (numberDense_ && areaFactor_ > 1.0) {
2093 double dense = numberDense_;
2094 dense *= dense;
2095 double withoutDense = totalElements_ - dense + 1.0;
2096 factor *= 1.0 + dense / withoutDense;
2097 }
2098 return factor;
2099 }
2100
2101 // checkConsistency. Checks that row and column copies look OK
checkConsistency()2102 void CoinFactorization::checkConsistency()
2103 {
2104 bool bad = false;
2105
2106 int iRow;
2107 int *startRowU = startRowU_.array();
2108 int *numberInRow = numberInRow_.array();
2109 int *numberInColumn = numberInColumn_.array();
2110 int *indexColumnU = indexColumnU_.array();
2111 int *indexRowU = indexRowU_.array();
2112 int *startColumnU = startColumnU_.array();
2113 for (iRow = 0; iRow < numberRows_; iRow++) {
2114 if (numberInRow[iRow]) {
2115 int startRow = startRowU[iRow];
2116 int endRow = startRow + numberInRow[iRow];
2117
2118 int j;
2119 for (j = startRow; j < endRow; j++) {
2120 int iColumn = indexColumnU[j];
2121 int startColumn = startColumnU[iColumn];
2122 int endColumn = startColumn + numberInColumn[iColumn];
2123 bool found = false;
2124
2125 int k;
2126 for (k = startColumn; k < endColumn; k++) {
2127 if (indexRowU[k] == iRow) {
2128 found = true;
2129 break;
2130 }
2131 }
2132 if (!found) {
2133 bad = true;
2134 std::cout << "row " << iRow << " column " << iColumn << " Rows" << std::endl;
2135 }
2136 }
2137 }
2138 }
2139 int iColumn;
2140 for (iColumn = 0; iColumn < numberColumns_; iColumn++) {
2141 if (numberInColumn[iColumn]) {
2142 int startColumn = startColumnU[iColumn];
2143 int endColumn = startColumn + numberInColumn[iColumn];
2144
2145 int j;
2146 for (j = startColumn; j < endColumn; j++) {
2147 int iRow = indexRowU[j];
2148 int startRow = startRowU[iRow];
2149 int endRow = startRow + numberInRow[iRow];
2150 bool found = false;
2151
2152 int k;
2153 for (k = startRow; k < endRow; k++) {
2154 if (indexColumnU[k] == iColumn) {
2155 found = true;
2156 break;
2157 }
2158 }
2159 if (!found) {
2160 bad = true;
2161 std::cout << "row " << iRow << " column " << iColumn << " Columns" << std::endl;
2162 }
2163 }
2164 }
2165 }
2166 if (bad) {
2167 abort();
2168 }
2169 }
2170 // pivotOneOtherRow. When just one other row so faster
pivotOneOtherRow(int pivotRow,int pivotColumn)2171 bool CoinFactorization::pivotOneOtherRow(int pivotRow,
2172 int pivotColumn)
2173 {
2174 int *numberInRow = numberInRow_.array();
2175 int *numberInColumn = numberInColumn_.array();
2176 int *numberInColumnPlus = numberInColumnPlus_.array();
2177 int numberInPivotRow = numberInRow[pivotRow] - 1;
2178 int *startRowU = startRowU_.array();
2179 int *startColumnU = startColumnU_.array();
2180 int startColumn = startColumnU[pivotColumn];
2181 int startRow = startRowU[pivotRow];
2182 int endRow = startRow + numberInPivotRow + 1;
2183
2184 //take out this bit of indexColumnU
2185 int *nextRow = nextRow_.array();
2186 int *lastRow = lastRow_.array();
2187 int next = nextRow[pivotRow];
2188 int last = lastRow[pivotRow];
2189
2190 nextRow[last] = next;
2191 lastRow[next] = last;
2192 nextRow[pivotRow] = numberGoodU_; //use for permute
2193 lastRow[pivotRow] = -2;
2194 numberInRow[pivotRow] = 0;
2195 //store column in L, compress in U and take column out
2196 int l = lengthL_;
2197
2198 if (l + 1 > lengthAreaL_) {
2199 //need more memory
2200 if ((messageLevel_ & 4) != 0)
2201 std::cout << "more memory needed in middle of invert" << std::endl;
2202 return false;
2203 }
2204 //l+=currentAreaL_->elementByColumn-elementL_;
2205 //int lSave=l;
2206 int *startColumnL = startColumnL_.array();
2207 CoinFactorizationDouble *elementL = elementL_.array();
2208 int *indexRowL = indexRowL_.array();
2209 startColumnL[numberGoodL_] = l; //for luck and first time
2210 numberGoodL_++;
2211 startColumnL[numberGoodL_] = l + 1;
2212 lengthL_++;
2213 CoinFactorizationDouble pivotElement;
2214 CoinFactorizationDouble otherMultiplier;
2215 int otherRow;
2216 int *saveColumn = saveColumn_.array();
2217 CoinFactorizationDouble *elementU = elementU_.array();
2218 int *indexRowU = indexRowU_.array();
2219
2220 if (indexRowU[startColumn] == pivotRow) {
2221 pivotElement = elementU[startColumn];
2222 otherMultiplier = elementU[startColumn + 1];
2223 otherRow = indexRowU[startColumn + 1];
2224 } else {
2225 pivotElement = elementU[startColumn + 1];
2226 otherMultiplier = elementU[startColumn];
2227 otherRow = indexRowU[startColumn];
2228 }
2229 int numberSave = numberInRow[otherRow];
2230 CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement;
2231
2232 CoinFactorizationDouble *pivotRegion = pivotRegion_.array();
2233 pivotRegion[numberGoodU_] = pivotMultiplier;
2234 numberInColumn[pivotColumn] = 0;
2235 otherMultiplier = otherMultiplier * pivotMultiplier;
2236 indexRowL[l] = otherRow;
2237 elementL[l] = otherMultiplier;
2238 //take out of row list
2239 int start = startRowU[otherRow];
2240 int end = start + numberSave;
2241 int where = start;
2242 int *indexColumnU = indexColumnU_.array();
2243
2244 while (indexColumnU[where] != pivotColumn) {
2245 where++;
2246 } /* endwhile */
2247 assert(where < end);
2248 end--;
2249 indexColumnU[where] = indexColumnU[end];
2250 int numberAdded = 0;
2251 int numberDeleted = 0;
2252
2253 //pack down and move to work
2254 int j;
2255 const int *nextCount = nextCount_.array();
2256 int *nextColumn = nextColumn_.array();
2257
2258 for (j = startRow; j < endRow; j++) {
2259 int iColumn = indexColumnU[j];
2260
2261 if (iColumn != pivotColumn) {
2262 int startColumn = startColumnU[iColumn];
2263 int endColumn = startColumn + numberInColumn[iColumn];
2264 int iRow = indexRowU[startColumn];
2265 CoinFactorizationDouble value = elementU[startColumn];
2266 double largest;
2267 bool foundOther = false;
2268
2269 //leave room for pivot
2270 int put = startColumn + 1;
2271 int positionLargest = -1;
2272 CoinFactorizationDouble thisPivotValue = 0.0;
2273 CoinFactorizationDouble otherElement = 0.0;
2274 CoinFactorizationDouble nextValue = elementU[put];
2275 ;
2276 int nextIRow = indexRowU[put];
2277
2278 //compress column and find largest not updated
2279 if (iRow != pivotRow) {
2280 if (iRow != otherRow) {
2281 largest = fabs(value);
2282 elementU[put] = value;
2283 indexRowU[put] = iRow;
2284 positionLargest = put;
2285 put++;
2286 int i;
2287 for (i = startColumn + 1; i < endColumn; i++) {
2288 iRow = nextIRow;
2289 value = nextValue;
2290 #ifdef ZEROFAULT
2291 // doesn't matter reading uninitialized but annoys checking
2292 if (i + 1 < endColumn) {
2293 #endif
2294 nextIRow = indexRowU[i + 1];
2295 nextValue = elementU[i + 1];
2296 #ifdef ZEROFAULT
2297 }
2298 #endif
2299 if (iRow != pivotRow) {
2300 if (iRow != otherRow) {
2301 //keep
2302 indexRowU[put] = iRow;
2303 elementU[put] = value;
2304 ;
2305 put++;
2306 } else {
2307 otherElement = value;
2308 foundOther = true;
2309 }
2310 } else {
2311 thisPivotValue = value;
2312 }
2313 }
2314 } else {
2315 otherElement = value;
2316 foundOther = true;
2317 //need to find largest
2318 largest = 0.0;
2319 int i;
2320 for (i = startColumn + 1; i < endColumn; i++) {
2321 iRow = nextIRow;
2322 value = nextValue;
2323 #ifdef ZEROFAULT
2324 // doesn't matter reading uninitialized but annoys checking
2325 if (i + 1 < endColumn) {
2326 #endif
2327 nextIRow = indexRowU[i + 1];
2328 nextValue = elementU[i + 1];
2329 #ifdef ZEROFAULT
2330 }
2331 #endif
2332 if (iRow != pivotRow) {
2333 //keep
2334 indexRowU[put] = iRow;
2335 elementU[put] = value;
2336 ;
2337 double absValue = fabs(value);
2338
2339 if (absValue > largest) {
2340 largest = absValue;
2341 positionLargest = put;
2342 }
2343 put++;
2344 } else {
2345 thisPivotValue = value;
2346 }
2347 }
2348 }
2349 } else {
2350 //need to find largest
2351 largest = 0.0;
2352 thisPivotValue = value;
2353 int i;
2354 for (i = startColumn + 1; i < endColumn; i++) {
2355 iRow = nextIRow;
2356 value = nextValue;
2357 #ifdef ZEROFAULT
2358 // doesn't matter reading uninitialized but annoys checking
2359 if (i + 1 < endColumn) {
2360 #endif
2361 nextIRow = indexRowU[i + 1];
2362 nextValue = elementU[i + 1];
2363 #ifdef ZEROFAULT
2364 }
2365 #endif
2366 if (iRow != otherRow) {
2367 //keep
2368 indexRowU[put] = iRow;
2369 elementU[put] = value;
2370 ;
2371 double absValue = fabs(value);
2372
2373 if (absValue > largest) {
2374 largest = absValue;
2375 positionLargest = put;
2376 }
2377 put++;
2378 } else {
2379 otherElement = value;
2380 foundOther = true;
2381 }
2382 }
2383 }
2384 //slot in pivot
2385 elementU[startColumn] = thisPivotValue;
2386 indexRowU[startColumn] = pivotRow;
2387 //clean up counts
2388 startColumn++;
2389 numberInColumn[iColumn] = put - startColumn;
2390 numberInColumnPlus[iColumn]++;
2391 startColumnU[iColumn]++;
2392 otherElement = otherElement - thisPivotValue * otherMultiplier;
2393 double absValue = fabs(otherElement);
2394
2395 if (absValue > zeroTolerance_) {
2396 if (!foundOther) {
2397 //have we space
2398 saveColumn[numberAdded++] = iColumn;
2399 int next = nextColumn[iColumn];
2400 int space;
2401
2402 space = startColumnU[next] - put - numberInColumnPlus[next];
2403 if (space <= 0) {
2404 //getColumnSpace also moves fixed part
2405 int number = numberInColumn[iColumn];
2406
2407 if (!getColumnSpace(iColumn, number + 1)) {
2408 return false;
2409 }
2410 //redo starts
2411 positionLargest = positionLargest + startColumnU[iColumn] - startColumn;
2412 startColumn = startColumnU[iColumn];
2413 put = startColumn + number;
2414 }
2415 }
2416 elementU[put] = otherElement;
2417 indexRowU[put] = otherRow;
2418 if (absValue > largest) {
2419 largest = absValue;
2420 positionLargest = put;
2421 }
2422 put++;
2423 } else {
2424 if (foundOther) {
2425 numberDeleted++;
2426 //take out of row list
2427 int where = start;
2428
2429 while (indexColumnU[where] != iColumn) {
2430 where++;
2431 } /* endwhile */
2432 assert(where < end);
2433 end--;
2434 indexColumnU[where] = indexColumnU[end];
2435 }
2436 }
2437 numberInColumn[iColumn] = put - startColumn;
2438 //move largest
2439 if (positionLargest >= 0) {
2440 value = elementU[positionLargest];
2441 iRow = indexRowU[positionLargest];
2442 elementU[positionLargest] = elementU[startColumn];
2443 indexRowU[positionLargest] = indexRowU[startColumn];
2444 elementU[startColumn] = value;
2445 indexRowU[startColumn] = iRow;
2446 }
2447 //linked list for column
2448 if (nextCount[iColumn + numberRows_] != -2) {
2449 //modify linked list
2450 deleteLink(iColumn + numberRows_);
2451 addLink(iColumn + numberRows_, numberInColumn[iColumn]);
2452 }
2453 }
2454 }
2455 //get space for row list
2456 next = nextRow[otherRow];
2457 int space;
2458
2459 space = startRowU[next] - end;
2460 totalElements_ += numberAdded - numberDeleted;
2461 int number = numberAdded + (end - start);
2462
2463 if (space < numberAdded) {
2464 numberInRow[otherRow] = end - start;
2465 if (!getRowSpace(otherRow, number)) {
2466 return false;
2467 }
2468 end = startRowU[otherRow] + end - start;
2469 }
2470 // do linked lists and update counts
2471 numberInRow[otherRow] = number;
2472 if (number != numberSave) {
2473 deleteLink(otherRow);
2474 addLink(otherRow, number);
2475 }
2476 for (j = 0; j < numberAdded; j++) {
2477 indexColumnU[end++] = saveColumn[j];
2478 }
2479 //modify linked list for pivots
2480 deleteLink(pivotRow);
2481 deleteLink(pivotColumn + numberRows_);
2482 return true;
2483 }
setPersistenceFlag(int flag)2484 void CoinFactorization::setPersistenceFlag(int flag)
2485 {
2486 persistenceFlag_ = flag;
2487 workArea_.setPersistence(flag, maximumRowsExtra_ + 1);
2488 workArea2_.setPersistence(flag, maximumRowsExtra_ + 1);
2489 pivotColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2490 permute_.setPersistence(flag, maximumRowsExtra_ + 1);
2491 pivotColumnBack_.setPersistence(flag, maximumRowsExtra_ + 1);
2492 permuteBack_.setPersistence(flag, maximumRowsExtra_ + 1);
2493 nextRow_.setPersistence(flag, maximumRowsExtra_ + 1);
2494 startRowU_.setPersistence(flag, maximumRowsExtra_ + 1);
2495 numberInRow_.setPersistence(flag, maximumRowsExtra_ + 1);
2496 numberInColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2497 numberInColumnPlus_.setPersistence(flag, maximumColumnsExtra_ + 1);
2498 firstCount_.setPersistence(flag, CoinMax(biggerDimension_ + 2, maximumRowsExtra_ + 1));
2499 nextCount_.setPersistence(flag, numberRows_ + numberColumns_);
2500 lastCount_.setPersistence(flag, numberRows_ + numberColumns_);
2501 nextColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2502 lastColumn_.setPersistence(flag, maximumColumnsExtra_ + 1);
2503 lastRow_.setPersistence(flag, maximumRowsExtra_ + 1);
2504 markRow_.setPersistence(flag, numberRows_);
2505 saveColumn_.setPersistence(flag, numberColumns_);
2506 indexColumnU_.setPersistence(flag, lengthAreaU_);
2507 pivotRowL_.setPersistence(flag, numberRows_ + 1);
2508 pivotRegion_.setPersistence(flag, maximumRowsExtra_ + 1);
2509 elementU_.setPersistence(flag, lengthAreaU_);
2510 indexRowU_.setPersistence(flag, lengthAreaU_);
2511 startColumnU_.setPersistence(flag, maximumColumnsExtra_ + 1);
2512 convertRowToColumnU_.setPersistence(flag, lengthAreaU_);
2513 elementL_.setPersistence(flag, lengthAreaL_);
2514 indexRowL_.setPersistence(flag, lengthAreaL_);
2515 startColumnL_.setPersistence(flag, numberRows_ + 1);
2516 startColumnR_.setPersistence(flag, maximumPivots_ + 1 + maximumColumnsExtra_ + 1);
2517 startRowL_.setPersistence(flag, 0);
2518 indexColumnL_.setPersistence(flag, 0);
2519 elementByRowL_.setPersistence(flag, 0);
2520 sparse_.setPersistence(flag, 0);
2521 }
2522 // Delete all stuff
almostDestructor()2523 void CoinFactorization::almostDestructor()
2524 {
2525 gutsOfDestructor(2);
2526 }
2527
2528 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
2529 */
2530