1 /* $Id: AbcMatrix.cpp 2385 2019-01-06 19:43:06Z unxusr $ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5
6 #include <cstdio>
7 #include "CoinPragma.hpp"
8 #include "CoinIndexedVector.hpp"
9 #include "CoinHelperFunctions.hpp"
10 #include "CoinAbcHelperFunctions.hpp"
11 #include "AbcSimplexFactorization.hpp"
12 #include "AbcPrimalColumnDantzig.hpp"
13 #include "AbcPrimalColumnSteepest.hpp"
14 #include "CoinTime.hpp"
15
16 #include "AbcSimplex.hpp"
17 #include "AbcSimplexDual.hpp"
18 // at end to get min/max!
19 #include "AbcMatrix.hpp"
20 #include "ClpMessage.hpp"
21 #ifdef INTEL_MKL
22 #include "mkl_spblas.h"
23 #endif
24 #if ABC_INSTRUMENT > 1
25 extern int abcPricing[20];
26 extern int abcPricingDense[20];
27 #endif
28 //=============================================================================
29
30 //#############################################################################
31 // Constructors / Destructor / Assignment
32 //#############################################################################
33
34 //-------------------------------------------------------------------
35 // Default Constructor
36 //-------------------------------------------------------------------
AbcMatrix()37 AbcMatrix::AbcMatrix()
38 : matrix_(NULL)
39 , model_(NULL)
40 , rowStart_(NULL)
41 , element_(NULL)
42 , column_(NULL)
43 , numberColumnBlocks_(0)
44 , numberRowBlocks_(0)
45 ,
46 #ifdef COUNT_COPY
47 countRealColumn_(NULL)
48 , countStartLarge_(NULL)
49 , countRow_(NULL)
50 , countElement_(NULL)
51 , smallestCount_(0)
52 , largestCount_(0)
53 ,
54 #endif
55 startFraction_(0.0)
56 , endFraction_(1.0)
57 , savedBestDj_(0.0)
58 , originalWanted_(0)
59 , currentWanted_(0)
60 , savedBestSequence_(-1)
61 , minimumObjectsScan_(-1)
62 , minimumGoodReducedCosts_(-1)
63 {
64 }
65
66 //-------------------------------------------------------------------
67 // Copy constructor
68 //-------------------------------------------------------------------
AbcMatrix(const AbcMatrix & rhs)69 AbcMatrix::AbcMatrix(const AbcMatrix &rhs)
70 {
71 #ifndef COIN_SPARSE_MATRIX
72 matrix_ = new CoinPackedMatrix(*(rhs.matrix_), -1, -1);
73 #else
74 matrix_ = new CoinPackedMatrix(*(rhs.matrix_), -0, -0);
75 #endif
76 model_ = rhs.model_;
77 rowStart_ = NULL;
78 element_ = NULL;
79 column_ = NULL;
80 #ifdef COUNT_COPY
81 countRealColumn_ = NULL;
82 countStartLarge_ = NULL;
83 countRow_ = NULL;
84 countElement_ = NULL;
85 #endif
86 numberColumnBlocks_ = rhs.numberColumnBlocks_;
87 CoinAbcMemcpy(startColumnBlock_, rhs.startColumnBlock_, numberColumnBlocks_ + 1);
88 numberRowBlocks_ = rhs.numberRowBlocks_;
89 if (numberRowBlocks_) {
90 assert(model_);
91 int numberRows = model_->numberRows();
92 int numberElements = matrix_->getNumElements();
93 memcpy(blockStart_, rhs.blockStart_, sizeof(blockStart_));
94 rowStart_ = CoinCopyOfArray(rhs.rowStart_, numberRows * (numberRowBlocks_ + 2));
95 element_ = CoinCopyOfArray(rhs.element_, numberElements);
96 column_ = CoinCopyOfArray(rhs.column_, numberElements);
97 #ifdef COUNT_COPY
98 smallestCount_ = rhs.smallestCount_;
99 largestCount_ = rhs.largestCount_;
100 int numberColumns = model_->numberColumns();
101 countRealColumn_ = CoinCopyOfArray(rhs.countRealColumn_, numberColumns);
102 memcpy(countStart_, rhs.countStart_, reinterpret_cast< char * >(&countRealColumn_) - reinterpret_cast< char * >(countStart_));
103 int numberLarge = numberColumns - countStart_[MAX_COUNT];
104 countStartLarge_ = CoinCopyOfArray(rhs.countStartLarge_, numberLarge + 1);
105 numberElements = countStartLarge_[numberLarge];
106 countElement_ = CoinCopyOfArray(rhs.countElement_, numberElements);
107 countRow_ = CoinCopyOfArray(rhs.countRow_, numberElements);
108 #endif
109 }
110 }
111
AbcMatrix(const CoinPackedMatrix & rhs)112 AbcMatrix::AbcMatrix(const CoinPackedMatrix &rhs)
113 {
114 #ifndef COIN_SPARSE_MATRIX
115 matrix_ = new CoinPackedMatrix(rhs, -1, -1);
116 #else
117 matrix_ = new CoinPackedMatrix(rhs, -0, -0);
118 #endif
119 matrix_->cleanMatrix();
120 model_ = NULL;
121 rowStart_ = NULL;
122 element_ = NULL;
123 column_ = NULL;
124 #ifdef COUNT_COPY
125 countRealColumn_ = NULL;
126 countStartLarge_ = NULL;
127 countRow_ = NULL;
128 countElement_ = NULL;
129 smallestCount_ = 0;
130 largestCount_ = 0;
131 #endif
132 numberColumnBlocks_ = 1;
133 startColumnBlock_[0] = 0;
134 startColumnBlock_[1] = 0;
135 numberRowBlocks_ = 0;
136 startFraction_ = 0;
137 endFraction_ = 1.0;
138 savedBestDj_ = 0;
139 originalWanted_ = 0;
140 currentWanted_ = 0;
141 savedBestSequence_ = -1;
142 minimumObjectsScan_ = -1;
143 minimumGoodReducedCosts_ = -1;
144 }
145 #ifdef ABC_SPRINT
146 /* Subset constructor (without gaps). */
AbcMatrix(const AbcMatrix & wholeMatrix,int numberRows,const int * whichRows,int numberColumns,const int * whichColumns)147 AbcMatrix::AbcMatrix(const AbcMatrix &wholeMatrix,
148 int numberRows, const int *whichRows,
149 int numberColumns, const int *whichColumns)
150 {
151 #ifndef COIN_SPARSE_MATRIX
152 matrix_ = new CoinPackedMatrix(*wholeMatrix.matrix_, numberRows, whichRows,
153 numberColumns, whichColumns);
154 #else
155 matrix_ = new CoinPackedMatrix(rhs, -0, -0);
156 abort();
157 #endif
158 matrix_->cleanMatrix();
159 model_ = NULL;
160 rowStart_ = NULL;
161 element_ = NULL;
162 column_ = NULL;
163 #ifdef COUNT_COPY
164 countRealColumn_ = NULL;
165 countStartLarge_ = NULL;
166 countRow_ = NULL;
167 countElement_ = NULL;
168 smallestCount_ = 0;
169 largestCount_ = 0;
170 #endif
171 numberColumnBlocks_ = 1;
172 startColumnBlock_[0] = 0;
173 startColumnBlock_[1] = 0;
174 numberRowBlocks_ = 0;
175 startFraction_ = 0;
176 endFraction_ = 1.0;
177 savedBestDj_ = 0;
178 originalWanted_ = 0;
179 currentWanted_ = 0;
180 savedBestSequence_ = -1;
181 minimumObjectsScan_ = -1;
182 minimumGoodReducedCosts_ = -1;
183 }
184 #endif
185 //-------------------------------------------------------------------
186 // Destructor
187 //-------------------------------------------------------------------
~AbcMatrix()188 AbcMatrix::~AbcMatrix()
189 {
190 delete matrix_;
191 delete[] rowStart_;
192 delete[] element_;
193 delete[] column_;
194 #ifdef COUNT_COPY
195 delete[] countRealColumn_;
196 delete[] countStartLarge_;
197 delete[] countRow_;
198 delete[] countElement_;
199 #endif
200 }
201
202 //----------------------------------------------------------------
203 // Assignment operator
204 //-------------------------------------------------------------------
205 AbcMatrix &
operator =(const AbcMatrix & rhs)206 AbcMatrix::operator=(const AbcMatrix &rhs)
207 {
208 if (this != &rhs) {
209 delete matrix_;
210 #ifndef COIN_SPARSE_MATRIX
211 matrix_ = new CoinPackedMatrix(*(rhs.matrix_));
212 #else
213 matrix_ = new CoinPackedMatrix(*(rhs.matrix_), -0, -0);
214 #endif
215 model_ = rhs.model_;
216 delete[] rowStart_;
217 delete[] element_;
218 delete[] column_;
219 #ifdef COUNT_COPY
220 delete[] countRealColumn_;
221 delete[] countStartLarge_;
222 delete[] countRow_;
223 delete[] countElement_;
224 #endif
225 rowStart_ = NULL;
226 element_ = NULL;
227 column_ = NULL;
228 #ifdef COUNT_COPY
229 countRealColumn_ = NULL;
230 countStartLarge_ = NULL;
231 countRow_ = NULL;
232 countElement_ = NULL;
233 #endif
234 numberColumnBlocks_ = rhs.numberColumnBlocks_;
235 CoinAbcMemcpy(startColumnBlock_, rhs.startColumnBlock_, numberColumnBlocks_ + 1);
236 numberRowBlocks_ = rhs.numberRowBlocks_;
237 if (numberRowBlocks_) {
238 assert(model_);
239 int numberRows = model_->numberRows();
240 int numberElements = matrix_->getNumElements();
241 memcpy(blockStart_, rhs.blockStart_, sizeof(blockStart_));
242 rowStart_ = CoinCopyOfArray(rhs.rowStart_, numberRows * (numberRowBlocks_ + 2));
243 element_ = CoinCopyOfArray(rhs.element_, numberElements);
244 column_ = CoinCopyOfArray(rhs.column_, numberElements);
245 #ifdef COUNT_COPY
246 smallestCount_ = rhs.smallestCount_;
247 largestCount_ = rhs.largestCount_;
248 int numberColumns = model_->numberColumns();
249 countRealColumn_ = CoinCopyOfArray(rhs.countRealColumn_, numberColumns);
250 memcpy(countStart_, rhs.countStart_, reinterpret_cast< char * >(&countRealColumn_) - reinterpret_cast< char * >(countStart_));
251 int numberLarge = numberColumns - countStart_[MAX_COUNT];
252 countStartLarge_ = CoinCopyOfArray(rhs.countStartLarge_, numberLarge + 1);
253 numberElements = countStartLarge_[numberLarge];
254 countElement_ = CoinCopyOfArray(rhs.countElement_, numberElements);
255 countRow_ = CoinCopyOfArray(rhs.countRow_, numberElements);
256 #endif
257 }
258 startFraction_ = rhs.startFraction_;
259 endFraction_ = rhs.endFraction_;
260 savedBestDj_ = rhs.savedBestDj_;
261 originalWanted_ = rhs.originalWanted_;
262 currentWanted_ = rhs.currentWanted_;
263 savedBestSequence_ = rhs.savedBestSequence_;
264 minimumObjectsScan_ = rhs.minimumObjectsScan_;
265 minimumGoodReducedCosts_ = rhs.minimumGoodReducedCosts_;
266 }
267 return *this;
268 }
269 // Sets model
setModel(AbcSimplex * model)270 void AbcMatrix::setModel(AbcSimplex *model)
271 {
272 model_ = model;
273 int numberColumns = model_->numberColumns();
274 bool needExtension = numberColumns > matrix_->getNumCols();
275 if (needExtension) {
276 CoinBigIndex lastElement = matrix_->getNumElements();
277 matrix_->reserve(numberColumns, lastElement, true);
278 CoinBigIndex *columnStart = matrix_->getMutableVectorStarts();
279 for (int i = numberColumns; i >= 0; i--) {
280 if (columnStart[i] == 0)
281 columnStart[i] = lastElement;
282 else
283 break;
284 }
285 assert(lastElement == columnStart[numberColumns]);
286 }
287 }
288 /* Returns a new matrix in reverse order without gaps */
289 CoinPackedMatrix *
reverseOrderedCopy() const290 AbcMatrix::reverseOrderedCopy() const
291 {
292 CoinPackedMatrix *matrix = new CoinPackedMatrix();
293 matrix->setExtraGap(0.0);
294 matrix->setExtraMajor(0.0);
295 matrix->reverseOrderedCopyOf(*matrix_);
296 return matrix;
297 }
298 /// returns number of elements in column part of basis,
299 CoinBigIndex
countBasis(const int * whichColumn,int & numberColumnBasic)300 AbcMatrix::countBasis(const int *whichColumn,
301 int &numberColumnBasic)
302 {
303 const int *COIN_RESTRICT columnLength = matrix_->getVectorLengths();
304 CoinBigIndex numberElements = 0;
305 int numberRows = model_->numberRows();
306 // just count - can be over so ignore zero problem
307 for (int i = 0; i < numberColumnBasic; i++) {
308 int iColumn = whichColumn[i] - numberRows;
309 numberElements += columnLength[iColumn];
310 }
311 return numberElements;
312 }
fillBasis(const int * COIN_RESTRICT whichColumn,int & numberColumnBasic,int * COIN_RESTRICT indexRowU,int * COIN_RESTRICT start,int * COIN_RESTRICT rowCount,int * COIN_RESTRICT columnCount,CoinFactorizationDouble * COIN_RESTRICT elementU)313 void AbcMatrix::fillBasis(const int *COIN_RESTRICT whichColumn,
314 int &numberColumnBasic,
315 int *COIN_RESTRICT indexRowU,
316 int *COIN_RESTRICT start,
317 int *COIN_RESTRICT rowCount,
318 int *COIN_RESTRICT columnCount,
319 CoinFactorizationDouble *COIN_RESTRICT elementU)
320 {
321 const int *COIN_RESTRICT columnLength = matrix_->getVectorLengths();
322 CoinBigIndex numberElements = start[0];
323 // fill
324 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts();
325 const int *COIN_RESTRICT row = matrix_->getIndices();
326 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
327 int numberRows = model_->numberRows();
328 for (int i = 0; i < numberColumnBasic; i++) {
329 int iColumn = whichColumn[i] - numberRows;
330 int length = columnLength[iColumn];
331 CoinBigIndex startThis = columnStart[iColumn];
332 columnCount[i] = length;
333 CoinBigIndex endThis = startThis + length;
334 for (CoinBigIndex j = startThis; j < endThis; j++) {
335 int iRow = row[j];
336 indexRowU[numberElements] = iRow;
337 rowCount[iRow]++;
338 assert(elementByColumn[j]);
339 elementU[numberElements++] = elementByColumn[j];
340 }
341 start[i + 1] = numberElements;
342 }
343 }
344 #ifdef ABC_LONG_FACTORIZATION
fillBasis(const int * COIN_RESTRICT whichColumn,int & numberColumnBasic,int * COIN_RESTRICT indexRowU,int * COIN_RESTRICT start,int * COIN_RESTRICT rowCount,int * COIN_RESTRICT columnCount,long double * COIN_RESTRICT elementU)345 void AbcMatrix::fillBasis(const int *COIN_RESTRICT whichColumn,
346 int &numberColumnBasic,
347 int *COIN_RESTRICT indexRowU,
348 int *COIN_RESTRICT start,
349 int *COIN_RESTRICT rowCount,
350 int *COIN_RESTRICT columnCount,
351 long double *COIN_RESTRICT elementU)
352 {
353 const int *COIN_RESTRICT columnLength = matrix_->getVectorLengths();
354 CoinBigIndex numberElements = start[0];
355 // fill
356 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts();
357 const int *COIN_RESTRICT row = matrix_->getIndices();
358 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
359 int numberRows = model_->numberRows();
360 for (int i = 0; i < numberColumnBasic; i++) {
361 int iColumn = whichColumn[i] - numberRows;
362 int length = columnLength[iColumn];
363 CoinBigIndex startThis = columnStart[iColumn];
364 columnCount[i] = length;
365 CoinBigIndex endThis = startThis + length;
366 for (CoinBigIndex j = startThis; j < endThis; j++) {
367 int iRow = row[j];
368 indexRowU[numberElements] = iRow;
369 rowCount[iRow]++;
370 assert(elementByColumn[j]);
371 elementU[numberElements++] = elementByColumn[j];
372 }
373 start[i + 1] = numberElements;
374 }
375 }
376 #endif
377 #if 0
378 /// Move largest in column to beginning
379 void
380 AbcMatrix::moveLargestToStart()
381 {
382 // get matrix data pointers
383 int * COIN_RESTRICT row = matrix_->getMutableIndices();
384 const CoinBigIndex * COIN_RESTRICT columnStart = matrix_->getVectorStarts();
385 double * COIN_RESTRICT elementByColumn = matrix_->getMutableElements();
386 int numberColumns=model_->numberColumns();
387 CoinBigIndex start = 0;
388 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
389 CoinBigIndex end = columnStart[iColumn+1];
390 double largest=0.0;
391 int position=-1;
392 for (CoinBigIndex j = start; j < end; j++) {
393 double value = fabs(elementByColumn[j]);
394 if (value>largest) {
395 largest=value;
396 position=j;
397 }
398 }
399 assert (position>=0); // ? empty column
400 if (position>start) {
401 double value=elementByColumn[start];
402 elementByColumn[start]=elementByColumn[position];
403 elementByColumn[position]=value;
404 int iRow=row[start];
405 row[start]=row[position];
406 row[position]=iRow;
407 }
408 start=end;
409 }
410 }
411 #endif
412 // Creates row copy
createRowCopy()413 void AbcMatrix::createRowCopy()
414 {
415 #if ABC_PARALLEL
416 if (model_->parallelMode() == 0)
417 #endif
418 numberRowBlocks_ = 1;
419 #if ABC_PARALLEL
420 else
421 numberRowBlocks_ = CoinMin(NUMBER_ROW_BLOCKS, model_->numberCpus());
422 #endif
423 int maximumRows = model_->maximumAbcNumberRows();
424 int numberRows = model_->numberRows();
425 int numberColumns = model_->numberColumns();
426 int numberElements = matrix_->getNumElements();
427 assert(!rowStart_);
428 char *whichBlock_ = new char[numberColumns];
429 rowStart_ = new CoinBigIndex[numberRows * (numberRowBlocks_ + 2)];
430 element_ = new double[numberElements];
431 column_ = new int[numberElements];
432 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts();
433 memset(blockStart_, 0, sizeof(blockStart_));
434 int ecount[10];
435 assert(numberRowBlocks_ < 16);
436 CoinAbcMemset0(ecount, 10);
437 // allocate to blocks (put a bit less in first as will be dealing with slacks) LATER
438 CoinBigIndex start = 0;
439 int block = 0;
440 CoinBigIndex work = (2 * numberColumns + matrix_->getNumElements() + numberRowBlocks_ - 1) / numberRowBlocks_;
441 CoinBigIndex thisWork = work;
442 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
443 CoinBigIndex end = columnStart[iColumn + 1];
444 assert(block >= 0 && block < numberRowBlocks_);
445 whichBlock_[iColumn] = static_cast< char >(block);
446 thisWork -= 2 + end - start;
447 ecount[block] += end - start;
448 start = end;
449 blockStart_[block]++;
450 if (thisWork <= 0) {
451 block++;
452 thisWork = work;
453 }
454 }
455 #if 0
456 printf("Blocks ");
457 for (int i=0;i<numberRowBlocks_;i++)
458 printf("(%d %d) ",blockStart_[i],ecount[i]);
459 printf("\n");
460 #endif
461 start = 0;
462 for (int i = 0; i < numberRowBlocks_; i++) {
463 int next = start + blockStart_[i];
464 blockStart_[i] = start;
465 start = next;
466 }
467 blockStart_[numberRowBlocks_] = start;
468 assert(start == numberColumns);
469 const int *COIN_RESTRICT row = matrix_->getIndices();
470 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
471 // counts
472 CoinAbcMemset0(rowStart_, numberRows * (numberRowBlocks_ + 2));
473 int *COIN_RESTRICT last = rowStart_ + numberRows * (numberRowBlocks_ + 1);
474 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
475 int block = whichBlock_[iColumn];
476 blockStart_[block]++;
477 int base = (block + 1) * numberRows;
478 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) {
479 int iRow = row[j];
480 rowStart_[base + iRow]++;
481 last[iRow]++;
482 }
483 }
484 // back to real starts
485 for (int iBlock = numberRowBlocks_ - 1; iBlock >= 0; iBlock--)
486 blockStart_[iBlock + 1] = blockStart_[iBlock];
487 blockStart_[0] = 0;
488 CoinBigIndex put = 0;
489 for (int iRow = 1; iRow < numberRows; iRow++) {
490 int n = last[iRow - 1];
491 last[iRow - 1] = put;
492 put += n;
493 rowStart_[iRow] = put;
494 }
495 int n = last[numberRows - 1];
496 last[numberRows - 1] = put;
497 put += n;
498 assert(put == numberElements);
499 //last[numberRows-1]=put;
500 // starts
501 int base = 0;
502 for (int iBlock = 0; iBlock < numberRowBlocks_; iBlock++) {
503 for (int iRow = 0; iRow < numberRows; iRow++) {
504 rowStart_[base + numberRows + iRow] += rowStart_[base + iRow];
505 }
506 base += numberRows;
507 }
508 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
509 int block = whichBlock_[iColumn];
510 int where = blockStart_[block];
511 blockStart_[block]++;
512 int base = block * numberRows;
513 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) {
514 int iRow = row[j];
515 CoinBigIndex put = rowStart_[base + iRow];
516 rowStart_[base + iRow]++;
517 column_[put] = where + maximumRows;
518 element_[put] = elementByColumn[j];
519 }
520 }
521 // back to real starts etc
522 base = numberRows * numberRowBlocks_;
523 for (int iBlock = numberRowBlocks_ - 1; iBlock >= 0; iBlock--) {
524 blockStart_[iBlock + 1] = blockStart_[iBlock] + maximumRows;
525 CoinAbcMemcpy(rowStart_ + base, rowStart_ + base - numberRows, numberRows);
526 base -= numberRows;
527 }
528 blockStart_[0] = 0; //maximumRows;
529 delete[] whichBlock_;
530 // and move
531 CoinAbcMemcpy(rowStart_, last, numberRows);
532 // All in useful
533 CoinAbcMemcpy(rowStart_ + (numberRowBlocks_ + 1) * numberRows,
534 rowStart_ + (numberRowBlocks_)*numberRows, numberRows);
535 #ifdef COUNT_COPY
536 // now blocked by element count
537 countRealColumn_ = new int[numberColumns];
538 int counts[2 * MAX_COUNT];
539 memset(counts, 0, sizeof(counts));
540 //memset(countFirst_,0,sizeof(countFirst_));
541 int numberLarge = 0;
542 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
543 int n = columnStart[iColumn + 1] - columnStart[iColumn];
544 if (n < MAX_COUNT)
545 counts[n]++;
546 else
547 numberLarge++;
548 }
549 CoinBigIndex numberExtra = 3; // for alignment
550 #define SMALL_COUNT 1
551 for (int i = 0; i < MAX_COUNT; i++) {
552 int n = counts[i];
553 if (n >= SMALL_COUNT) {
554 n &= 3;
555 int extra = (4 - n) & 3;
556 numberExtra += i * extra;
557 } else {
558 // treat as large
559 numberLarge += n;
560 }
561 }
562 countElement_ = new double[numberElements + numberExtra];
563 countRow_ = new int[numberElements + numberExtra];
564 countStartLarge_ = new CoinBigIndex[numberLarge + 1];
565 countStartLarge_[numberLarge] = numberElements + numberExtra;
566 //return;
567 CoinInt64 xx = reinterpret_cast< CoinInt64 >(countElement_);
568 int iBottom = static_cast< int >(xx & 31);
569 int offset = iBottom >> 3;
570 CoinBigIndex firstElementLarge = 0;
571 if (offset)
572 firstElementLarge = 4 - offset;
573 //countStart_[0]=firstElementLarge;
574 int positionLarge = 0;
575 smallestCount_ = 0;
576 largestCount_ = 0;
577 for (int i = 0; i < MAX_COUNT; i++) {
578 int n = counts[i];
579 countFirst_[i] = positionLarge;
580 countStart_[i] = firstElementLarge;
581 if (n >= SMALL_COUNT) {
582 counts[i + MAX_COUNT] = 1;
583 if (smallestCount_ == 0)
584 smallestCount_ = i;
585 largestCount_ = i;
586 positionLarge += n;
587 firstElementLarge += n * i;
588 n &= 3;
589 int extra = (4 - n) & 3;
590 firstElementLarge += i * extra;
591 }
592 counts[i] = 0;
593 }
594 largestCount_++;
595 countFirst_[MAX_COUNT] = positionLarge;
596 countStart_[MAX_COUNT] = firstElementLarge;
597 numberLarge = 0;
598 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
599 CoinBigIndex start = columnStart[iColumn];
600 int n = columnStart[iColumn + 1] - start;
601 CoinBigIndex put;
602 int position;
603 if (n < MAX_COUNT && counts[MAX_COUNT + n] != 0) {
604 int iWhich = counts[n];
605 position = countFirst_[n] + iWhich;
606 int iBlock4 = iWhich & (~3);
607 iWhich &= 3;
608 put = countStart_[n] + iBlock4 * n;
609 put += iWhich;
610 counts[n]++;
611 for (int i = 0; i < n; i++) {
612 countRow_[put] = row[start + i];
613 countElement_[put] = elementByColumn[start + i];
614 put += 4;
615 }
616 } else {
617 position = positionLarge + numberLarge;
618 put = firstElementLarge;
619 countStartLarge_[numberLarge] = put;
620 firstElementLarge += n;
621 numberLarge++;
622 CoinAbcMemcpy(countRow_ + put, row + start, n);
623 CoinAbcMemcpy(countElement_ + put, elementByColumn + start, n);
624 }
625 countRealColumn_[position] = iColumn + maximumRows;
626 }
627 countStartLarge_[numberLarge] = firstElementLarge;
628 assert(firstElementLarge <= numberElements + numberExtra);
629 #endif
630 }
631 // Make all useful
makeAllUseful(CoinIndexedVector &)632 void AbcMatrix::makeAllUseful(CoinIndexedVector & /*spare*/)
633 {
634 int numberRows = model_->numberRows();
635 CoinBigIndex *COIN_RESTRICT rowEnd = rowStart_ + numberRows;
636 const CoinBigIndex *COIN_RESTRICT rowReallyEnd = rowStart_ + 2 * numberRows;
637 for (int iRow = 0; iRow < numberRows; iRow++) {
638 rowEnd[iRow] = rowReallyEnd[iRow];
639 }
640 }
641 #define SQRT_ARRAY
642 // Creates scales for column copy (rowCopy in model may be modified)
scale(int numberAlreadyScaled)643 void AbcMatrix::scale(int numberAlreadyScaled)
644 {
645 int numberRows = model_->numberRows();
646 bool inBranchAndBound = (model_->specialOptions(), 0x1000000) != 0;
647 bool doScaling = numberAlreadyScaled >= 0;
648 if (!doScaling)
649 numberAlreadyScaled = 0;
650 if (numberAlreadyScaled == numberRows)
651 return; // no need to do anything
652 int numberColumns = model_->numberColumns();
653 double *COIN_RESTRICT rowScale = model_->rowScale2();
654 double *COIN_RESTRICT inverseRowScale = model_->inverseRowScale2();
655 double *COIN_RESTRICT columnScale = model_->columnScale2();
656 double *COIN_RESTRICT inverseColumnScale = model_->inverseColumnScale2();
657 // we are going to mark bits we are interested in
658 int whichArray = model_->getAvailableArrayPublic();
659 char *COIN_RESTRICT usefulColumn = reinterpret_cast< char * >(model_->usefulArray(whichArray)->getIndices());
660 memset(usefulColumn, 1, numberColumns);
661 const double *COIN_RESTRICT rowLower = model_->rowLower();
662 const double *COIN_RESTRICT rowUpper = model_->rowUpper();
663 const double *COIN_RESTRICT columnLower = model_->columnLower();
664 const double *COIN_RESTRICT columnUpper = model_->columnUpper();
665 //#define LEAVE_FIXED
666 // mark empty and fixed columns
667 // get matrix data pointers
668 const int *COIN_RESTRICT row = matrix_->getIndices();
669 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts();
670 double *COIN_RESTRICT elementByColumn = matrix_->getMutableElements();
671 CoinPackedMatrix *COIN_RESTRICT rowCopy = reverseOrderedCopy();
672 const int *column = rowCopy->getIndices();
673 const CoinBigIndex *COIN_RESTRICT rowStart = rowCopy->getVectorStarts();
674 const double *COIN_RESTRICT element = rowCopy->getElements();
675 assert(numberAlreadyScaled >= 0 && numberAlreadyScaled < numberRows);
676 #ifndef LEAVE_FIXED
677 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
678 if (columnUpper[iColumn] == columnLower[iColumn])
679 usefulColumn[iColumn] = 0;
680 }
681 #endif
682 double overallLargest = -1.0e-20;
683 double overallSmallest = 1.0e20;
684 if (!numberAlreadyScaled) {
685 // may be redundant
686 CoinFillN(rowScale, numberRows, 1.0);
687 CoinFillN(columnScale, numberColumns, 1.0);
688 CoinBigIndex start = 0;
689 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
690 CoinBigIndex end = columnStart[iColumn + 1];
691 if (usefulColumn[iColumn]) {
692 if (end > start) {
693 for (CoinBigIndex j = start; j < end; j++) {
694 double value = fabs(elementByColumn[j]);
695 overallLargest = CoinMax(overallLargest, value);
696 overallSmallest = CoinMin(overallSmallest, value);
697 }
698 } else {
699 usefulColumn[iColumn] = 0;
700 }
701 }
702 start = end;
703 }
704 } else {
705 CoinBigIndex start = rowStart[numberAlreadyScaled];
706 for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) {
707 rowScale[iRow] = 1.0;
708 CoinBigIndex end = rowStart[iRow + 1];
709 for (CoinBigIndex j = start; j < end; j++) {
710 int iColumn = column[j];
711 if (usefulColumn[iColumn]) {
712 double value = fabs(elementByColumn[j]) * columnScale[iColumn];
713 overallLargest = CoinMax(overallLargest, value);
714 overallSmallest = CoinMin(overallSmallest, value);
715 }
716 }
717 }
718 }
719 if ((overallSmallest >= 0.5 && overallLargest <= 2.0) || !doScaling) {
720 //printf("no scaling\n");
721 delete rowCopy;
722 model_->clearArraysPublic(whichArray);
723 CoinFillN(inverseRowScale + numberAlreadyScaled, numberRows - numberAlreadyScaled, 1.0);
724 if (!numberAlreadyScaled)
725 CoinFillN(inverseColumnScale, numberColumns, 1.0);
726 //moveLargestToStart();
727 return;
728 }
729 // need to scale
730 double largest;
731 double smallest;
732 int scalingMethod = model_->scalingFlag();
733 if (scalingMethod == 4) {
734 // As auto
735 scalingMethod = 3;
736 } else if (scalingMethod == 5) {
737 // As geometric
738 scalingMethod = 2;
739 }
740 double savedOverallRatio = 0.0;
741 double tolerance = 5.0 * model_->primalTolerance();
742 bool finished = false;
743 // if scalingMethod 3 then may change
744 bool extraDetails = (model_->logLevel() > 2);
745 bool secondTime = false;
746 while (!finished) {
747 int numberPass = !numberAlreadyScaled ? 3 : 1;
748 overallLargest = -1.0e-20;
749 overallSmallest = 1.0e20;
750 if (!secondTime) {
751 secondTime = true;
752 } else {
753 CoinFillN(rowScale, numberRows, 1.0);
754 CoinFillN(columnScale, numberColumns, 1.0);
755 }
756 if (scalingMethod == 1 || scalingMethod == 3) {
757 // Maximum in each row
758 for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) {
759 largest = 1.0e-10;
760 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow + 1]; j++) {
761 int iColumn = column[j];
762 if (usefulColumn[iColumn]) {
763 double value = fabs(element[j]);
764 largest = CoinMax(largest, value);
765 assert(largest < 1.0e40);
766 }
767 }
768 rowScale[iRow] = 1.0 / largest;
769 #ifdef COIN_DEVELOP
770 if (extraDetails) {
771 overallLargest = CoinMax(overallLargest, largest);
772 overallSmallest = CoinMin(overallSmallest, largest);
773 }
774 #endif
775 }
776 } else {
777 while (numberPass) {
778 overallLargest = 0.0;
779 overallSmallest = 1.0e50;
780 numberPass--;
781 // Geometric mean on row scales
782 for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) {
783 largest = 1.0e-50;
784 smallest = 1.0e50;
785 for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow + 1]; j++) {
786 int iColumn = column[j];
787 if (usefulColumn[iColumn]) {
788 double value = fabs(element[j]);
789 value *= columnScale[iColumn];
790 largest = CoinMax(largest, value);
791 smallest = CoinMin(smallest, value);
792 }
793 }
794 #ifdef SQRT_ARRAY
795 rowScale[iRow] = smallest * largest;
796 #else
797 rowScale[iRow] = 1.0 / sqrt(smallest * largest);
798 #endif
799 if (extraDetails) {
800 overallLargest = CoinMax(largest * rowScale[iRow], overallLargest);
801 overallSmallest = CoinMin(smallest * rowScale[iRow], overallSmallest);
802 }
803 }
804 if (model_->scalingFlag() == 5)
805 break; // just scale rows
806 #ifdef SQRT_ARRAY
807 CoinAbcInverseSqrts(rowScale, numberRows);
808 #endif
809 if (!inBranchAndBound)
810 model_->messageHandler()->message(CLP_PACKEDSCALE_WHILE, *model_->messagesPointer())
811 << overallSmallest
812 << overallLargest
813 << CoinMessageEol;
814 // skip last column round
815 if (numberPass == 1)
816 break;
817 // Geometric mean on column scales
818 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
819 if (usefulColumn[iColumn]) {
820 largest = 1.0e-50;
821 smallest = 1.0e50;
822 for (CoinBigIndex j = columnStart[iColumn];
823 j < columnStart[iColumn + 1]; j++) {
824 int iRow = row[j];
825 double value = fabs(elementByColumn[j]);
826 value *= rowScale[iRow];
827 largest = CoinMax(largest, value);
828 smallest = CoinMin(smallest, value);
829 }
830 #ifdef SQRT_ARRAY
831 columnScale[iColumn] = smallest * largest;
832 #else
833 columnScale[iColumn] = 1.0 / sqrt(smallest * largest);
834 #endif
835 }
836 }
837 #ifdef SQRT_ARRAY
838 CoinAbcInverseSqrts(columnScale, numberColumns);
839 #endif
840 }
841 }
842 // If ranges will make horrid then scale
843 for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) {
844 double difference = rowUpper[iRow] - rowLower[iRow];
845 double scaledDifference = difference * rowScale[iRow];
846 if (scaledDifference > tolerance && scaledDifference < 1.0e-4) {
847 // make gap larger
848 rowScale[iRow] *= 1.0e-4 / scaledDifference;
849 rowScale[iRow] = CoinMax(1.0e-10, CoinMin(1.0e10, rowScale[iRow]));
850 //printf("Row %d difference %g scaled diff %g => %g\n",iRow,difference,
851 // scaledDifference,difference*rowScale[iRow]);
852 }
853 }
854 // final pass to scale columns so largest is reasonable
855 // See what smallest will be if largest is 1.0
856 if (model_->scalingFlag() != 5) {
857 overallSmallest = 1.0e50;
858 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
859 if (usefulColumn[iColumn]) {
860 largest = 1.0e-20;
861 smallest = 1.0e50;
862 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) {
863 int iRow = row[j];
864 double value = fabs(elementByColumn[j] * rowScale[iRow]);
865 largest = CoinMax(largest, value);
866 smallest = CoinMin(smallest, value);
867 }
868 if (overallSmallest * largest > smallest)
869 overallSmallest = smallest / largest;
870 }
871 }
872 }
873 if (scalingMethod == 1 || scalingMethod == 2) {
874 finished = true;
875 } else if (savedOverallRatio == 0.0 && scalingMethod != 4) {
876 savedOverallRatio = overallSmallest;
877 scalingMethod = 4;
878 } else {
879 assert(scalingMethod == 4);
880 if (overallSmallest > 2.0 * savedOverallRatio) {
881 finished = true; // geometric was better
882 if (model_->scalingFlag() == 4) {
883 // If in Branch and bound change
884 if ((model_->specialOptions() & 1024) != 0) {
885 model_->scaling(2);
886 }
887 }
888 } else {
889 scalingMethod = 1; // redo equilibrium
890 if (model_->scalingFlag() == 4) {
891 // If in Branch and bound change
892 if ((model_->specialOptions() & 1024) != 0) {
893 model_->scaling(1);
894 }
895 }
896 }
897 #if 0
898 if (extraDetails) {
899 if (finished)
900 printf("equilibrium ratio %g, geometric ratio %g , geo chosen\n",
901 savedOverallRatio, overallSmallest);
902 else
903 printf("equilibrium ratio %g, geometric ratio %g , equi chosen\n",
904 savedOverallRatio, overallSmallest);
905 }
906 #endif
907 }
908 }
909 //#define RANDOMIZE
910 #ifdef RANDOMIZE
911 // randomize by up to 10%
912 for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) {
913 double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5
914 rowScale[iRow] *= (1.0 + 0.1 * value);
915 }
916 #endif
917 overallLargest = 1.0;
918 if (overallSmallest < 1.0e-1)
919 overallLargest = 1.0 / sqrt(overallSmallest);
920 overallLargest = CoinMin(100.0, overallLargest);
921 overallSmallest = 1.0e50;
922 char *COIN_RESTRICT usedRow = reinterpret_cast< char * >(inverseRowScale);
923 memset(usedRow, 0, numberRows);
924 //printf("scaling %d\n",model_->scalingFlag());
925 if (model_->scalingFlag() != 5) {
926 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
927 if (usefulColumn[iColumn]) {
928 largest = 1.0e-20;
929 smallest = 1.0e50;
930 for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn + 1]; j++) {
931 int iRow = row[j];
932 usedRow[iRow] = 1;
933 double value = fabs(elementByColumn[j] * rowScale[iRow]);
934 largest = CoinMax(largest, value);
935 smallest = CoinMin(smallest, value);
936 }
937 columnScale[iColumn] = overallLargest / largest;
938 //columnScale[iColumn]=CoinMax(1.0e-10,CoinMin(1.0e10,columnScale[iColumn]));
939 #ifdef RANDOMIZE
940 if (!numberAlreadyScaled) {
941 double value = 0.5 - randomNumberGenerator_.randomDouble(); //between -0.5 to + 0.5
942 columnScale[iColumn] *= (1.0 + 0.1 * value);
943 }
944 #endif
945 double difference = columnUpper[iColumn] - columnLower[iColumn];
946 if (difference < 1.0e-5 * columnScale[iColumn]) {
947 // make gap larger
948 columnScale[iColumn] = difference / 1.0e-5;
949 //printf("Column %d difference %g scaled diff %g => %g\n",iColumn,difference,
950 // scaledDifference,difference*columnScale[iColumn]);
951 }
952 double value = smallest * columnScale[iColumn];
953 if (overallSmallest > value)
954 overallSmallest = value;
955 //overallSmallest = CoinMin(overallSmallest,smallest*columnScale[iColumn]);
956 } else {
957 assert(columnScale[iColumn] == 1.0);
958 //columnScale[iColumn]=1.0;
959 }
960 }
961 for (int iRow = numberAlreadyScaled; iRow < numberRows; iRow++) {
962 if (!usedRow[iRow]) {
963 rowScale[iRow] = 1.0;
964 }
965 }
966 }
967 if (!inBranchAndBound)
968 model_->messageHandler()->message(CLP_PACKEDSCALE_FINAL, *model_->messagesPointer())
969 << overallSmallest
970 << overallLargest
971 << CoinMessageEol;
972 if (overallSmallest < 1.0e-13) {
973 // Change factorization zero tolerance
974 double newTolerance = CoinMax(1.0e-15 * (overallSmallest / 1.0e-13),
975 1.0e-18);
976 if (model_->factorization()->zeroTolerance() > newTolerance)
977 model_->factorization()->zeroTolerance(newTolerance);
978 newTolerance = CoinMax(overallSmallest * 0.5, 1.0e-18);
979 model_->setZeroTolerance(newTolerance);
980 #ifndef NDEBUG
981 assert(newTolerance < 0.0); // just so we can fix
982 #endif
983 }
984 // make copy (could do faster by using previous values)
985 // could just do partial
986 CoinAbcReciprocal(inverseRowScale + numberAlreadyScaled, numberRows - numberAlreadyScaled,
987 rowScale + numberAlreadyScaled);
988 if (!numberAlreadyScaled)
989 CoinAbcReciprocal(inverseColumnScale, numberColumns, columnScale);
990 // Do scaled copy //NO and move largest to start
991 CoinBigIndex start = 0;
992 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
993 double scale = columnScale[iColumn];
994 CoinBigIndex end = columnStart[iColumn + 1];
995 for (CoinBigIndex j = start; j < end; j++) {
996 double value = elementByColumn[j];
997 int iRow = row[j];
998 if (iRow >= numberAlreadyScaled) {
999 value *= scale * rowScale[iRow];
1000 elementByColumn[j] = value;
1001 }
1002 }
1003 start = end;
1004 }
1005 delete rowCopy;
1006 #if 0
1007 if (model_->rowCopy()) {
1008 // need to replace row by row
1009 CoinPackedMatrix * rowCopy = NULL;
1010 //static_cast< AbcMatrix*>(model_->rowCopy());
1011 double * element = rowCopy->getMutableElements();
1012 const int * column = rowCopy->getIndices();
1013 const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
1014 // scale row copy
1015 for (iRow = 0; iRow < numberRows; iRow++) {
1016 CoinBigIndex j;
1017 double scale = rowScale[iRow];
1018 double * elementsInThisRow = element + rowStart[iRow];
1019 const int * columnsInThisRow = column + rowStart[iRow];
1020 int number = rowStart[iRow+1] - rowStart[iRow];
1021 assert (number <= numberColumns);
1022 for (j = 0; j < number; j++) {
1023 int iColumn = columnsInThisRow[j];
1024 elementsInThisRow[j] *= scale * columnScale[iColumn];
1025 }
1026 }
1027 }
1028 #endif
1029 model_->clearArraysPublic(whichArray);
1030 }
1031 /* Return <code>y + A * scalar *x</code> in <code>y</code>.
1032 @pre <code>x</code> must be of size <code>numColumns()</code>
1033 @pre <code>y</code> must be of size <code>numRows()</code> */
1034 //scaled versions
timesModifyExcludingSlacks(double scalar,const double * x,double * y) const1035 void AbcMatrix::timesModifyExcludingSlacks(double scalar,
1036 const double *x, double *y) const
1037 {
1038 int numberTotal = model_->numberTotal();
1039 int maximumRows = model_->maximumAbcNumberRows();
1040 // get matrix data pointers
1041 const int *COIN_RESTRICT row = matrix_->getIndices();
1042 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
1043 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
1044 for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) {
1045 double value = x[iColumn];
1046 if (value) {
1047 CoinBigIndex start = columnStart[iColumn];
1048 CoinBigIndex end = columnStart[iColumn + 1];
1049 value *= scalar;
1050 for (CoinBigIndex j = start; j < end; j++) {
1051 int iRow = row[j];
1052 y[iRow] += value * elementByColumn[j];
1053 }
1054 }
1055 }
1056 }
1057 /* Return <code>y + A * scalar(+-1) *x</code> in <code>y</code>.
1058 @pre <code>x</code> must be of size <code>numColumns()+numRows()</code>
1059 @pre <code>y</code> must be of size <code>numRows()</code> */
timesModifyIncludingSlacks(double scalar,const double * x,double * y) const1060 void AbcMatrix::timesModifyIncludingSlacks(double scalar,
1061 const double *x, double *y) const
1062 {
1063 int numberRows = model_->numberRows();
1064 int numberTotal = model_->numberTotal();
1065 int maximumRows = model_->maximumAbcNumberRows();
1066 // makes no sense for x==y??
1067 assert(x != y);
1068 // For now just by column and assumes already scaled (use reallyScale)
1069 // get matrix data pointers
1070 const int *COIN_RESTRICT row = matrix_->getIndices();
1071 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
1072 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
1073 if (scalar == 1.0) {
1074 // add
1075 if (x != y) {
1076 for (int i = 0; i < numberRows; i++)
1077 y[i] += x[i];
1078 } else {
1079 for (int i = 0; i < numberRows; i++)
1080 y[i] += y[i];
1081 }
1082 for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) {
1083 double value = x[iColumn];
1084 if (value) {
1085 CoinBigIndex start = columnStart[iColumn];
1086 CoinBigIndex next = columnStart[iColumn + 1];
1087 for (CoinBigIndex j = start; j < next; j++) {
1088 int jRow = row[j];
1089 y[jRow] += value * elementByColumn[j];
1090 }
1091 }
1092 }
1093 } else {
1094 // subtract
1095 if (x != y) {
1096 for (int i = 0; i < numberRows; i++)
1097 y[i] -= x[i];
1098 } else {
1099 for (int i = 0; i < numberRows; i++)
1100 y[i] = 0.0;
1101 }
1102 for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) {
1103 double value = x[iColumn];
1104 if (value) {
1105 CoinBigIndex start = columnStart[iColumn];
1106 CoinBigIndex next = columnStart[iColumn + 1];
1107 for (CoinBigIndex j = start; j < next; j++) {
1108 int jRow = row[j];
1109 y[jRow] -= value * elementByColumn[j];
1110 }
1111 }
1112 }
1113 }
1114 }
1115 /* Return A * scalar(+-1) *x</code> in <code>y</code>.
1116 @pre <code>x</code> must be of size <code>numColumns()+numRows()</code>
1117 @pre <code>y</code> must be of size <code>numRows()</code> */
timesIncludingSlacks(double scalar,const double * x,double * y) const1118 void AbcMatrix::timesIncludingSlacks(double scalar,
1119 const double *x, double *y) const
1120 {
1121 int numberRows = model_->numberRows();
1122 int numberTotal = model_->numberTotal();
1123 int maximumRows = model_->maximumAbcNumberRows();
1124 // For now just by column and assumes already scaled (use reallyScale)
1125 // get matrix data pointers
1126 const int *COIN_RESTRICT row = matrix_->getIndices();
1127 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
1128 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
1129 if (scalar == 1.0) {
1130 // add
1131 if (x != y) {
1132 for (int i = 0; i < numberRows; i++)
1133 y[i] = x[i];
1134 }
1135 for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) {
1136 double value = x[iColumn];
1137 if (value) {
1138 CoinBigIndex start = columnStart[iColumn];
1139 CoinBigIndex next = columnStart[iColumn + 1];
1140 for (CoinBigIndex j = start; j < next; j++) {
1141 int jRow = row[j];
1142 y[jRow] += value * elementByColumn[j];
1143 }
1144 }
1145 }
1146 } else {
1147 // subtract
1148 if (x != y) {
1149 for (int i = 0; i < numberRows; i++)
1150 y[i] = -x[i];
1151 } else {
1152 for (int i = 0; i < numberRows; i++)
1153 y[i] = -y[i];
1154 }
1155 for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) {
1156 double value = x[iColumn];
1157 if (value) {
1158 CoinBigIndex start = columnStart[iColumn];
1159 CoinBigIndex next = columnStart[iColumn + 1];
1160 for (CoinBigIndex j = start; j < next; j++) {
1161 int jRow = row[j];
1162 y[jRow] -= value * elementByColumn[j];
1163 }
1164 }
1165 }
1166 }
1167 }
1168 extern double parallelDual4(AbcSimplexDual *);
firstPass(AbcSimplex * model,int iBlock,double upperTheta,int & freeSequence,CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList)1169 static double firstPass(AbcSimplex *model, int iBlock,
1170 double upperTheta, int &freeSequence,
1171 CoinPartitionedVector &tableauRow,
1172 CoinPartitionedVector &candidateList)
1173 {
1174 int *COIN_RESTRICT index = tableauRow.getIndices();
1175 double *COIN_RESTRICT array = tableauRow.denseVector();
1176 double *COIN_RESTRICT arrayCandidate = candidateList.denseVector();
1177 int *COIN_RESTRICT indexCandidate = candidateList.getIndices();
1178 const double *COIN_RESTRICT abcDj = model->djRegion();
1179 const unsigned char *COIN_RESTRICT internalStatus = model->internalStatus();
1180 // do first pass to get possibles
1181 double bestPossible = 0.0;
1182 // We can also see if infeasible or pivoting on free
1183 double tentativeTheta = 1.0e25; // try with this much smaller as guess
1184 double acceptablePivot = model->currentAcceptablePivot();
1185 double dualT = -model->currentDualTolerance();
1186 // fixed will have been taken out by now
1187 const double multiplier[] = { 1.0, -1.0 };
1188 freeSequence = -1;
1189 int firstIn = model->abcMatrix()->blockStart(iBlock);
1190 int numberNonZero = tableauRow.getNumElements(iBlock) + firstIn;
1191 int numberRemaining = firstIn;
1192 //first=tableauRow.getNumElements();
1193 // could pass in last and if numberNonZero==last-firstIn scan as well
1194 if (model->ordinaryVariables()) {
1195 for (int i = firstIn; i < numberNonZero; i++) {
1196 int iSequence = index[i];
1197 double tableauValue = array[i];
1198 unsigned char iStatus = internalStatus[iSequence] & 7;
1199 double mult = multiplier[iStatus];
1200 double alpha = tableauValue * mult;
1201 double oldValue = abcDj[iSequence] * mult;
1202 double value = oldValue - tentativeTheta * alpha;
1203 if (value < dualT) {
1204 bestPossible = CoinMax(bestPossible, alpha);
1205 value = oldValue - upperTheta * alpha;
1206 if (value < dualT && alpha >= acceptablePivot) {
1207 upperTheta = (oldValue - dualT) / alpha;
1208 }
1209 // add to list
1210 arrayCandidate[numberRemaining] = alpha;
1211 indexCandidate[numberRemaining++] = iSequence;
1212 }
1213 }
1214 } else {
1215 double badFree = 0.0;
1216 double freeAlpha = model->currentAcceptablePivot();
1217 int freeSequenceIn = model->freeSequenceIn();
1218 double currentDualTolerance = model->currentDualTolerance();
1219 for (int i = firstIn; i < numberNonZero; i++) {
1220 int iSequence = index[i];
1221 double tableauValue = array[i];
1222 unsigned char iStatus = internalStatus[iSequence] & 7;
1223 if ((iStatus & 4) == 0) {
1224 double mult = multiplier[iStatus];
1225 double alpha = tableauValue * mult;
1226 double oldValue = abcDj[iSequence] * mult;
1227 double value = oldValue - tentativeTheta * alpha;
1228 if (value < dualT) {
1229 bestPossible = CoinMax(bestPossible, alpha);
1230 value = oldValue - upperTheta * alpha;
1231 if (value < dualT && alpha >= acceptablePivot) {
1232 upperTheta = (oldValue - dualT) / alpha;
1233 }
1234 // add to list
1235 arrayCandidate[numberRemaining] = alpha;
1236 indexCandidate[numberRemaining++] = iSequence;
1237 }
1238 } else {
1239 bool keep;
1240 bestPossible = CoinMax(bestPossible, fabs(tableauValue));
1241 double oldValue = abcDj[iSequence];
1242 // If free has to be very large - should come in via dualRow
1243 //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3)
1244 //break;
1245 if (oldValue > currentDualTolerance) {
1246 keep = true;
1247 } else if (oldValue < -currentDualTolerance) {
1248 keep = true;
1249 } else {
1250 if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) {
1251 keep = true;
1252 } else {
1253 keep = false;
1254 badFree = CoinMax(badFree, fabs(tableauValue));
1255 }
1256 }
1257 if (keep) {
1258 #ifdef PAN
1259 if (model->fakeSuperBasic(iSequence) >= 0) {
1260 #endif
1261 if (iSequence == freeSequenceIn)
1262 tableauValue = COIN_DBL_MAX;
1263 // free - choose largest
1264 if (fabs(tableauValue) > fabs(freeAlpha)) {
1265 freeAlpha = tableauValue;
1266 freeSequence = iSequence;
1267 }
1268 #ifdef PAN
1269 }
1270 #endif
1271 }
1272 }
1273 }
1274 }
1275 //firstInX=numberNonZero-firstIn;
1276 //lastInX=-1;//numberRemaining-lastInX;
1277 tableauRow.setNumElementsPartition(iBlock, numberNonZero - firstIn);
1278 candidateList.setNumElementsPartition(iBlock, numberRemaining - firstIn);
1279 return upperTheta;
1280 }
1281 // gets sorted tableau row and a possible value of theta
1282 double
dualColumn1Row(int iBlock,double upperTheta,int & freeSequence,const CoinIndexedVector & update,CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList) const1283 AbcMatrix::dualColumn1Row(int iBlock, double upperTheta, int &freeSequence,
1284 const CoinIndexedVector &update,
1285 CoinPartitionedVector &tableauRow,
1286 CoinPartitionedVector &candidateList) const
1287 {
1288 int maximumRows = model_->maximumAbcNumberRows();
1289 int number = update.getNumElements();
1290 const double *COIN_RESTRICT pi = update.denseVector();
1291 const int *COIN_RESTRICT piIndex = update.getIndices();
1292 const CoinBigIndex *COIN_RESTRICT rowStart = rowStart_;
1293 int numberRows = model_->numberRows();
1294 const CoinBigIndex *COIN_RESTRICT rowEnd = rowStart + numberRows * numberRowBlocks_;
1295 // count down
1296 int nColumns;
1297 int firstIn = blockStart_[iBlock];
1298 int first = firstIn;
1299 if (!first)
1300 first = maximumRows;
1301 int last = blockStart_[iBlock + 1];
1302 nColumns = last - first;
1303 int target = nColumns;
1304 rowStart += iBlock * numberRows;
1305 rowEnd = rowStart + numberRows;
1306 for (int i = 0; i < number; i++) {
1307 int iRow = piIndex[i];
1308 CoinBigIndex end = rowEnd[iRow];
1309 target -= end - rowStart[iRow];
1310 if (target < 0)
1311 break;
1312 }
1313 if (target > 0) {
1314 //printf("going to few %d ops %d\n",number,nColumns-target);
1315 return dualColumn1RowFew(iBlock, upperTheta, freeSequence,
1316 update, tableauRow, candidateList);
1317 }
1318 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
1319 int *COIN_RESTRICT index = tableauRow.getIndices();
1320 double *COIN_RESTRICT array = tableauRow.denseVector();
1321 const double *COIN_RESTRICT element = element_;
1322 const int *COIN_RESTRICT column = column_;
1323 for (int i = 0; i < number; i++) {
1324 int iRow = piIndex[i];
1325 double piValue = pi[iRow];
1326 CoinBigIndex end = rowEnd[iRow];
1327 for (CoinBigIndex j = rowStart[iRow]; j < end; j++) {
1328 int iColumn = column[j];
1329 assert(iColumn >= first && iColumn < last);
1330 double value = element[j];
1331 array[iColumn] += piValue * value;
1332 }
1333 }
1334 int numberNonZero;
1335 int numberRemaining;
1336 if (iBlock == 0) {
1337 #if 1
1338 upperTheta = static_cast< AbcSimplexDual * >(model_)->dualColumn1A();
1339 numberNonZero = tableauRow.getNumElements(0);
1340 numberRemaining = candidateList.getNumElements(0);
1341 #else
1342 numberNonZero = 0;
1343 for (int i = 0; i < number; i++) {
1344 int iRow = piIndex[i];
1345 unsigned char type = internalStatus[iRow];
1346 if ((type & 7) < 6) {
1347 index[numberNonZero] = iRow;
1348 double piValue = pi[iRow];
1349 array[numberNonZero++] = piValue;
1350 }
1351 }
1352 numberRemaining = 0;
1353 #endif
1354 } else {
1355 numberNonZero = firstIn;
1356 numberRemaining = firstIn;
1357 }
1358 double *COIN_RESTRICT arrayCandidate = candidateList.denseVector();
1359 int *COIN_RESTRICT indexCandidate = candidateList.getIndices();
1360 //printf("first %d last %d firstIn %d lastIn %d\n",
1361 // first,last,firstIn,lastIn);
1362 const double *COIN_RESTRICT abcDj = model_->djRegion();
1363 // do first pass to get possibles
1364 double bestPossible = 0.0;
1365 // We can also see if infeasible or pivoting on free
1366 double tentativeTheta = 1.0e25; // try with this much smaller as guess
1367 double acceptablePivot = model_->currentAcceptablePivot();
1368 double dualT = -model_->currentDualTolerance();
1369 const double multiplier[] = { 1.0, -1.0 };
1370 double zeroTolerance = model_->zeroTolerance();
1371 freeSequence = -1;
1372 if (model_->ordinaryVariables()) {
1373 for (int iSequence = first; iSequence < last; iSequence++) {
1374 double tableauValue = array[iSequence];
1375 if (tableauValue) {
1376 array[iSequence] = 0.0;
1377 if (fabs(tableauValue) > zeroTolerance) {
1378 unsigned char iStatus = internalStatus[iSequence] & 7;
1379 if (iStatus < 4) {
1380 index[numberNonZero] = iSequence;
1381 array[numberNonZero++] = tableauValue;
1382 double mult = multiplier[iStatus];
1383 double alpha = tableauValue * mult;
1384 double oldValue = abcDj[iSequence] * mult;
1385 double value = oldValue - tentativeTheta * alpha;
1386 if (value < dualT) {
1387 bestPossible = CoinMax(bestPossible, alpha);
1388 value = oldValue - upperTheta * alpha;
1389 if (value < dualT && alpha >= acceptablePivot) {
1390 upperTheta = (oldValue - dualT) / alpha;
1391 }
1392 // add to list
1393 arrayCandidate[numberRemaining] = alpha;
1394 indexCandidate[numberRemaining++] = iSequence;
1395 }
1396 }
1397 }
1398 }
1399 }
1400 } else {
1401 double badFree = 0.0;
1402 double freeAlpha = model_->currentAcceptablePivot();
1403 int freeSequenceIn = model_->freeSequenceIn();
1404 //printf("block %d freeSequence %d acceptable %g\n",iBlock,freeSequenceIn,freeAlpha);
1405 double currentDualTolerance = model_->currentDualTolerance();
1406 for (int iSequence = first; iSequence < last; iSequence++) {
1407 double tableauValue = array[iSequence];
1408 if (tableauValue) {
1409 array[iSequence] = 0.0;
1410 if (fabs(tableauValue) > zeroTolerance) {
1411 unsigned char iStatus = internalStatus[iSequence] & 7;
1412 if (iStatus < 6) {
1413 if ((iStatus & 4) == 0) {
1414 index[numberNonZero] = iSequence;
1415 array[numberNonZero++] = tableauValue;
1416 double mult = multiplier[iStatus];
1417 double alpha = tableauValue * mult;
1418 double oldValue = abcDj[iSequence] * mult;
1419 double value = oldValue - tentativeTheta * alpha;
1420 if (value < dualT) {
1421 bestPossible = CoinMax(bestPossible, alpha);
1422 value = oldValue - upperTheta * alpha;
1423 if (value < dualT && alpha >= acceptablePivot) {
1424 upperTheta = (oldValue - dualT) / alpha;
1425 }
1426 // add to list
1427 arrayCandidate[numberRemaining] = alpha;
1428 indexCandidate[numberRemaining++] = iSequence;
1429 }
1430 } else {
1431 bool keep;
1432 index[numberNonZero] = iSequence;
1433 array[numberNonZero++] = tableauValue;
1434 bestPossible = CoinMax(bestPossible, fabs(tableauValue));
1435 double oldValue = abcDj[iSequence];
1436 // If free has to be very large - should come in via dualRow
1437 //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3)
1438 //break;
1439 // may be fake super basic
1440 if (oldValue > currentDualTolerance) {
1441 keep = true;
1442 } else if (oldValue < -currentDualTolerance) {
1443 keep = true;
1444 } else {
1445 if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) {
1446 keep = true;
1447 } else {
1448 keep = false;
1449 badFree = CoinMax(badFree, fabs(tableauValue));
1450 }
1451 }
1452 #if 0
1453 if (iSequence==freeSequenceIn)
1454 assert (keep);
1455 #endif
1456 if (keep) {
1457 #ifdef PAN
1458 if (model_->fakeSuperBasic(iSequence) >= 0) {
1459 #endif
1460 if (iSequence == freeSequenceIn)
1461 tableauValue = COIN_DBL_MAX;
1462 // free - choose largest
1463 if (fabs(tableauValue) > fabs(freeAlpha)) {
1464 freeAlpha = tableauValue;
1465 freeSequence = iSequence;
1466 }
1467 #ifdef PAN
1468 }
1469 #endif
1470 }
1471 }
1472 }
1473 }
1474 }
1475 }
1476 }
1477 #if 0
1478 if (model_->freeSequenceIn()>=first&&model_->freeSequenceIn()<last)
1479 assert (freeSequence==model_->freeSequenceIn());
1480 extern int xxInfo[6][8];
1481 xxInfo[0][iBlock]=first;
1482 xxInfo[1][iBlock]=last;
1483 xxInfo[2][iBlock]=firstIn;
1484 xxInfo[3][iBlock]=numberNonZero-firstIn;
1485 xxInfo[4][iBlock]=numberRemaining-firstIn;
1486 #endif
1487 tableauRow.setNumElementsPartition(iBlock, numberNonZero - firstIn);
1488 candidateList.setNumElementsPartition(iBlock, numberRemaining - firstIn);
1489 return upperTheta;
1490 }
1491 // gets sorted tableau row and a possible value of theta
1492 double
dualColumn1Row2(double upperTheta,int & freeSequence,const CoinIndexedVector & update,CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList) const1493 AbcMatrix::dualColumn1Row2(double upperTheta, int &freeSequence,
1494 const CoinIndexedVector &update,
1495 CoinPartitionedVector &tableauRow,
1496 CoinPartitionedVector &candidateList) const
1497 {
1498 //int first=model_->maximumAbcNumberRows();
1499 assert(update.getNumElements() == 2);
1500 const double *COIN_RESTRICT pi = update.denseVector();
1501 const int *COIN_RESTRICT piIndex = update.getIndices();
1502 int *COIN_RESTRICT index = tableauRow.getIndices();
1503 double *COIN_RESTRICT array = tableauRow.denseVector();
1504 const CoinBigIndex *COIN_RESTRICT rowStart = rowStart_;
1505 int numberRows = model_->numberRows();
1506 const CoinBigIndex *COIN_RESTRICT rowEnd = rowStart + numberRows * numberRowBlocks_;
1507 const double *COIN_RESTRICT element = element_;
1508 const int *COIN_RESTRICT column = column_;
1509 int iRow0 = piIndex[0];
1510 int iRow1 = piIndex[1];
1511 CoinBigIndex end0 = rowEnd[iRow0];
1512 CoinBigIndex end1 = rowEnd[iRow1];
1513 if (end0 - rowStart[iRow0] > end1 - rowStart[iRow1]) {
1514 int temp = iRow0;
1515 iRow0 = iRow1;
1516 iRow1 = temp;
1517 }
1518 CoinBigIndex start = rowStart[iRow0];
1519 CoinBigIndex end = rowEnd[iRow0];
1520 double piValue = pi[iRow0];
1521 double *COIN_RESTRICT arrayCandidate = candidateList.denseVector();
1522 int numberNonZero;
1523 numberNonZero = tableauRow.getNumElements(0);
1524 int n = numberNonZero;
1525 for (CoinBigIndex j = start; j < end; j++) {
1526 int iSequence = column[j];
1527 double value = element[j];
1528 arrayCandidate[iSequence] = piValue * value;
1529 index[n++] = iSequence;
1530 }
1531 start = rowStart[iRow1];
1532 end = rowEnd[iRow1];
1533 piValue = pi[iRow1];
1534 for (CoinBigIndex j = start; j < end; j++) {
1535 int iSequence = column[j];
1536 double value = element[j];
1537 value *= piValue;
1538 if (!arrayCandidate[iSequence]) {
1539 arrayCandidate[iSequence] = value;
1540 index[n++] = iSequence;
1541 } else {
1542 arrayCandidate[iSequence] += value;
1543 }
1544 }
1545 // pack down
1546 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
1547 double zeroTolerance = model_->zeroTolerance();
1548 while (numberNonZero < n) {
1549 int iSequence = index[numberNonZero];
1550 double value = arrayCandidate[iSequence];
1551 arrayCandidate[iSequence] = 0.0;
1552 unsigned char iStatus = internalStatus[iSequence] & 7;
1553 if (fabs(value) > zeroTolerance && iStatus < 6) {
1554 index[numberNonZero] = iSequence;
1555 array[numberNonZero++] = value;
1556 } else {
1557 // kill
1558 n--;
1559 index[numberNonZero] = index[n];
1560 }
1561 }
1562 tableauRow.setNumElementsPartition(0, numberNonZero);
1563 return firstPass(model_, 0, upperTheta, freeSequence,
1564 tableauRow,
1565 candidateList);
1566 }
1567 //static int ixxxxxx=1;
1568 // gets sorted tableau row and a possible value of theta
1569 double
dualColumn1RowFew(int iBlock,double upperTheta,int & freeSequence,const CoinIndexedVector & update,CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList) const1570 AbcMatrix::dualColumn1RowFew(int iBlock, double upperTheta, int &freeSequence,
1571 const CoinIndexedVector &update,
1572 CoinPartitionedVector &tableauRow,
1573 CoinPartitionedVector &candidateList) const
1574 {
1575 //int first=model_->maximumAbcNumberRows();
1576 int number = update.getNumElements();
1577 const double *COIN_RESTRICT pi = update.denseVector();
1578 const int *COIN_RESTRICT piIndex = update.getIndices();
1579 int *COIN_RESTRICT index = tableauRow.getIndices();
1580 double *COIN_RESTRICT array = tableauRow.denseVector();
1581 const CoinBigIndex *COIN_RESTRICT rowStart = rowStart_;
1582 int numberRows = model_->numberRows();
1583 const CoinBigIndex *COIN_RESTRICT rowEnd = rowStart + numberRows * numberRowBlocks_;
1584 const double *COIN_RESTRICT element = element_;
1585 const int *COIN_RESTRICT column = column_;
1586 double *COIN_RESTRICT arrayCandidate = candidateList.denseVector();
1587 int numberNonZero;
1588 assert(iBlock >= 0);
1589 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
1590 int firstIn = blockStart_[iBlock];
1591 if (iBlock == 0) {
1592 numberNonZero = 0;
1593 for (int i = 0; i < number; i++) {
1594 int iRow = piIndex[i];
1595 unsigned char type = internalStatus[iRow];
1596 if ((type & 7) < 6) {
1597 index[numberNonZero] = iRow;
1598 double piValue = pi[iRow];
1599 array[numberNonZero++] = piValue;
1600 }
1601 }
1602 } else {
1603 numberNonZero = firstIn;
1604 }
1605 int n = numberNonZero;
1606 rowStart += iBlock * numberRows;
1607 rowEnd = rowStart + numberRows;
1608 for (int i = 0; i < number; i++) {
1609 int iRow = piIndex[i];
1610 double piValue = pi[iRow];
1611 CoinBigIndex end = rowEnd[iRow];
1612 for (CoinBigIndex j = rowStart[iRow]; j < end; j++) {
1613 int iColumn = column[j];
1614 double value = element[j] * piValue;
1615 double oldValue = arrayCandidate[iColumn];
1616 value += oldValue;
1617 if (!oldValue) {
1618 arrayCandidate[iColumn] = value;
1619 index[n++] = iColumn;
1620 } else if (value) {
1621 arrayCandidate[iColumn] = value;
1622 } else {
1623 arrayCandidate[iColumn] = COIN_INDEXED_REALLY_TINY_ELEMENT;
1624 }
1625 }
1626 }
1627 // pack down
1628 double zeroTolerance = model_->zeroTolerance();
1629 while (numberNonZero < n) {
1630 int iSequence = index[numberNonZero];
1631 double value = arrayCandidate[iSequence];
1632 arrayCandidate[iSequence] = 0.0;
1633 unsigned char iStatus = internalStatus[iSequence] & 7;
1634 if (fabs(value) > zeroTolerance && iStatus < 6) {
1635 index[numberNonZero] = iSequence;
1636 array[numberNonZero++] = value;
1637 } else {
1638 // kill
1639 n--;
1640 index[numberNonZero] = index[n];
1641 }
1642 }
1643 tableauRow.setNumElementsPartition(iBlock, numberNonZero - firstIn);
1644 upperTheta = firstPass(model_, iBlock, upperTheta, freeSequence,
1645 tableauRow,
1646 candidateList);
1647 return upperTheta;
1648 }
1649 // gets sorted tableau row and a possible value of theta
1650 double
dualColumn1Row1(double upperTheta,int & freeSequence,const CoinIndexedVector & update,CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList) const1651 AbcMatrix::dualColumn1Row1(double upperTheta, int &freeSequence,
1652 const CoinIndexedVector &update,
1653 CoinPartitionedVector &tableauRow,
1654 CoinPartitionedVector &candidateList) const
1655 {
1656 assert(update.getNumElements() == 1);
1657 int iRow = update.getIndices()[0];
1658 double piValue = update.denseVector()[iRow];
1659 int *COIN_RESTRICT index = tableauRow.getIndices();
1660 double *COIN_RESTRICT array = tableauRow.denseVector();
1661 const CoinBigIndex *COIN_RESTRICT rowStart = rowStart_;
1662 int numberRows = model_->numberRows();
1663 const CoinBigIndex *COIN_RESTRICT rowEnd = rowStart + numberRows * numberRowBlocks_;
1664 CoinBigIndex start = rowStart[iRow];
1665 CoinBigIndex end = rowEnd[iRow];
1666 const double *COIN_RESTRICT element = element_;
1667 const int *COIN_RESTRICT column = column_;
1668 int numberNonZero;
1669 int numberRemaining;
1670 numberNonZero = tableauRow.getNumElements(0);
1671 numberRemaining = candidateList.getNumElements(0);
1672 double *COIN_RESTRICT arrayCandidate = candidateList.denseVector();
1673 int *COIN_RESTRICT indexCandidate = candidateList.getIndices();
1674 const double *COIN_RESTRICT abcDj = model_->djRegion();
1675 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
1676 // do first pass to get possibles
1677 double bestPossible = 0.0;
1678 // We can also see if infeasible or pivoting on free
1679 double tentativeTheta = 1.0e25; // try with this much smaller as guess
1680 double acceptablePivot = model_->currentAcceptablePivot();
1681 double dualT = -model_->currentDualTolerance();
1682 const double multiplier[] = { 1.0, -1.0 };
1683 double zeroTolerance = model_->zeroTolerance();
1684 freeSequence = -1;
1685 if (model_->ordinaryVariables()) {
1686 for (CoinBigIndex j = start; j < end; j++) {
1687 int iSequence = column[j];
1688 double value = element[j];
1689 double tableauValue = piValue * value;
1690 if (fabs(tableauValue) > zeroTolerance) {
1691 unsigned char iStatus = internalStatus[iSequence] & 7;
1692 if (iStatus < 4) {
1693 index[numberNonZero] = iSequence;
1694 array[numberNonZero++] = tableauValue;
1695 double mult = multiplier[iStatus];
1696 double alpha = tableauValue * mult;
1697 double oldValue = abcDj[iSequence] * mult;
1698 double value = oldValue - tentativeTheta * alpha;
1699 if (value < dualT) {
1700 bestPossible = CoinMax(bestPossible, alpha);
1701 value = oldValue - upperTheta * alpha;
1702 if (value < dualT && alpha >= acceptablePivot) {
1703 upperTheta = (oldValue - dualT) / alpha;
1704 }
1705 // add to list
1706 arrayCandidate[numberRemaining] = alpha;
1707 indexCandidate[numberRemaining++] = iSequence;
1708 }
1709 }
1710 }
1711 }
1712 } else {
1713 double badFree = 0.0;
1714 double freeAlpha = model_->currentAcceptablePivot();
1715 int freeSequenceIn = model_->freeSequenceIn();
1716 double currentDualTolerance = model_->currentDualTolerance();
1717 for (CoinBigIndex j = start; j < end; j++) {
1718 int iSequence = column[j];
1719 double value = element[j];
1720 double tableauValue = piValue * value;
1721 if (fabs(tableauValue) > zeroTolerance) {
1722 unsigned char iStatus = internalStatus[iSequence] & 7;
1723 if (iStatus < 6) {
1724 if ((iStatus & 4) == 0) {
1725 index[numberNonZero] = iSequence;
1726 array[numberNonZero++] = tableauValue;
1727 double mult = multiplier[iStatus];
1728 double alpha = tableauValue * mult;
1729 double oldValue = abcDj[iSequence] * mult;
1730 double value = oldValue - tentativeTheta * alpha;
1731 if (value < dualT) {
1732 bestPossible = CoinMax(bestPossible, alpha);
1733 value = oldValue - upperTheta * alpha;
1734 if (value < dualT && alpha >= acceptablePivot) {
1735 upperTheta = (oldValue - dualT) / alpha;
1736 }
1737 // add to list
1738 arrayCandidate[numberRemaining] = alpha;
1739 indexCandidate[numberRemaining++] = iSequence;
1740 }
1741 } else {
1742 bool keep;
1743 index[numberNonZero] = iSequence;
1744 array[numberNonZero++] = tableauValue;
1745 bestPossible = CoinMax(bestPossible, fabs(tableauValue));
1746 double oldValue = abcDj[iSequence];
1747 // If free has to be very large - should come in via dualRow
1748 //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3)
1749 //break;
1750 if (oldValue > currentDualTolerance) {
1751 keep = true;
1752 } else if (oldValue < -currentDualTolerance) {
1753 keep = true;
1754 } else {
1755 if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) {
1756 keep = true;
1757 } else {
1758 keep = false;
1759 badFree = CoinMax(badFree, fabs(tableauValue));
1760 }
1761 }
1762 if (keep) {
1763 #ifdef PAN
1764 if (model_->fakeSuperBasic(iSequence) >= 0) {
1765 #endif
1766 if (iSequence == freeSequenceIn)
1767 tableauValue = COIN_DBL_MAX;
1768 // free - choose largest
1769 if (fabs(tableauValue) > fabs(freeAlpha)) {
1770 freeAlpha = tableauValue;
1771 freeSequence = iSequence;
1772 }
1773 #ifdef PAN
1774 }
1775 #endif
1776 }
1777 }
1778 }
1779 }
1780 }
1781 }
1782 tableauRow.setNumElementsPartition(0, numberNonZero);
1783 candidateList.setNumElementsPartition(0, numberRemaining);
1784 return upperTheta;
1785 }
1786 //#define PARALLEL2
1787 #ifdef PARALLEL2
1788 #undef cilk_for
1789 #undef cilk_spawn
1790 #undef cilk_sync
1791 #include <cilk/cilk.h>
1792 #include <cilk/cilk_api.h>
1793 #endif
1794 #if 0
1795 static void compact(int numberBlocks,CoinIndexedVector * vector,const int * starts,const int * lengths)
1796 {
1797 int numberNonZeroIn=vector->getNumElements();
1798 int * index = vector->getIndices();
1799 double * array = vector->denseVector();
1800 CoinAbcCompact(numberBlocks,numberNonZeroIn,
1801 array,starts,lengths);
1802 int numberNonZero = CoinAbcCompact(numberBlocks,numberNonZeroIn,
1803 index,starts,lengths);
1804 vector->setNumElements(numberNonZero);
1805 }
1806 static void compactBoth(int numberBlocks,CoinIndexedVector * vector1,CoinIndexedVector * vector2,
1807 const int * starts,const int * lengths1, const int * lengths2)
1808 {
1809 cilk_spawn compact(numberBlocks,vector1,starts,lengths1);
1810 compact(numberBlocks,vector2,starts,lengths2);
1811 cilk_sync;
1812 }
1813 #endif
rebalance() const1814 void AbcMatrix::rebalance() const
1815 {
1816 int maximumRows = model_->maximumAbcNumberRows();
1817 int numberTotal = model_->numberTotal();
1818 /* rebalance
1819 For non-vector version
1820 each basic etc column is 1
1821 each real column is 5+2*nel
1822 each basic slack is 0
1823 each real slack is 3
1824 */
1825 #if ABC_PARALLEL
1826 int howOften = CoinMax(model_->factorization()->maximumPivots(), 200);
1827 if ((model_->numberIterations() % howOften) == 0 || !startColumnBlock_[1]) {
1828 int numberCpus = model_->numberCpus();
1829 if (numberCpus > 1) {
1830 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
1831 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
1832 int numberRows = model_->numberRows();
1833 int total = 0;
1834 for (int iSequence = 0; iSequence < numberRows; iSequence++) {
1835 unsigned char iStatus = internalStatus[iSequence] & 7;
1836 if (iStatus < 4)
1837 total += 3;
1838 }
1839 int totalSlacks = total;
1840 CoinBigIndex end = columnStart[maximumRows];
1841 for (int iSequence = maximumRows; iSequence < numberTotal; iSequence++) {
1842 CoinBigIndex start = end;
1843 end = columnStart[iSequence + 1];
1844 unsigned char iStatus = internalStatus[iSequence] & 7;
1845 if (iStatus < 4)
1846 total += 5 + 2 * (end - start);
1847 else
1848 total += 1;
1849 }
1850 int chunk = (total + numberCpus - 1) / numberCpus;
1851 total = totalSlacks;
1852 int iCpu = 0;
1853 startColumnBlock_[0] = 0;
1854 end = columnStart[maximumRows];
1855 for (int iSequence = maximumRows; iSequence < numberTotal; iSequence++) {
1856 CoinBigIndex start = end;
1857 end = columnStart[iSequence + 1];
1858 unsigned char iStatus = internalStatus[iSequence] & 7;
1859 if (iStatus < 4)
1860 total += 5 + 2 * (end - start);
1861 else
1862 total += 1;
1863 if (total > chunk) {
1864 iCpu++;
1865 total = 0;
1866 startColumnBlock_[iCpu] = iSequence;
1867 }
1868 }
1869 assert(iCpu < numberCpus);
1870 iCpu++;
1871 for (; iCpu <= numberCpus; iCpu++)
1872 startColumnBlock_[iCpu] = numberTotal;
1873 numberColumnBlocks_ = numberCpus;
1874 } else {
1875 numberColumnBlocks_ = 1;
1876 startColumnBlock_[0] = 0;
1877 startColumnBlock_[1] = numberTotal;
1878 }
1879 }
1880 #else
1881 startColumnBlock_[0] = 0;
1882 startColumnBlock_[1] = numberTotal;
1883 #endif
1884 }
1885 double
dualColumn1(const CoinIndexedVector & update,CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList) const1886 AbcMatrix::dualColumn1(const CoinIndexedVector &update,
1887 CoinPartitionedVector &tableauRow, CoinPartitionedVector &candidateList) const
1888 {
1889 int numberTotal = model_->numberTotal();
1890 // rebalance
1891 rebalance();
1892 tableauRow.setPackedMode(true);
1893 candidateList.setPackedMode(true);
1894 int number = update.getNumElements();
1895 double upperTheta;
1896 if (rowStart_ && number < 3) {
1897 #if ABC_INSTRUMENT > 1
1898 {
1899 int n = update.getNumElements();
1900 abcPricing[n < 19 ? n : 19]++;
1901 }
1902 #endif
1903 // always do serially
1904 // do slacks first
1905 int starts[2];
1906 starts[0] = 0;
1907 starts[1] = numberTotal;
1908 tableauRow.setPartitions(1, starts);
1909 candidateList.setPartitions(1, starts);
1910 upperTheta = static_cast< AbcSimplexDual * >(model_)->dualColumn1A();
1911 //assert (upperTheta>-100*model_->dualTolerance()||model_->sequenceIn()>=0||model_->lastFirstFree()>=0);
1912 int freeSequence = -1;
1913 // worth using row copy
1914 assert(number);
1915 if (number == 2) {
1916 upperTheta = dualColumn1Row2(upperTheta, freeSequence, update, tableauRow, candidateList);
1917 } else {
1918 upperTheta = dualColumn1Row1(upperTheta, freeSequence, update, tableauRow, candidateList);
1919 }
1920 if (freeSequence >= 0) {
1921 int numberNonZero = tableauRow.getNumElements(0);
1922 const int *COIN_RESTRICT index = tableauRow.getIndices();
1923 const double *COIN_RESTRICT array = tableauRow.denseVector();
1924 // search for free coming in
1925 double freeAlpha = 0.0;
1926 int bestSequence = model_->sequenceIn();
1927 if (bestSequence >= 0)
1928 freeAlpha = model_->alpha();
1929 index = tableauRow.getIndices();
1930 array = tableauRow.denseVector();
1931 // free variable - search
1932 for (int k = 0; k < numberNonZero; k++) {
1933 if (freeSequence == index[k]) {
1934 if (fabs(freeAlpha) < fabs(array[k])) {
1935 freeAlpha = array[k];
1936 }
1937 break;
1938 }
1939 }
1940 if (model_->sequenceIn() < 0 || fabs(freeAlpha) > fabs(model_->alpha())) {
1941 double oldValue = model_->djRegion()[freeSequence];
1942 model_->setSequenceIn(freeSequence);
1943 model_->setAlpha(freeAlpha);
1944 model_->setTheta(oldValue / freeAlpha);
1945 }
1946 }
1947 } else {
1948 // three or more
1949 // need to do better job on dividing up (but wait until vector or by row)
1950 upperTheta = parallelDual4(static_cast< AbcSimplexDual * >(model_));
1951 }
1952 //tableauRow.compact();
1953 //candidateList.compact();
1954 #if 0 //ndef NDEBUG
1955 model_->checkArrays();
1956 #endif
1957 candidateList.computeNumberElements();
1958 int numberRemaining = candidateList.getNumElements();
1959 if (!numberRemaining && model_->sequenceIn() < 0) {
1960 return COIN_DBL_MAX; // Looks infeasible
1961 } else {
1962 return upperTheta;
1963 }
1964 }
1965 #define _mm256_broadcast_sd(x) static_cast< __m256d >(__builtin_ia32_vbroadcastsd256(x))
1966 #define _mm256_load_pd(x) *(__m256d *)(x)
1967 #define _mm256_store_pd (s, x) * ((__m256d *)s) = x
dualColumn1Part(int iBlock,int & sequenceIn,double & upperThetaResult,const CoinIndexedVector & update,CoinPartitionedVector & tableauRow,CoinPartitionedVector & candidateList) const1968 void AbcMatrix::dualColumn1Part(int iBlock, int &sequenceIn, double &upperThetaResult,
1969 const CoinIndexedVector &update,
1970 CoinPartitionedVector &tableauRow, CoinPartitionedVector &candidateList) const
1971 {
1972 double upperTheta = upperThetaResult;
1973 #if 0
1974 double time0=CoinCpuTime();
1975 #endif
1976 int maximumRows = model_->maximumAbcNumberRows();
1977 int firstIn = startColumnBlock_[iBlock];
1978 int last = startColumnBlock_[iBlock + 1];
1979 int numberNonZero;
1980 int numberRemaining;
1981 int first;
1982 if (firstIn == 0) {
1983 upperTheta = static_cast< AbcSimplexDual * >(model_)->dualColumn1A();
1984 numberNonZero = tableauRow.getNumElements(0);
1985 numberRemaining = candidateList.getNumElements(0);
1986 first = maximumRows;
1987 } else {
1988 first = firstIn;
1989 numberNonZero = first;
1990 numberRemaining = first;
1991 }
1992 sequenceIn = -1;
1993 // get matrix data pointers
1994 const int *COIN_RESTRICT row = matrix_->getIndices();
1995 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
1996 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
1997 const double *COIN_RESTRICT pi = update.denseVector();
1998 //const int * COIN_RESTRICT piIndex = update.getIndices();
1999 int *COIN_RESTRICT index = tableauRow.getIndices();
2000 double *COIN_RESTRICT array = tableauRow.denseVector();
2001 // pivot elements
2002 double *COIN_RESTRICT arrayCandidate = candidateList.denseVector();
2003 // indices
2004 int *COIN_RESTRICT indexCandidate = candidateList.getIndices();
2005 const double *COIN_RESTRICT abcDj = model_->djRegion();
2006 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
2007 // do first pass to get possibles
2008 double bestPossible = 0.0;
2009 // We can also see if infeasible or pivoting on free
2010 double tentativeTheta = 1.0e25; // try with this much smaller as guess
2011 double acceptablePivot = model_->currentAcceptablePivot();
2012 double dualT = -model_->currentDualTolerance();
2013 const double multiplier[] = { 1.0, -1.0 };
2014 double zeroTolerance = model_->zeroTolerance();
2015 if (model_->ordinaryVariables()) {
2016 #ifdef COUNT_COPY
2017 if (first > maximumRows || last < model_->numberTotal() || false) {
2018 #endif
2019 #if 1
2020 for (int iSequence = first; iSequence < last; iSequence++) {
2021 unsigned char iStatus = internalStatus[iSequence] & 7;
2022 if (iStatus < 4) {
2023 CoinBigIndex start = columnStart[iSequence];
2024 CoinBigIndex next = columnStart[iSequence + 1];
2025 double tableauValue = 0.0;
2026 for (CoinBigIndex j = start; j < next; j++) {
2027 int jRow = row[j];
2028 tableauValue += pi[jRow] * elementByColumn[j];
2029 }
2030 if (fabs(tableauValue) > zeroTolerance) {
2031 #else
2032 cilk_for(int iSequence = first; iSequence < last; iSequence++)
2033 {
2034 unsigned char iStatus = internalStatus[iSequence] & 7;
2035 if (iStatus < 4) {
2036 CoinBigIndex start = columnStart[iSequence];
2037 CoinBigIndex next = columnStart[iSequence + 1];
2038 double tableauValue = 0.0;
2039 for (CoinBigIndex j = start; j < next; j++) {
2040 int jRow = row[j];
2041 tableauValue += pi[jRow] * elementByColumn[j];
2042 }
2043 array[iSequence] = tableauValue;
2044 }
2045 }
2046 //printf("time %.6g\n",CoinCpuTime()-time0);
2047 for (int iSequence = first; iSequence < last; iSequence++) {
2048 double tableauValue = array[iSequence];
2049 if (tableauValue) {
2050 array[iSequence] = 0.0;
2051 if (fabs(tableauValue) > zeroTolerance) {
2052 unsigned char iStatus = internalStatus[iSequence] & 7;
2053 #endif
2054 index[numberNonZero] = iSequence;
2055 array[numberNonZero++] = tableauValue;
2056 double mult = multiplier[iStatus];
2057 double alpha = tableauValue * mult;
2058 double oldValue = abcDj[iSequence] * mult;
2059 double value = oldValue - tentativeTheta * alpha;
2060 if (value < dualT) {
2061 bestPossible = CoinMax(bestPossible, alpha);
2062 value = oldValue - upperTheta * alpha;
2063 if (value < dualT && alpha >= acceptablePivot) {
2064 upperTheta = (oldValue - dualT) / alpha;
2065 }
2066 // add to list
2067 arrayCandidate[numberRemaining] = alpha;
2068 indexCandidate[numberRemaining++] = iSequence;
2069 }
2070 }
2071 }
2072 }
2073 #ifdef COUNT_COPY
2074 } else {
2075 const double *COIN_RESTRICT element = countElement_;
2076 const int *COIN_RESTRICT row = countRow_;
2077 double temp[4] __attribute__((aligned(32)));
2078 memset(temp, 0, sizeof(temp));
2079 for (int iCount = smallestCount_; iCount < largestCount_; iCount++) {
2080 int iStart = countFirst_[iCount];
2081 int number = countFirst_[iCount + 1] - iStart;
2082 if (!number)
2083 continue;
2084 const int *COIN_RESTRICT blockRow = row + countStart_[iCount];
2085 const double *COIN_RESTRICT blockElement = element + countStart_[iCount];
2086 const int *COIN_RESTRICT sequence = countRealColumn_ + iStart;
2087 // really need to sort and swap to avoid tests
2088 int numberBlocks = number >> 2;
2089 number &= 3;
2090 for (int iBlock = 0; iBlock < numberBlocks; iBlock++) {
2091 double tableauValue0 = 0.0;
2092 double tableauValue1 = 0.0;
2093 double tableauValue2 = 0.0;
2094 double tableauValue3 = 0.0;
2095 for (int j = 0; j < iCount; j++) {
2096 tableauValue0 += pi[blockRow[0]] * blockElement[0];
2097 tableauValue1 += pi[blockRow[1]] * blockElement[1];
2098 tableauValue2 += pi[blockRow[2]] * blockElement[2];
2099 tableauValue3 += pi[blockRow[3]] * blockElement[3];
2100 blockRow += 4;
2101 blockElement += 4;
2102 }
2103 if (fabs(tableauValue0) > zeroTolerance) {
2104 int iSequence = sequence[0];
2105 unsigned char iStatus = internalStatus[iSequence] & 7;
2106 if (iStatus < 4) {
2107 index[numberNonZero] = iSequence;
2108 array[numberNonZero++] = tableauValue0;
2109 double mult = multiplier[iStatus];
2110 double alpha = tableauValue0 * mult;
2111 double oldValue = abcDj[iSequence] * mult;
2112 double value = oldValue - tentativeTheta * alpha;
2113 if (value < dualT) {
2114 bestPossible = CoinMax(bestPossible, alpha);
2115 value = oldValue - upperTheta * alpha;
2116 if (value < dualT && alpha >= acceptablePivot) {
2117 upperTheta = (oldValue - dualT) / alpha;
2118 }
2119 // add to list
2120 arrayCandidate[numberRemaining] = alpha;
2121 indexCandidate[numberRemaining++] = iSequence;
2122 }
2123 }
2124 }
2125 if (fabs(tableauValue1) > zeroTolerance) {
2126 int iSequence = sequence[1];
2127 unsigned char iStatus = internalStatus[iSequence] & 7;
2128 if (iStatus < 4) {
2129 index[numberNonZero] = iSequence;
2130 array[numberNonZero++] = tableauValue1;
2131 double mult = multiplier[iStatus];
2132 double alpha = tableauValue1 * mult;
2133 double oldValue = abcDj[iSequence] * mult;
2134 double value = oldValue - tentativeTheta * alpha;
2135 if (value < dualT) {
2136 bestPossible = CoinMax(bestPossible, alpha);
2137 value = oldValue - upperTheta * alpha;
2138 if (value < dualT && alpha >= acceptablePivot) {
2139 upperTheta = (oldValue - dualT) / alpha;
2140 }
2141 // add to list
2142 arrayCandidate[numberRemaining] = alpha;
2143 indexCandidate[numberRemaining++] = iSequence;
2144 }
2145 }
2146 }
2147 if (fabs(tableauValue2) > zeroTolerance) {
2148 int iSequence = sequence[2];
2149 unsigned char iStatus = internalStatus[iSequence] & 7;
2150 if (iStatus < 4) {
2151 index[numberNonZero] = iSequence;
2152 array[numberNonZero++] = tableauValue2;
2153 double mult = multiplier[iStatus];
2154 double alpha = tableauValue2 * mult;
2155 double oldValue = abcDj[iSequence] * mult;
2156 double value = oldValue - tentativeTheta * alpha;
2157 if (value < dualT) {
2158 bestPossible = CoinMax(bestPossible, alpha);
2159 value = oldValue - upperTheta * alpha;
2160 if (value < dualT && alpha >= acceptablePivot) {
2161 upperTheta = (oldValue - dualT) / alpha;
2162 }
2163 // add to list
2164 arrayCandidate[numberRemaining] = alpha;
2165 indexCandidate[numberRemaining++] = iSequence;
2166 }
2167 }
2168 }
2169 if (fabs(tableauValue3) > zeroTolerance) {
2170 int iSequence = sequence[3];
2171 unsigned char iStatus = internalStatus[iSequence] & 7;
2172 if (iStatus < 4) {
2173 index[numberNonZero] = iSequence;
2174 array[numberNonZero++] = tableauValue3;
2175 double mult = multiplier[iStatus];
2176 double alpha = tableauValue3 * mult;
2177 double oldValue = abcDj[iSequence] * mult;
2178 double value = oldValue - tentativeTheta * alpha;
2179 if (value < dualT) {
2180 bestPossible = CoinMax(bestPossible, alpha);
2181 value = oldValue - upperTheta * alpha;
2182 if (value < dualT && alpha >= acceptablePivot) {
2183 upperTheta = (oldValue - dualT) / alpha;
2184 }
2185 // add to list
2186 arrayCandidate[numberRemaining] = alpha;
2187 indexCandidate[numberRemaining++] = iSequence;
2188 }
2189 }
2190 }
2191 sequence += 4;
2192 }
2193 for (int i = 0; i < number; i++) {
2194 int iSequence = sequence[i];
2195 unsigned char iStatus = internalStatus[iSequence] & 7;
2196 if (iStatus < 4) {
2197 double tableauValue = 0.0;
2198 for (int j = 0; j < iCount; j++) {
2199 int iRow = blockRow[4 * j];
2200 tableauValue += pi[iRow] * blockElement[4 * j];
2201 }
2202 if (fabs(tableauValue) > zeroTolerance) {
2203 index[numberNonZero] = iSequence;
2204 array[numberNonZero++] = tableauValue;
2205 double mult = multiplier[iStatus];
2206 double alpha = tableauValue * mult;
2207 double oldValue = abcDj[iSequence] * mult;
2208 double value = oldValue - tentativeTheta * alpha;
2209 if (value < dualT) {
2210 bestPossible = CoinMax(bestPossible, alpha);
2211 value = oldValue - upperTheta * alpha;
2212 if (value < dualT && alpha >= acceptablePivot) {
2213 upperTheta = (oldValue - dualT) / alpha;
2214 }
2215 // add to list
2216 arrayCandidate[numberRemaining] = alpha;
2217 indexCandidate[numberRemaining++] = iSequence;
2218 }
2219 }
2220 }
2221 blockRow++;
2222 blockElement++;
2223 }
2224 }
2225 int numberColumns = model_->numberColumns();
2226 // large ones
2227 const CoinBigIndex *COIN_RESTRICT largeStart = countStartLarge_ - countFirst_[MAX_COUNT];
2228 for (int i = countFirst_[MAX_COUNT]; i < numberColumns; i++) {
2229 int iSequence = countRealColumn_[i];
2230 unsigned char iStatus = internalStatus[iSequence] & 7;
2231 if (iStatus < 4) {
2232 CoinBigIndex start = largeStart[i];
2233 CoinBigIndex next = largeStart[i + 1];
2234 double tableauValue = 0.0;
2235 for (CoinBigIndex j = start; j < next; j++) {
2236 int jRow = row[j];
2237 tableauValue += pi[jRow] * element[j];
2238 }
2239 if (fabs(tableauValue) > zeroTolerance) {
2240 index[numberNonZero] = iSequence;
2241 array[numberNonZero++] = tableauValue;
2242 double mult = multiplier[iStatus];
2243 double alpha = tableauValue * mult;
2244 double oldValue = abcDj[iSequence] * mult;
2245 double value = oldValue - tentativeTheta * alpha;
2246 if (value < dualT) {
2247 bestPossible = CoinMax(bestPossible, alpha);
2248 value = oldValue - upperTheta * alpha;
2249 if (value < dualT && alpha >= acceptablePivot) {
2250 upperTheta = (oldValue - dualT) / alpha;
2251 }
2252 // add to list
2253 arrayCandidate[numberRemaining] = alpha;
2254 indexCandidate[numberRemaining++] = iSequence;
2255 }
2256 }
2257 }
2258 }
2259 }
2260 #endif
2261 } else {
2262 double badFree = 0.0;
2263 double freePivot = model_->currentAcceptablePivot();
2264 int freeSequenceIn = model_->freeSequenceIn();
2265 double currentDualTolerance = model_->currentDualTolerance();
2266 for (int iSequence = first; iSequence < last; iSequence++) {
2267 unsigned char iStatus = internalStatus[iSequence] & 7;
2268 if (iStatus < 6) {
2269 CoinBigIndex start = columnStart[iSequence];
2270 CoinBigIndex next = columnStart[iSequence + 1];
2271 double tableauValue = 0.0;
2272 for (CoinBigIndex j = start; j < next; j++) {
2273 int jRow = row[j];
2274 tableauValue += pi[jRow] * elementByColumn[j];
2275 }
2276 if (fabs(tableauValue) > zeroTolerance) {
2277 if ((iStatus & 4) == 0) {
2278 index[numberNonZero] = iSequence;
2279 array[numberNonZero++] = tableauValue;
2280 double mult = multiplier[iStatus];
2281 double alpha = tableauValue * mult;
2282 double oldValue = abcDj[iSequence] * mult;
2283 double value = oldValue - tentativeTheta * alpha;
2284 if (value < dualT) {
2285 bestPossible = CoinMax(bestPossible, alpha);
2286 value = oldValue - upperTheta * alpha;
2287 if (value < dualT && alpha >= acceptablePivot) {
2288 upperTheta = (oldValue - dualT) / alpha;
2289 }
2290 // add to list
2291 arrayCandidate[numberRemaining] = alpha;
2292 indexCandidate[numberRemaining++] = iSequence;
2293 }
2294 } else {
2295 bool keep;
2296 index[numberNonZero] = iSequence;
2297 array[numberNonZero++] = tableauValue;
2298 bestPossible = CoinMax(bestPossible, fabs(tableauValue));
2299 double oldValue = abcDj[iSequence];
2300 // If free has to be very large - should come in via dualRow
2301 //if (getInternalStatus(iSequence+addSequence)==isFree&&fabs(tableauValue)<1.0e-3)
2302 //break;
2303 if (oldValue > currentDualTolerance) {
2304 keep = true;
2305 } else if (oldValue < -currentDualTolerance) {
2306 keep = true;
2307 } else {
2308 if (fabs(tableauValue) > CoinMax(10.0 * acceptablePivot, 1.0e-5)) {
2309 keep = true;
2310 } else {
2311 keep = false;
2312 badFree = CoinMax(badFree, fabs(tableauValue));
2313 }
2314 }
2315 if (keep) {
2316 #ifdef PAN
2317 if (model_->fakeSuperBasic(iSequence) >= 0) {
2318 #endif
2319 if (iSequence == freeSequenceIn)
2320 tableauValue = COIN_DBL_MAX;
2321 // free - choose largest
2322 if (fabs(tableauValue) > fabs(freePivot)) {
2323 freePivot = tableauValue;
2324 sequenceIn = iSequence;
2325 }
2326 #ifdef PAN
2327 }
2328 #endif
2329 }
2330 }
2331 }
2332 }
2333 }
2334 }
2335 // adjust
2336 numberNonZero -= firstIn;
2337 numberRemaining -= firstIn;
2338 tableauRow.setNumElementsPartition(iBlock, numberNonZero);
2339 candidateList.setNumElementsPartition(iBlock, numberRemaining);
2340 if (!numberRemaining && model_->sequenceIn() < 0) {
2341
2342 upperThetaResult = COIN_DBL_MAX; // Looks infeasible
2343 } else {
2344 upperThetaResult = upperTheta;
2345 }
2346 }
2347 // gets tableau row - returns number of slacks in block
2348 int AbcMatrix::primalColumnRow(int iBlock, bool doByRow, const CoinIndexedVector &updates,
2349 CoinPartitionedVector &tableauRow) const
2350 {
2351 int maximumRows = model_->maximumAbcNumberRows();
2352 int first = tableauRow.startPartition(iBlock);
2353 int last = tableauRow.startPartition(iBlock + 1);
2354 if (doByRow) {
2355 assert(first == blockStart_[iBlock]);
2356 assert(last == blockStart_[iBlock + 1]);
2357 } else {
2358 assert(first == startColumnBlock_[iBlock]);
2359 assert(last == startColumnBlock_[iBlock + 1]);
2360 }
2361 int numberSlacks = updates.getNumElements();
2362 int numberNonZero = 0;
2363 const double *COIN_RESTRICT pi = updates.denseVector();
2364 const int *COIN_RESTRICT piIndex = updates.getIndices();
2365 int *COIN_RESTRICT index = tableauRow.getIndices() + first;
2366 double *COIN_RESTRICT array = tableauRow.denseVector() + first;
2367 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
2368 if (!iBlock) {
2369 numberNonZero = numberSlacks;
2370 for (int i = 0; i < numberSlacks; i++) {
2371 int iRow = piIndex[i];
2372 index[i] = iRow;
2373 array[i] = pi[iRow]; // ? what if small or basic
2374 }
2375 first = maximumRows;
2376 }
2377 double zeroTolerance = model_->zeroTolerance();
2378 if (doByRow) {
2379 int numberRows = model_->numberRows();
2380 const CoinBigIndex *COIN_RESTRICT rowStart = rowStart_ + iBlock * numberRows;
2381 const CoinBigIndex *COIN_RESTRICT rowEnd = rowStart + numberRows;
2382 const double *COIN_RESTRICT element = element_;
2383 const int *COIN_RESTRICT column = column_;
2384 if (numberSlacks > 1) {
2385 double *COIN_RESTRICT arrayTemp = tableauRow.denseVector();
2386 for (int i = 0; i < numberSlacks; i++) {
2387 int iRow = piIndex[i];
2388 double piValue = pi[iRow];
2389 CoinBigIndex end = rowEnd[iRow];
2390 for (CoinBigIndex j = rowStart[iRow]; j < end; j++) {
2391 int iColumn = column[j];
2392 arrayTemp[iColumn] += element[j] * piValue;
2393 }
2394 }
2395 for (int iSequence = first; iSequence < last; iSequence++) {
2396 double tableauValue = arrayTemp[iSequence];
2397 if (tableauValue) {
2398 arrayTemp[iSequence] = 0.0;
2399 if (fabs(tableauValue) > zeroTolerance) {
2400 unsigned char iStatus = internalStatus[iSequence] & 7;
2401 if (iStatus < 6) {
2402 index[numberNonZero] = iSequence;
2403 array[numberNonZero++] = tableauValue;
2404 }
2405 }
2406 }
2407 }
2408 } else {
2409 int iRow = piIndex[0];
2410 double piValue = pi[iRow];
2411 CoinBigIndex end = rowEnd[iRow];
2412 for (CoinBigIndex j = rowStart[iRow]; j < end; j++) {
2413 int iSequence = column[j];
2414 double tableauValue = element[j] * piValue;
2415 if (fabs(tableauValue) > zeroTolerance) {
2416 unsigned char iStatus = internalStatus[iSequence] & 7;
2417 if (iStatus < 6) {
2418 index[numberNonZero] = iSequence;
2419 array[numberNonZero++] = tableauValue;
2420 }
2421 }
2422 }
2423 }
2424 } else {
2425 // get matrix data pointers
2426 const int *COIN_RESTRICT row = matrix_->getIndices();
2427 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
2428 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
2429 const double *COIN_RESTRICT pi = updates.denseVector();
2430 for (int iSequence = first; iSequence < last; iSequence++) {
2431 unsigned char iStatus = internalStatus[iSequence] & 7;
2432 if (iStatus < 6) {
2433 CoinBigIndex start = columnStart[iSequence];
2434 CoinBigIndex next = columnStart[iSequence + 1];
2435 double tableauValue = 0.0;
2436 for (CoinBigIndex j = start; j < next; j++) {
2437 int jRow = row[j];
2438 tableauValue += pi[jRow] * elementByColumn[j];
2439 }
2440 if (fabs(tableauValue) > zeroTolerance) {
2441 index[numberNonZero] = iSequence;
2442 array[numberNonZero++] = tableauValue;
2443 }
2444 }
2445 }
2446 }
2447 tableauRow.setNumElementsPartition(iBlock, numberNonZero);
2448 return numberSlacks;
2449 }
2450 // Get sequenceIn when Dantzig
2451 int AbcMatrix::pivotColumnDantzig(const CoinIndexedVector &updates,
2452 CoinPartitionedVector &spare) const
2453 {
2454 int maximumRows = model_->maximumAbcNumberRows();
2455 // rebalance
2456 rebalance();
2457 spare.setPackedMode(true);
2458 bool useRowCopy = false;
2459 if (rowStart_) {
2460 // see if worth using row copy
2461 int number = updates.getNumElements();
2462 assert(number);
2463 useRowCopy = (number << 2) < maximumRows;
2464 }
2465 const int *starts;
2466 if (useRowCopy)
2467 starts = blockStart();
2468 else
2469 starts = startColumnBlock();
2470 #if ABC_PARALLEL
2471 #define NUMBER_BLOCKS NUMBER_ROW_BLOCKS
2472 int numberBlocks = CoinMin(NUMBER_BLOCKS, model_->numberCpus());
2473 #else
2474 #define NUMBER_BLOCKS 1
2475 int numberBlocks = NUMBER_BLOCKS;
2476 #endif
2477 #if ABC_PARALLEL
2478 if (model_->parallelMode() == 0)
2479 numberBlocks = 1;
2480 #endif
2481 spare.setPartitions(numberBlocks, starts);
2482 int which[NUMBER_BLOCKS];
2483 double best[NUMBER_BLOCKS];
2484 for (int i = 0; i < numberBlocks - 1; i++)
2485 which[i] = cilk_spawn pivotColumnDantzig(i, useRowCopy, updates, spare, best[i]);
2486 which[numberBlocks - 1] = pivotColumnDantzig(numberBlocks - 1, useRowCopy, updates,
2487 spare, best[numberBlocks - 1]);
2488 cilk_sync;
2489 int bestSequence = -1;
2490 double bestValue = model_->dualTolerance();
2491 for (int i = 0; i < numberBlocks; i++) {
2492 if (best[i] > bestValue) {
2493 bestValue = best[i];
2494 bestSequence = which[i];
2495 }
2496 }
2497 return bestSequence;
2498 }
2499 // Get sequenceIn when Dantzig (One block)
2500 int AbcMatrix::pivotColumnDantzig(int iBlock, bool doByRow, const CoinIndexedVector &updates,
2501 CoinPartitionedVector &spare,
2502 double &bestValue) const
2503 {
2504 // could rewrite to do more directly
2505 int numberSlacks = primalColumnRow(iBlock, doByRow, updates, spare);
2506 double *COIN_RESTRICT reducedCost = model_->djRegion();
2507 int first = spare.startPartition(iBlock);
2508 int last = spare.startPartition(iBlock + 1);
2509 int *COIN_RESTRICT index = spare.getIndices() + first;
2510 double *COIN_RESTRICT array = spare.denseVector() + first;
2511 int numberNonZero = spare.getNumElements(iBlock);
2512 int bestSequence = -1;
2513 double bestDj = model_->dualTolerance();
2514 double bestFreeDj = model_->dualTolerance();
2515 int bestFreeSequence = -1;
2516 // redo LOTS so signs for slacks and columns same
2517 if (!first) {
2518 first = model_->maximumAbcNumberRows();
2519 for (int i = 0; i < numberSlacks; i++) {
2520 int iSequence = index[i];
2521 double value = reducedCost[iSequence];
2522 value += array[i];
2523 array[i] = 0.0;
2524 reducedCost[iSequence] = value;
2525 }
2526 #ifndef CLP_PRIMAL_SLACK_MULTIPLIER
2527 #define CLP_PRIMAL_SLACK_MULTIPLIER 1.0
2528 #endif
2529 int numberRows = model_->numberRows();
2530 for (int iSequence = 0; iSequence < numberRows; iSequence++) {
2531 // check flagged variable
2532 if (!model_->flagged(iSequence)) {
2533 double value = reducedCost[iSequence] * CLP_PRIMAL_SLACK_MULTIPLIER;
2534 AbcSimplex::Status status = model_->getInternalStatus(iSequence);
2535
2536 switch (status) {
2537
2538 case AbcSimplex::basic:
2539 case AbcSimplex::isFixed:
2540 break;
2541 case AbcSimplex::isFree:
2542 case AbcSimplex::superBasic:
2543 if (fabs(value) > bestFreeDj) {
2544 bestFreeDj = fabs(value);
2545 bestFreeSequence = iSequence;
2546 }
2547 break;
2548 case AbcSimplex::atUpperBound:
2549 if (value > bestDj) {
2550 bestDj = value;
2551 bestSequence = iSequence;
2552 }
2553 break;
2554 case AbcSimplex::atLowerBound:
2555 if (value < -bestDj) {
2556 bestDj = -value;
2557 bestSequence = iSequence;
2558 }
2559 }
2560 }
2561 }
2562 }
2563 for (int i = numberSlacks; i < numberNonZero; i++) {
2564 int iSequence = index[i];
2565 double value = reducedCost[iSequence];
2566 value += array[i];
2567 array[i] = 0.0;
2568 reducedCost[iSequence] = value;
2569 }
2570 for (int iSequence = first; iSequence < last; iSequence++) {
2571 // check flagged variable
2572 if (!model_->flagged(iSequence)) {
2573 double value = reducedCost[iSequence];
2574 AbcSimplex::Status status = model_->getInternalStatus(iSequence);
2575
2576 switch (status) {
2577
2578 case AbcSimplex::basic:
2579 case AbcSimplex::isFixed:
2580 break;
2581 case AbcSimplex::isFree:
2582 case AbcSimplex::superBasic:
2583 if (fabs(value) > bestFreeDj) {
2584 bestFreeDj = fabs(value);
2585 bestFreeSequence = iSequence;
2586 }
2587 break;
2588 case AbcSimplex::atUpperBound:
2589 if (value > bestDj) {
2590 bestDj = value;
2591 bestSequence = iSequence;
2592 }
2593 break;
2594 case AbcSimplex::atLowerBound:
2595 if (value < -bestDj) {
2596 bestDj = -value;
2597 bestSequence = iSequence;
2598 }
2599 }
2600 }
2601 }
2602 spare.setNumElementsPartition(iBlock, 0);
2603 // bias towards free
2604 if (bestFreeSequence >= 0 && bestFreeDj > 0.1 * bestDj) {
2605 bestSequence = bestFreeSequence;
2606 bestDj = 10.0 * bestFreeDj;
2607 }
2608 bestValue = bestDj;
2609 return bestSequence;
2610 }
2611 // gets tableau row and dj row - returns number of slacks in block
2612 int AbcMatrix::primalColumnRowAndDjs(int iBlock, const CoinIndexedVector &updateTableau,
2613 const CoinIndexedVector &updateDjs,
2614 CoinPartitionedVector &tableauRow) const
2615 {
2616 int maximumRows = model_->maximumAbcNumberRows();
2617 int first = tableauRow.startPartition(iBlock);
2618 int last = tableauRow.startPartition(iBlock + 1);
2619 assert(first == startColumnBlock_[iBlock]);
2620 assert(last == startColumnBlock_[iBlock + 1]);
2621 int numberSlacks = updateTableau.getNumElements();
2622 int numberNonZero = 0;
2623 const double *COIN_RESTRICT piTableau = updateTableau.denseVector();
2624 const double *COIN_RESTRICT pi = updateDjs.denseVector();
2625 int *COIN_RESTRICT index = tableauRow.getIndices() + first;
2626 double *COIN_RESTRICT array = tableauRow.denseVector() + first;
2627 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
2628 double *COIN_RESTRICT reducedCost = model_->djRegion();
2629 if (!iBlock) {
2630 const int *COIN_RESTRICT piIndexTableau = updateTableau.getIndices();
2631 numberNonZero = numberSlacks;
2632 for (int i = 0; i < numberSlacks; i++) {
2633 int iRow = piIndexTableau[i];
2634 index[i] = iRow;
2635 array[i] = piTableau[iRow]; // ? what if small or basic
2636 }
2637 const int *COIN_RESTRICT piIndex = updateDjs.getIndices();
2638 int number = updateDjs.getNumElements();
2639 for (int i = 0; i < number; i++) {
2640 int iRow = piIndex[i];
2641 reducedCost[iRow] -= pi[iRow]; // sign?
2642 }
2643 first = maximumRows;
2644 }
2645 double zeroTolerance = model_->zeroTolerance();
2646 // get matrix data pointers
2647 const int *COIN_RESTRICT row = matrix_->getIndices();
2648 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
2649 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
2650 for (int iSequence = first; iSequence < last; iSequence++) {
2651 unsigned char iStatus = internalStatus[iSequence] & 7;
2652 if (iStatus < 6) {
2653 CoinBigIndex start = columnStart[iSequence];
2654 CoinBigIndex next = columnStart[iSequence + 1];
2655 double tableauValue = 0.0;
2656 double djValue = reducedCost[iSequence];
2657 for (CoinBigIndex j = start; j < next; j++) {
2658 int jRow = row[j];
2659 tableauValue += piTableau[jRow] * elementByColumn[j];
2660 djValue -= pi[jRow] * elementByColumn[j]; // sign?
2661 }
2662 reducedCost[iSequence] = djValue;
2663 if (fabs(tableauValue) > zeroTolerance) {
2664 index[numberNonZero] = iSequence;
2665 array[numberNonZero++] = tableauValue;
2666 }
2667 }
2668 }
2669 tableauRow.setNumElementsPartition(iBlock, numberNonZero);
2670 return numberSlacks;
2671 }
2672 /* does steepest edge double or triple update
2673 If scaleFactor!=0 then use with tableau row to update djs
2674 otherwise use updateForDjs
2675 */
2676 int AbcMatrix::primalColumnDouble(int iBlock, CoinPartitionedVector &updateForTableauRow,
2677 CoinPartitionedVector &updateForDjs,
2678 const CoinIndexedVector &updateForWeights,
2679 CoinPartitionedVector &spareColumn1,
2680 double *infeasibilities,
2681 double referenceIn, double devex,
2682 // Array for exact devex to say what is in reference framework
2683 unsigned int *reference,
2684 double *weights, double scaleFactor) const
2685 {
2686 int maximumRows = model_->maximumAbcNumberRows();
2687 int first = startColumnBlock_[iBlock];
2688 int last = startColumnBlock_[iBlock + 1];
2689 const double *COIN_RESTRICT piTableau = updateForTableauRow.denseVector();
2690 const double *COIN_RESTRICT pi = updateForDjs.denseVector();
2691 const double *COIN_RESTRICT piWeights = updateForWeights.denseVector();
2692 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
2693 double *COIN_RESTRICT reducedCost = model_->djRegion();
2694 double tolerance = model_->currentDualTolerance();
2695 // use spareColumn to track new infeasibilities
2696 int *COIN_RESTRICT newInfeas = spareColumn1.getIndices() + first;
2697 int numberNewInfeas = 0;
2698 // we can't really trust infeasibilities if there is dual error
2699 // this coding has to mimic coding in checkDualSolution
2700 double error = CoinMin(1.0e-2, model_->largestDualError());
2701 // allow tolerance at least slightly bigger than standard
2702 tolerance = tolerance + error;
2703 double mult[2] = { 1.0, -1.0 };
2704 bool updateWeights = devex != 0.0;
2705 #define isReference(i) (((reference[i >> 5] >> (i & 31)) & 1) != 0)
2706 // Scale factor is other way round so tableau row is 1.0* while dj update is scaleFactor*
2707 if (!iBlock) {
2708 int numberSlacks = updateForTableauRow.getNumElements();
2709 const int *COIN_RESTRICT piIndexTableau = updateForTableauRow.getIndices();
2710 if (!scaleFactor) {
2711 const int *COIN_RESTRICT piIndex = updateForDjs.getIndices();
2712 int number = updateForDjs.getNumElements();
2713 for (int i = 0; i < number; i++) {
2714 int iRow = piIndex[i];
2715 int iStatus = internalStatus[iRow] & 7;
2716 double value = reducedCost[iRow];
2717 value += pi[iRow];
2718 if (iStatus < 4) {
2719 reducedCost[iRow] = value;
2720 value *= mult[iStatus];
2721 if (value < 0.0) {
2722 if (!infeasibilities[iRow])
2723 newInfeas[numberNewInfeas++] = iRow;
2724 #ifdef CLP_PRIMAL_SLACK_MULTIPLIER
2725 infeasibilities[iRow] = value * value * CLP_PRIMAL_SLACK_MULTIPLIER;
2726 #else
2727 infeasibilities[iRow] = value * value;
2728 #endif
2729 } else {
2730 if (infeasibilities[iRow])
2731 infeasibilities[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT;
2732 }
2733 }
2734 }
2735 } else if (scaleFactor != COIN_DBL_MAX) {
2736 for (int i = 0; i < numberSlacks; i++) {
2737 int iRow = piIndexTableau[i];
2738 int iStatus = internalStatus[iRow] & 7;
2739 if (iStatus < 4) {
2740 double value = reducedCost[iRow];
2741 value += scaleFactor * piTableau[iRow]; // sign?
2742 reducedCost[iRow] = value;
2743 value *= mult[iStatus];
2744 if (value < 0.0) {
2745 if (!infeasibilities[iRow])
2746 newInfeas[numberNewInfeas++] = iRow;
2747 #ifdef CLP_PRIMAL_SLACK_MULTIPLIER
2748 infeasibilities[iRow] = value * value * CLP_PRIMAL_SLACK_MULTIPLIER;
2749 #else
2750 infeasibilities[iRow] = value * value;
2751 #endif
2752 } else {
2753 if (infeasibilities[iRow])
2754 infeasibilities[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT;
2755 }
2756 }
2757 }
2758 }
2759 if (updateWeights) {
2760 for (int i = 0; i < numberSlacks; i++) {
2761 int iRow = piIndexTableau[i];
2762 double modification = piWeights[iRow];
2763 double thisWeight = weights[iRow];
2764 double pivot = piTableau[iRow];
2765 double pivotSquared = pivot * pivot;
2766 thisWeight += pivotSquared * devex - pivot * modification;
2767 if (thisWeight < DEVEX_TRY_NORM) {
2768 if (referenceIn < 0.0) {
2769 // steepest
2770 thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared);
2771 } else {
2772 // exact
2773 thisWeight = referenceIn * pivotSquared;
2774 if (isReference(iRow))
2775 thisWeight += 1.0;
2776 thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM);
2777 }
2778 }
2779 weights[iRow] = thisWeight;
2780 }
2781 }
2782 first = maximumRows;
2783 }
2784 double zeroTolerance = model_->zeroTolerance();
2785 double freeTolerance = FREE_ACCEPT * tolerance;
2786 ;
2787 // get matrix data pointers
2788 const int *COIN_RESTRICT row = matrix_->getIndices();
2789 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
2790 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
2791 bool updateDjs = scaleFactor != COIN_DBL_MAX;
2792 for (int iSequence = first; iSequence < last; iSequence++) {
2793 unsigned char iStatus = internalStatus[iSequence] & 7;
2794 if (iStatus < 6) {
2795 CoinBigIndex start = columnStart[iSequence];
2796 CoinBigIndex next = columnStart[iSequence + 1];
2797 double tableauValue = 0.0;
2798 double djValue = reducedCost[iSequence];
2799 if (!scaleFactor) {
2800 for (CoinBigIndex j = start; j < next; j++) {
2801 int jRow = row[j];
2802 tableauValue += piTableau[jRow] * elementByColumn[j];
2803 djValue += pi[jRow] * elementByColumn[j];
2804 }
2805 } else {
2806 for (CoinBigIndex j = start; j < next; j++) {
2807 int jRow = row[j];
2808 tableauValue += piTableau[jRow] * elementByColumn[j];
2809 }
2810 djValue += tableauValue * scaleFactor; // sign?
2811 }
2812 if (updateDjs) {
2813 reducedCost[iSequence] = djValue;
2814 if (iStatus < 4) {
2815 djValue *= mult[iStatus];
2816 if (djValue < 0.0) {
2817 if (!infeasibilities[iSequence])
2818 newInfeas[numberNewInfeas++] = iSequence;
2819 infeasibilities[iSequence] = djValue * djValue;
2820 } else {
2821 if (infeasibilities[iSequence])
2822 infeasibilities[iSequence] = COIN_INDEXED_REALLY_TINY_ELEMENT;
2823 }
2824 } else {
2825 if (fabs(djValue) > freeTolerance) {
2826 // we are going to bias towards free (but only if reasonable)
2827 djValue *= FREE_BIAS;
2828 if (!infeasibilities[iSequence])
2829 newInfeas[numberNewInfeas++] = iSequence;
2830 // store square in list
2831 infeasibilities[iSequence] = djValue * djValue;
2832 } else {
2833 if (infeasibilities[iSequence])
2834 infeasibilities[iSequence] = COIN_INDEXED_REALLY_TINY_ELEMENT;
2835 }
2836 }
2837 }
2838 if (fabs(tableauValue) > zeroTolerance && updateWeights) {
2839 double modification = 0.0;
2840 for (CoinBigIndex j = start; j < next; j++) {
2841 int jRow = row[j];
2842 modification += piWeights[jRow] * elementByColumn[j];
2843 }
2844 double thisWeight = weights[iSequence];
2845 double pivot = tableauValue;
2846 double pivotSquared = pivot * pivot;
2847 thisWeight += pivotSquared * devex - pivot * modification;
2848 if (thisWeight < DEVEX_TRY_NORM) {
2849 if (referenceIn < 0.0) {
2850 // steepest
2851 thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared);
2852 } else {
2853 // exact
2854 thisWeight = referenceIn * pivotSquared;
2855 if (isReference(iSequence))
2856 thisWeight += 1.0;
2857 thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM);
2858 }
2859 }
2860 weights[iSequence] = thisWeight;
2861 }
2862 }
2863 }
2864 spareColumn1.setTempNumElementsPartition(iBlock, numberNewInfeas);
2865 int bestSequence = -1;
2866 #if 0
2867 if (!iBlock)
2868 first=0;
2869 // not at present - maybe later
2870 double bestDj=tolerance*tolerance;
2871 for (int iSequence=first;iSequence<last;iSequence++) {
2872 if (infeasibilities[iSequence]>bestDj*weights[iSequence]) {
2873 int iStatus=internalStatus[iSequence]&7;
2874 assert (iStatus<6);
2875 bestSequence=iSequence;
2876 bestDj=infeasibilities[iSequence]/weights[iSequence];
2877 }
2878 }
2879 #endif
2880 return bestSequence;
2881 }
2882 /* does steepest edge double or triple update
2883 If scaleFactor!=0 then use with tableau row to update djs
2884 otherwise use updateForDjs
2885 */
2886 int AbcMatrix::primalColumnSparseDouble(int iBlock, CoinPartitionedVector &updateForTableauRow,
2887 CoinPartitionedVector &updateForDjs,
2888 const CoinIndexedVector &updateForWeights,
2889 CoinPartitionedVector &spareColumn1,
2890 double *infeasibilities,
2891 double referenceIn, double devex,
2892 // Array for exact devex to say what is in reference framework
2893 unsigned int *reference,
2894 double *weights, double scaleFactor) const
2895 {
2896 int maximumRows = model_->maximumAbcNumberRows();
2897 int first = blockStart_[iBlock];
2898 //int last=blockStart_[iBlock+1];
2899 const double *COIN_RESTRICT piTableau = updateForTableauRow.denseVector();
2900 //const double * COIN_RESTRICT pi=updateForDjs.denseVector();
2901 const double *COIN_RESTRICT piWeights = updateForWeights.denseVector();
2902 const unsigned char *COIN_RESTRICT internalStatus = model_->internalStatus();
2903 double *COIN_RESTRICT reducedCost = model_->djRegion();
2904 double tolerance = model_->currentDualTolerance();
2905 // use spareColumn to track new infeasibilities
2906 int *COIN_RESTRICT newInfeas = spareColumn1.getIndices() + first;
2907 int numberNewInfeas = 0;
2908 // we can't really trust infeasibilities if there is dual error
2909 // this coding has to mimic coding in checkDualSolution
2910 double error = CoinMin(1.0e-2, model_->largestDualError());
2911 // allow tolerance at least slightly bigger than standard
2912 tolerance = tolerance + error;
2913 double mult[2] = { 1.0, -1.0 };
2914 bool updateWeights = devex != 0.0;
2915 int numberSlacks = updateForTableauRow.getNumElements();
2916 const int *COIN_RESTRICT piIndexTableau = updateForTableauRow.getIndices();
2917 #define isReference(i) (((reference[i >> 5] >> (i & 31)) & 1) != 0)
2918 // Scale factor is other way round so tableau row is 1.0* while dj update is scaleFactor*
2919 assert(scaleFactor);
2920 if (!iBlock) {
2921 if (scaleFactor != COIN_DBL_MAX) {
2922 for (int i = 0; i < numberSlacks; i++) {
2923 int iRow = piIndexTableau[i];
2924 int iStatus = internalStatus[iRow] & 7;
2925 if (iStatus < 4) {
2926 double value = reducedCost[iRow];
2927 value += scaleFactor * piTableau[iRow]; // sign?
2928 reducedCost[iRow] = value;
2929 value *= mult[iStatus];
2930 if (value < 0.0) {
2931 if (!infeasibilities[iRow])
2932 newInfeas[numberNewInfeas++] = iRow;
2933 #ifdef CLP_PRIMAL_SLACK_MULTIPLIER
2934 infeasibilities[iRow] = value * value * CLP_PRIMAL_SLACK_MULTIPLIER;
2935 #else
2936 infeasibilities[iRow] = value * value;
2937 #endif
2938 } else {
2939 if (infeasibilities[iRow])
2940 infeasibilities[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT;
2941 }
2942 }
2943 }
2944 }
2945 if (updateWeights) {
2946 for (int i = 0; i < numberSlacks; i++) {
2947 int iRow = piIndexTableau[i];
2948 double modification = piWeights[iRow];
2949 double thisWeight = weights[iRow];
2950 double pivot = piTableau[iRow];
2951 double pivotSquared = pivot * pivot;
2952 thisWeight += pivotSquared * devex - pivot * modification;
2953 if (thisWeight < DEVEX_TRY_NORM) {
2954 if (referenceIn < 0.0) {
2955 // steepest
2956 thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared);
2957 } else {
2958 // exact
2959 thisWeight = referenceIn * pivotSquared;
2960 if (isReference(iRow))
2961 thisWeight += 1.0;
2962 thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM);
2963 }
2964 }
2965 weights[iRow] = thisWeight;
2966 }
2967 }
2968 first = maximumRows;
2969 }
2970 double zeroTolerance = model_->zeroTolerance();
2971 double freeTolerance = FREE_ACCEPT * tolerance;
2972 ;
2973 // get matrix data pointers
2974 const int *COIN_RESTRICT row = matrix_->getIndices();
2975 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
2976 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
2977 // get tableau row
2978 int *COIN_RESTRICT index = updateForTableauRow.getIndices() + first;
2979 double *COIN_RESTRICT array = updateForTableauRow.denseVector();
2980 int numberRows = model_->numberRows();
2981 const CoinBigIndex *COIN_RESTRICT rowStart = rowStart_ + iBlock * numberRows;
2982 const CoinBigIndex *COIN_RESTRICT rowEnd = rowStart + numberRows;
2983 const double *COIN_RESTRICT element = element_;
2984 const int *COIN_RESTRICT column = column_;
2985 int numberInRow = 0;
2986 if (numberSlacks > 2) {
2987 for (int i = 0; i < numberSlacks; i++) {
2988 int iRow = piIndexTableau[i];
2989 double piValue = piTableau[iRow];
2990 CoinBigIndex end = rowEnd[iRow];
2991 for (CoinBigIndex j = rowStart[iRow]; j < end; j++) {
2992 int iSequence = column[j];
2993 double value = element[j] * piValue;
2994 double oldValue = array[iSequence];
2995 value += oldValue;
2996 if (!oldValue) {
2997 array[iSequence] = value;
2998 index[numberInRow++] = iSequence;
2999 } else if (value) {
3000 array[iSequence] = value;
3001 } else {
3002 array[iSequence] = COIN_INDEXED_REALLY_TINY_ELEMENT;
3003 }
3004 }
3005 }
3006 } else if (numberSlacks == 2) {
3007 int iRow0 = piIndexTableau[0];
3008 int iRow1 = piIndexTableau[1];
3009 CoinBigIndex end0 = rowEnd[iRow0];
3010 CoinBigIndex end1 = rowEnd[iRow1];
3011 if (end0 - rowStart[iRow0] > end1 - rowStart[iRow1]) {
3012 int temp = iRow0;
3013 iRow0 = iRow1;
3014 iRow1 = temp;
3015 }
3016 CoinBigIndex start = rowStart[iRow0];
3017 CoinBigIndex end = rowEnd[iRow0];
3018 double piValue = piTableau[iRow0];
3019 for (CoinBigIndex j = start; j < end; j++) {
3020 int iSequence = column[j];
3021 double value = element[j];
3022 array[iSequence] = piValue * value;
3023 index[numberInRow++] = iSequence;
3024 }
3025 start = rowStart[iRow1];
3026 end = rowEnd[iRow1];
3027 piValue = piTableau[iRow1];
3028 for (CoinBigIndex j = start; j < end; j++) {
3029 int iSequence = column[j];
3030 double value = element[j];
3031 value *= piValue;
3032 if (!array[iSequence]) {
3033 array[iSequence] = value;
3034 index[numberInRow++] = iSequence;
3035 } else {
3036 value += array[iSequence];
3037 if (value)
3038 array[iSequence] = value;
3039 else
3040 array[iSequence] = COIN_INDEXED_REALLY_TINY_ELEMENT;
3041 }
3042 }
3043 } else {
3044 int iRow0 = piIndexTableau[0];
3045 CoinBigIndex start = rowStart[iRow0];
3046 CoinBigIndex end = rowEnd[iRow0];
3047 double piValue = piTableau[iRow0];
3048 for (CoinBigIndex j = start; j < end; j++) {
3049 int iSequence = column[j];
3050 double value = element[j];
3051 array[iSequence] = piValue * value;
3052 index[numberInRow++] = iSequence;
3053 }
3054 }
3055 bool updateDjs = scaleFactor != COIN_DBL_MAX;
3056 for (int iLook = 0; iLook < numberInRow; iLook++) {
3057 int iSequence = index[iLook];
3058 unsigned char iStatus = internalStatus[iSequence] & 7;
3059 if (iStatus < 6) {
3060 double tableauValue = array[iSequence];
3061 array[iSequence] = 0.0;
3062 double djValue = reducedCost[iSequence];
3063 djValue += tableauValue * scaleFactor; // sign?
3064 if (updateDjs) {
3065 reducedCost[iSequence] = djValue;
3066 if (iStatus < 4) {
3067 djValue *= mult[iStatus];
3068 if (djValue < 0.0) {
3069 if (!infeasibilities[iSequence])
3070 newInfeas[numberNewInfeas++] = iSequence;
3071 infeasibilities[iSequence] = djValue * djValue;
3072 } else {
3073 if (infeasibilities[iSequence])
3074 infeasibilities[iSequence] = COIN_INDEXED_REALLY_TINY_ELEMENT;
3075 }
3076 } else {
3077 if (fabs(djValue) > freeTolerance) {
3078 // we are going to bias towards free (but only if reasonable)
3079 djValue *= FREE_BIAS;
3080 if (!infeasibilities[iSequence])
3081 newInfeas[numberNewInfeas++] = iSequence;
3082 // store square in list
3083 infeasibilities[iSequence] = djValue * djValue;
3084 } else {
3085 if (infeasibilities[iSequence])
3086 infeasibilities[iSequence] = COIN_INDEXED_REALLY_TINY_ELEMENT;
3087 }
3088 }
3089 }
3090 if (fabs(tableauValue) > zeroTolerance && updateWeights) {
3091 CoinBigIndex start = columnStart[iSequence];
3092 CoinBigIndex next = columnStart[iSequence + 1];
3093 double modification = 0.0;
3094 for (CoinBigIndex j = start; j < next; j++) {
3095 int jRow = row[j];
3096 modification += piWeights[jRow] * elementByColumn[j];
3097 }
3098 double thisWeight = weights[iSequence];
3099 double pivot = tableauValue;
3100 double pivotSquared = pivot * pivot;
3101 thisWeight += pivotSquared * devex - pivot * modification;
3102 if (thisWeight < DEVEX_TRY_NORM) {
3103 if (referenceIn < 0.0) {
3104 // steepest
3105 thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared);
3106 } else {
3107 // exact
3108 thisWeight = referenceIn * pivotSquared;
3109 if (isReference(iSequence))
3110 thisWeight += 1.0;
3111 thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM);
3112 }
3113 }
3114 weights[iSequence] = thisWeight;
3115 }
3116 } else {
3117 array[iSequence] = 0.0;
3118 }
3119 }
3120 spareColumn1.setTempNumElementsPartition(iBlock, numberNewInfeas);
3121 int bestSequence = -1;
3122 #if 0
3123 if (!iBlock)
3124 first=0;
3125 // not at present - maybe later
3126 double bestDj=tolerance*tolerance;
3127 for (int iSequence=first;iSequence<last;iSequence++) {
3128 if (infeasibilities[iSequence]>bestDj*weights[iSequence]) {
3129 int iStatus=internalStatus[iSequence]&7;
3130 assert (iStatus<6);
3131 bestSequence=iSequence;
3132 bestDj=infeasibilities[iSequence]/weights[iSequence];
3133 }
3134 }
3135 #endif
3136 return bestSequence;
3137 }
3138 #if 0
3139 /* Chooses best weighted dj
3140 */
3141 int
3142 AbcMatrix::chooseBestDj(int iBlock,const CoinIndexedVector & infeasibilities,
3143 const double * weights) const
3144 {
3145 return 0;
3146 }
3147 #endif
3148 /* does steepest edge double or triple update
3149 If scaleFactor!=0 then use with tableau row to update djs
3150 otherwise use updateForDjs
3151 Returns best
3152 */
3153 int AbcMatrix::primalColumnDouble(CoinPartitionedVector &updateForTableauRow,
3154 CoinPartitionedVector &updateForDjs,
3155 const CoinIndexedVector &updateForWeights,
3156 CoinPartitionedVector &spareColumn1,
3157 CoinIndexedVector &infeasible,
3158 double referenceIn, double devex,
3159 // Array for exact devex to say what is in reference framework
3160 unsigned int *reference,
3161 double *weights, double scaleFactor) const
3162 {
3163 //int maximumRows = model_->maximumAbcNumberRows();
3164 // rebalance
3165 rebalance();
3166 #ifdef PRICE_IN_ABC_MATRIX
3167 int which[NUMBER_BLOCKS];
3168 #endif
3169 double *infeasibilities = infeasible.denseVector();
3170 int bestSequence = -1;
3171 // see if worth using row copy
3172 int maximumRows = model_->maximumAbcNumberRows();
3173 int number = updateForTableauRow.getNumElements();
3174 #ifdef GCC_4_9
3175 assert(number);
3176 #else
3177 if (!number) {
3178 printf("Null tableau row!\n");
3179 }
3180 #endif
3181 bool useRowCopy = (gotRowCopy() && (number << 2) < maximumRows);
3182 //useRowCopy=false;
3183 if (!scaleFactor)
3184 useRowCopy = false; // look again later
3185 const int *starts;
3186 int numberBlocks;
3187 if (useRowCopy) {
3188 starts = blockStart_;
3189 numberBlocks = numberRowBlocks_;
3190 } else {
3191 starts = startColumnBlock_;
3192 numberBlocks = numberColumnBlocks_;
3193 }
3194 if (useRowCopy) {
3195 for (int i = 0; i < numberBlocks; i++)
3196 #ifdef PRICE_IN_ABC_MATRIX
3197 which[i] =
3198 #endif
3199 cilk_spawn primalColumnSparseDouble(i, updateForTableauRow, updateForDjs, updateForWeights,
3200 spareColumn1,
3201 infeasibilities, referenceIn, devex, reference, weights, scaleFactor);
3202 cilk_sync;
3203 } else {
3204 for (int i = 0; i < numberBlocks; i++)
3205 #ifdef PRICE_IN_ABC_MATRIX
3206 which[i] =
3207 #endif
3208 cilk_spawn primalColumnDouble(i, updateForTableauRow, updateForDjs, updateForWeights,
3209 spareColumn1,
3210 infeasibilities, referenceIn, devex, reference, weights, scaleFactor);
3211 cilk_sync;
3212 }
3213 #ifdef PRICE_IN_ABC_MATRIX
3214 double bestValue = model_->dualTolerance();
3215 int sequenceIn[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
3216 #endif
3217 assert(numberColumnBlocks_ <= 8);
3218 #ifdef PRICE_IN_ABC_MATRIX
3219 double weightedDj[8];
3220 int nPossible = 0;
3221 #endif
3222 //const double * reducedCost = model_->djRegion();
3223 // use spareColumn to track new infeasibilities
3224 int numberInfeas = infeasible.getNumElements();
3225 int *COIN_RESTRICT infeas = infeasible.getIndices();
3226 const int *COIN_RESTRICT newInfeasAll = spareColumn1.getIndices();
3227 for (int i = 0; i < numberColumnBlocks_; i++) {
3228 const int *COIN_RESTRICT newInfeas = newInfeasAll + starts[i];
3229 int numberNewInfeas = spareColumn1.getNumElements(i);
3230 spareColumn1.setTempNumElementsPartition(i, 0);
3231 for (int j = 0; j < numberNewInfeas; j++)
3232 infeas[numberInfeas++] = newInfeas[j];
3233 #ifdef PRICE_IN_ABC_MATRIX
3234 if (which[i] >= 0) {
3235 int iSequence = which[i];
3236 double value = fabs(infeasibilities[iSequence] / weights[iSequence]);
3237 if (value > bestValue) {
3238 bestValue = value;
3239 bestSequence = which[i];
3240 }
3241 weightedDj[nPossible] = -value;
3242 sequenceIn[nPossible++] = iSequence;
3243 }
3244 #endif
3245 }
3246 infeasible.setNumElements(numberInfeas);
3247 #ifdef PRICE_IN_ABC_MATRIX
3248 CoinSort_2(weightedDj, weightedDj + nPossible, sequenceIn);
3249 //model_->setMultipleSequenceIn(sequenceIn);
3250 #endif
3251 return bestSequence;
3252 }
3253 // Partial pricing
3254 void AbcMatrix::partialPricing(double startFraction, double endFraction,
3255 int &bestSequence, int &numberWanted)
3256 {
3257 numberWanted = currentWanted_;
3258 int maximumRows = model_->maximumAbcNumberRows();
3259 // get matrix data pointers
3260 const int *COIN_RESTRICT row = matrix_->getIndices();
3261 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
3262 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
3263 int numberColumns = model_->numberColumns();
3264 int start = static_cast< int >(startFraction * numberColumns);
3265 int end = CoinMin(static_cast< int >(endFraction * numberColumns + 1), numberColumns);
3266 // adjust
3267 start += maximumRows;
3268 end += maximumRows;
3269 double tolerance = model_->currentDualTolerance();
3270 double *reducedCost = model_->djRegion();
3271 const double *duals = model_->dualRowSolution();
3272 const double *cost = model_->costRegion();
3273 double bestDj;
3274 if (bestSequence >= 0)
3275 bestDj = fabs(reducedCost[bestSequence]);
3276 else
3277 bestDj = tolerance;
3278 int sequenceOut = model_->sequenceOut();
3279 int saveSequence = bestSequence;
3280 int lastScan = minimumObjectsScan_ < 0 ? end : start + minimumObjectsScan_;
3281 int minNeg = minimumGoodReducedCosts_ == -1 ? numberWanted : minimumGoodReducedCosts_;
3282 for (int iSequence = start; iSequence < end; iSequence++) {
3283 if (iSequence != sequenceOut) {
3284 double value;
3285 AbcSimplex::Status status = model_->getInternalStatus(iSequence);
3286 switch (status) {
3287 case AbcSimplex::basic:
3288 case AbcSimplex::isFixed:
3289 break;
3290 case AbcSimplex::isFree:
3291 case AbcSimplex::superBasic:
3292 value = cost[iSequence];
3293 for (CoinBigIndex j = columnStart[iSequence];
3294 j < columnStart[iSequence + 1]; j++) {
3295 int jRow = row[j];
3296 value -= duals[jRow] * elementByColumn[j];
3297 }
3298 value = fabs(value);
3299 if (value > FREE_ACCEPT * tolerance) {
3300 numberWanted--;
3301 // we are going to bias towards free (but only if reasonable)
3302 value *= FREE_BIAS;
3303 if (value > bestDj) {
3304 // check flagged variable and correct dj
3305 if (!model_->flagged(iSequence)) {
3306 bestDj = value;
3307 bestSequence = iSequence;
3308 } else {
3309 // just to make sure we don't exit before got something
3310 numberWanted++;
3311 }
3312 }
3313 }
3314 break;
3315 case AbcSimplex::atUpperBound:
3316 value = cost[iSequence];
3317 // scaled
3318 for (CoinBigIndex j = columnStart[iSequence];
3319 j < columnStart[iSequence + 1]; j++) {
3320 int jRow = row[j];
3321 value -= duals[jRow] * elementByColumn[j];
3322 }
3323 if (value > tolerance) {
3324 numberWanted--;
3325 if (value > bestDj) {
3326 // check flagged variable and correct dj
3327 if (!model_->flagged(iSequence)) {
3328 bestDj = value;
3329 bestSequence = iSequence;
3330 } else {
3331 // just to make sure we don't exit before got something
3332 numberWanted++;
3333 }
3334 }
3335 }
3336 break;
3337 case AbcSimplex::atLowerBound:
3338 value = cost[iSequence];
3339 for (CoinBigIndex j = columnStart[iSequence];
3340 j < columnStart[iSequence + 1]; j++) {
3341 int jRow = row[j];
3342 value -= duals[jRow] * elementByColumn[j];
3343 }
3344 value = -value;
3345 if (value > tolerance) {
3346 numberWanted--;
3347 if (value > bestDj) {
3348 // check flagged variable and correct dj
3349 if (!model_->flagged(iSequence)) {
3350 bestDj = value;
3351 bestSequence = iSequence;
3352 } else {
3353 // just to make sure we don't exit before got something
3354 numberWanted++;
3355 }
3356 }
3357 }
3358 break;
3359 }
3360 }
3361 if (numberWanted + minNeg < originalWanted_ && iSequence > lastScan) {
3362 // give up
3363 break;
3364 }
3365 if (!numberWanted)
3366 break;
3367 }
3368 if (bestSequence != saveSequence) {
3369 // recompute dj
3370 double value = cost[bestSequence];
3371 for (CoinBigIndex j = columnStart[bestSequence];
3372 j < columnStart[bestSequence + 1]; j++) {
3373 int jRow = row[j];
3374 value -= duals[jRow] * elementByColumn[j];
3375 }
3376 reducedCost[bestSequence] = value;
3377 savedBestSequence_ = bestSequence;
3378 savedBestDj_ = reducedCost[savedBestSequence_];
3379 }
3380 currentWanted_ = numberWanted;
3381 }
3382 /* Return <code>x *A</code> in <code>z</code> but
3383 just for indices Already in z.
3384 Note - z always packed mode */
3385 void AbcMatrix::subsetTransposeTimes(const CoinIndexedVector &x,
3386 CoinIndexedVector &z) const
3387 {
3388 int maximumRows = model_->maximumAbcNumberRows();
3389 // get matrix data pointers
3390 const int *COIN_RESTRICT row = matrix_->getIndices();
3391 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
3392 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
3393 const double *COIN_RESTRICT other = x.denseVector();
3394 int numberNonZero = z.getNumElements();
3395 int *COIN_RESTRICT index = z.getIndices();
3396 double *COIN_RESTRICT array = z.denseVector();
3397 int numberRows = model_->numberRows();
3398 for (int i = 0; i < numberNonZero; i++) {
3399 int iSequence = index[i];
3400 if (iSequence >= numberRows) {
3401 CoinBigIndex start = columnStart[iSequence];
3402 CoinBigIndex next = columnStart[iSequence + 1];
3403 double value = 0.0;
3404 for (CoinBigIndex j = start; j < next; j++) {
3405 int jRow = row[j];
3406 value -= other[jRow] * elementByColumn[j];
3407 }
3408 array[i] = value;
3409 } else {
3410 array[i] = -other[iSequence];
3411 }
3412 }
3413 }
3414 // Return <code>-x *A</code> in <code>z</code>
3415 void AbcMatrix::transposeTimes(const CoinIndexedVector &x,
3416 CoinIndexedVector &z) const
3417 {
3418 int maximumRows = model_->maximumAbcNumberRows();
3419 // get matrix data pointers
3420 const int *COIN_RESTRICT row = matrix_->getIndices();
3421 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
3422 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
3423 const double *COIN_RESTRICT other = x.denseVector();
3424 int numberNonZero = 0;
3425 int *COIN_RESTRICT index = z.getIndices();
3426 double *COIN_RESTRICT array = z.denseVector();
3427 int numberColumns = model_->numberColumns();
3428 double zeroTolerance = model_->zeroTolerance();
3429 for (int iSequence = maximumRows; iSequence < maximumRows + numberColumns; iSequence++) {
3430 CoinBigIndex start = columnStart[iSequence];
3431 CoinBigIndex next = columnStart[iSequence + 1];
3432 double value = 0.0;
3433 for (CoinBigIndex j = start; j < next; j++) {
3434 int jRow = row[j];
3435 value -= other[jRow] * elementByColumn[j];
3436 }
3437 if (fabs(value) > zeroTolerance) {
3438 // TEMP
3439 array[iSequence - maximumRows] = value;
3440 index[numberNonZero++] = iSequence - maximumRows;
3441 }
3442 }
3443 z.setNumElements(numberNonZero);
3444 }
3445 /* Return A * scalar(+-1) *x + y</code> in <code>y</code>.
3446 @pre <code>x</code> must be of size <code>numRows()</code>
3447 @pre <code>y</code> must be of size <code>numRows()+numColumns()</code> */
3448 void AbcMatrix::transposeTimesNonBasic(double scalar,
3449 const double *pi, double *y) const
3450 {
3451 int numberTotal = model_->numberTotal();
3452 int maximumRows = model_->maximumAbcNumberRows();
3453 assert(scalar == -1.0);
3454 // get matrix data pointers
3455 const int *COIN_RESTRICT row = matrix_->getIndices();
3456 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
3457 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
3458 int numberRows = model_->numberRows();
3459 const unsigned char *COIN_RESTRICT status = model_->internalStatus();
3460 for (int i = 0; i < numberRows; i++) {
3461 y[i] += scalar * pi[i];
3462 }
3463 for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) {
3464 unsigned char type = status[iColumn] & 7;
3465 if (type < 6) {
3466 CoinBigIndex start = columnStart[iColumn];
3467 CoinBigIndex next = columnStart[iColumn + 1];
3468 double value = 0.0;
3469 for (CoinBigIndex j = start; j < next; j++) {
3470 int jRow = row[j];
3471 value += scalar * pi[jRow] * elementByColumn[j];
3472 }
3473 y[iColumn] += value;
3474 } else {
3475 y[iColumn] = 0.0; // may not be but .....
3476 }
3477 }
3478 }
3479 /* Return y - A * x</code> in <code>y</code>.
3480 @pre <code>x</code> must be of size <code>numRows()</code>
3481 @pre <code>y</code> must be of size <code>numRows()+numColumns()</code> */
3482 void AbcMatrix::transposeTimesAll(const double *pi, double *y) const
3483 {
3484 int numberTotal = model_->numberTotal();
3485 int maximumRows = model_->maximumAbcNumberRows();
3486 // get matrix data pointers
3487 const int *COIN_RESTRICT row = matrix_->getIndices();
3488 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - maximumRows;
3489 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
3490 int numberRows = model_->numberRows();
3491 for (int i = 0; i < numberRows; i++) {
3492 y[i] -= pi[i];
3493 }
3494 for (int iColumn = maximumRows; iColumn < numberTotal; iColumn++) {
3495 CoinBigIndex start = columnStart[iColumn];
3496 CoinBigIndex next = columnStart[iColumn + 1];
3497 double value = 0.0;
3498 for (CoinBigIndex j = start; j < next; j++) {
3499 int jRow = row[j];
3500 value += pi[jRow] * elementByColumn[j];
3501 }
3502 y[iColumn] -= value;
3503 }
3504 }
3505 /* Return y + A * scalar(+-1) *x</code> in <code>y</code>.
3506 @pre <code>x</code> must be of size <code>numRows()</code>
3507 @pre <code>y</code> must be of size <code>numRows()</code> */
3508 void AbcMatrix::transposeTimesBasic(double scalar,
3509 const double *pi, double *y) const
3510 {
3511 assert(scalar == -1.0);
3512 int numberRows = model_->numberRows();
3513 //AbcMemset0(y,numberRows);
3514 // get matrix data pointers
3515 const int *COIN_RESTRICT row = matrix_->getIndices();
3516 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts() - model_->maximumAbcNumberRows();
3517 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
3518 const int *COIN_RESTRICT pivotVariable = model_->pivotVariable();
3519 for (int i = 0; i < numberRows; i++) {
3520 int iSequence = pivotVariable[i];
3521 double value;
3522 if (iSequence >= numberRows) {
3523 CoinBigIndex start = columnStart[iSequence];
3524 CoinBigIndex next = columnStart[iSequence + 1];
3525 value = 0.0;
3526 for (CoinBigIndex j = start; j < next; j++) {
3527 int jRow = row[j];
3528 value += pi[jRow] * elementByColumn[j];
3529 }
3530 } else {
3531 value = pi[iSequence];
3532 }
3533 y[i] += scalar * value;
3534 }
3535 }
3536 // Adds multiple of a column (or slack) into an CoinIndexedvector
3537 void AbcMatrix::add(CoinIndexedVector &rowArray, int iSequence, double multiplier) const
3538 {
3539 int maximumRows = model_->maximumAbcNumberRows();
3540 if (iSequence >= maximumRows) {
3541 const int *COIN_RESTRICT row = matrix_->getIndices();
3542 iSequence -= maximumRows;
3543 const CoinBigIndex *COIN_RESTRICT columnStart = matrix_->getVectorStarts();
3544 const double *COIN_RESTRICT elementByColumn = matrix_->getElements();
3545 CoinBigIndex start = columnStart[iSequence];
3546 CoinBigIndex next = columnStart[iSequence + 1];
3547 for (CoinBigIndex j = start; j < next; j++) {
3548 int jRow = row[j];
3549 rowArray.quickAdd(jRow, elementByColumn[j] * multiplier);
3550 }
3551 } else {
3552 rowArray.quickAdd(iSequence, multiplier);
3553 }
3554 }
3555 /* Unpacks a column into an CoinIndexedVector
3556 */
3557 void AbcMatrix::unpack(CoinIndexedVector &usefulArray,
3558 int sequence) const
3559 {
3560 usefulArray.clear();
3561 int maximumRows = model_->maximumAbcNumberRows();
3562 if (sequence < maximumRows) {
3563 //slack
3564 usefulArray.insert(sequence, 1.0);
3565 } else {
3566 // column
3567 const CoinBigIndex *COIN_RESTRICT columnStart = matrix()->getVectorStarts() - maximumRows;
3568 CoinBigIndex start = columnStart[sequence];
3569 CoinBigIndex end = columnStart[sequence + 1];
3570 const int *COIN_RESTRICT row = matrix()->getIndices() + start;
3571 const double *COIN_RESTRICT elementByColumn = matrix()->getElements() + start;
3572 int *COIN_RESTRICT index = usefulArray.getIndices();
3573 double *COIN_RESTRICT array = usefulArray.denseVector();
3574 int numberNonZero = end - start;
3575 for (int j = 0; j < numberNonZero; j++) {
3576 int iRow = row[j];
3577 index[j] = iRow;
3578 array[iRow] = elementByColumn[j];
3579 }
3580 usefulArray.setNumElements(numberNonZero);
3581 }
3582 }
3583 // Row starts
3584 CoinBigIndex *
3585 AbcMatrix::rowStart() const
3586 {
3587 return rowStart_;
3588 }
3589 // Row ends
3590 CoinBigIndex *
3591 AbcMatrix::rowEnd() const
3592 {
3593 //if (numberRowBlocks_<2) {
3594 //return rowStart_+1;
3595 //} else {
3596 return rowStart_ + model_->numberRows() * (numberRowBlocks_ + 1);
3597 //}
3598 }
3599 // Row elements
3600 double *
3601 AbcMatrix::rowElements() const
3602 {
3603 return element_;
3604 }
3605 // Row columnss
3606 CoinSimplexInt *
3607 AbcMatrix::rowColumns() const
3608 {
3609 return column_;
3610 }
3611
3612 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
3613 */
3614