/* $Id$ */ // Copyright (C) 2002, International Business Machines // Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifdef ABC_JUST_ONE_FACTORIZATION #include "CoinAbcCommonFactorization.hpp" #define CoinAbcTypeFactorization CoinAbcBaseFactorization #define ABC_SMALL -1 #include "CoinAbcBaseFactorization.hpp" #endif #ifdef CoinAbcTypeFactorization #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinAbcHelperFunctions.hpp" #if CILK_CONFLICT > 0 // for conflicts extern int cilk_conflict; #endif //:class CoinAbcTypeFactorization. Deals with Factorization and Updates #if ABC_SMALL < 2 // getColumnSpaceIterateR. Gets space for one extra R element in Column //may have to do compression (returns true) //also moves existing vector bool CoinAbcTypeFactorization::getColumnSpaceIterateR(CoinSimplexInt iColumn, CoinFactorizationDouble value, CoinSimplexInt iRow) { CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_ + lengthAreaR_; CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_ + lengthAreaR_; CoinBigIndex *COIN_RESTRICT startR = startColumnRAddress_ + maximumPivots_ + 1; CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; CoinSimplexInt number = numberInColumnPlus[iColumn]; //*** modify so sees if can go in //see if it can go in at end CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_; if (lengthAreaR_ - startR[maximumRowsExtra_] < number + 1) { //compression CoinSimplexInt jColumn = nextColumn[maximumRowsExtra_]; CoinBigIndex put = 0; while (jColumn != maximumRowsExtra_) { //move CoinBigIndex get; CoinBigIndex getEnd; get = startR[jColumn]; getEnd = get + numberInColumnPlus[jColumn]; startR[jColumn] = put; CoinBigIndex i; for (i = get; i < getEnd; i++) { indexRowR[put] = indexRowR[i]; elementR[put] = elementR[i]; put++; } jColumn = nextColumn[jColumn]; } numberCompressions_++; startR[maximumRowsExtra_] = put; } // Still may not be room (as iColumn was still in) if (lengthAreaR_ - startR[maximumRowsExtra_] < number + 1) return false; CoinSimplexInt next = nextColumn[iColumn]; CoinSimplexInt last = lastColumn[iColumn]; //out nextColumn[last] = next; lastColumn[next] = last; CoinBigIndex put = startR[maximumRowsExtra_]; //in at end last = lastColumn[maximumRowsExtra_]; nextColumn[last] = iColumn; lastColumn[maximumRowsExtra_] = iColumn; lastColumn[iColumn] = last; nextColumn[iColumn] = maximumRowsExtra_; //move CoinBigIndex get = startR[iColumn]; startR[iColumn] = put; CoinSimplexInt i = 0; for (i = 0; i < number; i++) { elementR[put] = elementR[get]; indexRowR[put++] = indexRowR[get++]; } //insert elementR[put] = value; indexRowR[put++] = iRow; numberInColumnPlus[iColumn]++; //add 4 for luck startR[maximumRowsExtra_] = CoinMin(static_cast< CoinBigIndex >(put + 4), lengthAreaR_); return true; } #endif CoinSimplexInt CoinAbcTypeFactorization::checkPivot(CoinSimplexDouble saveFromU, CoinSimplexDouble oldPivot) const { CoinSimplexInt status; if (fabs(saveFromU) > 1.0e-8) { CoinFactorizationDouble checkTolerance; if (numberRowsExtra_ < numberRows_ + 2) { checkTolerance = 1.0e-5; } else if (numberRowsExtra_ < numberRows_ + 10) { checkTolerance = 1.0e-6; } else if (numberRowsExtra_ < numberRows_ + 50) { checkTolerance = 1.0e-8; } else { checkTolerance = 1.0e-10; } checkTolerance *= relaxCheck_; if (fabs(1.0 - fabs(saveFromU / oldPivot)) < checkTolerance) { status = 0; } else { #if COIN_DEBUG std::cout << "inaccurate pivot " << oldPivot << " " << saveFromU << std::endl; #endif if (fabs(fabs(oldPivot) - fabs(saveFromU)) < 1.0e-12 || fabs(1.0 - fabs(saveFromU / oldPivot)) < 1.0e-8) { status = 1; } else { status = 2; } } } else { //error status = 2; #if COIN_DEBUG std::cout << "inaccurate pivot " << saveFromU / oldPivot << " " << saveFromU << std::endl; #endif } return status; } #define INLINE_IT #define INLINE_IT2 #define INLINE_IT3 #define UNROLL 0 inline void scatterUpdateInline(CoinSimplexInt number, CoinFactorizationDouble pivotValue, const CoinFactorizationDouble *COIN_RESTRICT thisElement, const CoinSimplexInt *COIN_RESTRICT thisIndex, CoinFactorizationDouble *COIN_RESTRICT region) { #if UNROLL == 0 for (CoinBigIndex j = number - 1; j >= 0; j--) { CoinSimplexInt iRow = thisIndex[j]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[j]; assert(value); region[iRow] = regionValue - value * pivotValue; } #elif UNROLL == 1 if ((number & 1) != 0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j = number - 1; j >= 0; j -= 2) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j - 1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j - 1] * pivotValue; } #elif UNROLL == 2 CoinSimplexInt iRow0; CoinSimplexInt iRow1; CoinFactorizationDouble regionValue0; CoinFactorizationDouble regionValue1; switch (number) { case 0: break; case 1: iRow0 = thisIndex[0]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; break; case 2: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; break; case 3: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; break; case 4: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; break; case 5: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; break; case 6: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; break; case 7: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; regionValue0 = region[iRow0]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; break; case 8: iRow0 = thisIndex[0]; iRow1 = thisIndex[1]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[0] * pivotValue; region[iRow1] = regionValue1 - thisElement[1] * pivotValue; iRow0 = thisIndex[2]; iRow1 = thisIndex[3]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[2] * pivotValue; region[iRow1] = regionValue1 - thisElement[3] * pivotValue; iRow0 = thisIndex[4]; iRow1 = thisIndex[5]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[4] * pivotValue; region[iRow1] = regionValue1 - thisElement[5] * pivotValue; iRow0 = thisIndex[6]; iRow1 = thisIndex[7]; regionValue0 = region[iRow0]; regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[6] * pivotValue; region[iRow1] = regionValue1 - thisElement[7] * pivotValue; break; default: if ((number & 1) != 0) { number--; CoinSimplexInt iRow = thisIndex[number]; CoinFactorizationDouble regionValue = region[iRow]; CoinFactorizationDouble value = thisElement[number]; region[iRow] = regionValue - value * pivotValue; } for (CoinBigIndex j = number - 1; j >= 0; j -= 2) { CoinSimplexInt iRow0 = thisIndex[j]; CoinSimplexInt iRow1 = thisIndex[j - 1]; CoinFactorizationDouble regionValue0 = region[iRow0]; CoinFactorizationDouble regionValue1 = region[iRow1]; region[iRow0] = regionValue0 - thisElement[j] * pivotValue; region[iRow1] = regionValue1 - thisElement[j - 1] * pivotValue; } break; } #endif } inline CoinFactorizationDouble gatherUpdate(CoinSimplexInt number, const CoinFactorizationDouble *COIN_RESTRICT thisElement, const CoinSimplexInt *COIN_RESTRICT thisIndex, CoinFactorizationDouble *COIN_RESTRICT region) { CoinFactorizationDouble pivotValue = 0.0; for (CoinBigIndex j = 0; j < number; j++) { CoinFactorizationDouble value = thisElement[j]; CoinSimplexInt jRow = thisIndex[j]; value *= region[jRow]; pivotValue -= value; } return pivotValue; } inline void multiplyIndexed(CoinSimplexInt number, const CoinFactorizationDouble *COIN_RESTRICT multiplier, const CoinSimplexInt *COIN_RESTRICT thisIndex, CoinFactorizationDouble *COIN_RESTRICT region) { for (CoinSimplexInt i = 0; i < number; i++) { CoinSimplexInt iRow = thisIndex[i]; CoinSimplexDouble value = region[iRow]; value *= multiplier[iRow]; region[iRow] = value; } } #if 0 /* Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots Fills in region for use later partial update already in U */ int CoinAbcTypeFactorization::checkReplace ( const AbcSimplex * model, CoinIndexedVector * regionSparse, int pivotRow, CoinSimplexDouble &pivotCheck, double acceptablePivot) { if ( lengthR_+numberRows_ >= lengthAreaR_ ) { //not enough room return 3; } #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #else CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) { //not enough room return 3; } #if ABC_SMALL < 2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; CoinFactorizationDouble oldPivot = pivotRegion[pivotRow]; // for accuracy check pivotCheck = pivotCheck / oldPivot; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL < 2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW > 2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL < 2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow; #if ABC_SMALL < 2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow<10) { CoinSimplexInt smallest=numberRowsExtra_; for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn]setNumElements ( numberNonZero ); if (numberNonZero) { assert (smallestIndex>=0); #ifndef NDEBUG const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; if (jRow!=smallestIndex) { while (jRow>=0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow=pivotLinked[jRow]; } assert (jRow==smallestIndex); } #endif //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL < 2 ,reinterpret_cast(btranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); } } else { #endif #if ABC_SMALL >= 0 // No row copy check space CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow); #endif #if ABC_SMALL < 2 } #endif numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; if ( iRow != pivotRow ) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } //check accuracy status = checkPivot(saveFromU,pivotCheck); if (status==1&&!numberPivots_) { printf("check status ok\n"); status=2; } pivotCheck=saveFromU; return status; } // replaceColumn. Replaces one Column to basis // returns 0=OK, 1=Probably OK, 2=singular, 3=no room //partial update already in U CoinSimplexInt CoinAbcTypeFactorization::replaceColumn ( CoinIndexedVector * regionSparse, CoinSimplexInt pivotRow, CoinSimplexDouble pivotCheck , bool skipBtranU, CoinSimplexDouble ) { assert (numberU_<=numberRowsExtra_); #ifndef ALWAYS_SKIP_BTRAN //return at once if too many iterations if ( numberRowsExtra_ >= maximumRowsExtra_ ) { return 5; } if ( lengthAreaU_ < lastEntryByColumnU_ ) { return 3; } #endif #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT elementU = elementUAddress_; #endif CoinSimplexInt * COIN_RESTRICT indexRowR = indexRowRAddress_; #if ABC_SMALL < 2 CoinSimplexInt * COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif #if ABC_SMALL < 2 CoinSimplexInt * COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; #endif CoinSimplexInt * COIN_RESTRICT permuteLookup = pivotColumnAddress_; CoinFactorizationDouble * COIN_RESTRICT region = denseVector(regionSparse); //take out old pivot column #ifndef ABC_USE_FUNCTION_POINTERS totalElements_ -= numberInColumn[pivotRow]; #else scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; totalElements_ -= scatter[pivotRow].number; CoinBigIndex saveStart = scatter[pivotRow].offset; CoinBigIndex saveEnd = scatter[pivotRow].number; scatter[pivotRow].offset=startU; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble * COIN_RESTRICT elementU2 = elementUColumnPlus+startU; CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #endif #ifndef ALWAYS_SKIP_BTRAN #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL < 2 CoinSimplexInt * COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex * COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW > 2 CoinBigIndex * COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL < 2 CoinFactorizationDouble * COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex * COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); CoinFactorizationDouble pivotValue = 1.0; CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt * COIN_RESTRICT indexRowU = indexRowUAddress_; #endif CoinFactorizationDouble * COIN_RESTRICT elementR = elementRAddress_; #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow; #if ABC_SMALL < 2 CoinBigIndex start=0; CoinBigIndex end=0; if (gotUCopy()) { start=startRowU[pivotRow]; nInRow=numberInRowU[pivotRow]; end= start + nInRow; } #endif CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ALWAYS_SKIP_BTRAN if (!skipBtranU) { CoinFactorizationDouble oldPivot = pivotRegion[pivotRow]; // for accuracy check pivotCheck = pivotCheck / oldPivot; #if ABC_SMALL < 2 if (gotUCopy()) { CoinSimplexInt smallestIndex=pivotLinkedForwardsAddress_[-1]; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow<10) { CoinSimplexInt smallest=numberRowsExtra_; for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn]setNumElements ( numberNonZero ); if (numberNonZero) { assert (smallestIndex>=0); #ifndef NDEBUG const CoinSimplexInt * COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow=pivotLinked[-1]; if (jRow!=smallestIndex) { while (jRow>=0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow=pivotLinked[jRow]; } assert (jRow==smallestIndex); } #endif //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU ( regionSparse, smallestIndex #if ABC_SMALL < 2 ,reinterpret_cast(btranCountInput_) #endif #if ABC_PARALLEL ,0 #endif ); } } else { #endif #if ABC_SMALL >= 0 // No row copy check space if ( lengthR_ + numberRows_>= lengthAreaR_ ) { //not enough room return 3; } CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); nInRow=replaceColumnU(regionSparse,deletedPosition,deletedColumns,pivotRow); #endif #if ABC_SMALL < 2 } #endif } #endif numberNonZero = regionSparse->getNumElements ( ); CoinFactorizationDouble saveFromU = 0.0; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startU = startColumnU[numberRows_]; startColumnU[pivotRow]=startU; CoinSimplexInt * COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble * COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #else //CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; #endif instrument_do("CoinAbcFactorizationReplaceColumn",2*numberRows_+4*numberInColumnU2); #ifndef ALWAYS_SKIP_BTRAN if (!skipBtranU) { for (CoinBigIndex i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; if ( iRow != pivotRow ) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } //check accuracy status = checkPivot(saveFromU,pivotCheck); } else { status=0; saveFromU=pivotCheck; } //regionSparse->print(); #endif if (status>1||(status==1&&!numberPivots_)) { // restore some things //pivotRegion[pivotRow] = oldPivot; CoinSimplexInt number = saveEnd-saveStart; totalElements_ += number; //numberInColumn[pivotRow]=number; regionSparse->clear(); return status; } else { pivotValue = 1.0 / saveFromU; // do what we would have done by now #if ABC_SMALL < 2 if (gotUCopy()) { for (CoinBigIndex i = start; i < end ; i ++ ) { CoinSimplexInt jColumn = indexColumnU[i]; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startColumn = startColumnU[jColumn]; #if CONVERTROW CoinBigIndex j = convertRowToColumn[i]; #else CoinBigIndex j; int number = numberInColumn[jColumn]; for (j=0;j(area+k+1); #if CONVERTROW CoinSimplexInt j = convertRowToColumn[i]; #else CoinSimplexInt j; for (j=0;j= 0 // no row copy CoinBigIndex COIN_RESTRICT * deletedPosition = reinterpret_cast(elementR+lengthR_); CoinSimplexInt COIN_RESTRICT * deletedColumns = reinterpret_cast(indexRowR+lengthR_); for (CoinSimplexInt i = 0; i < nInRow ; i ++ ) { CoinBigIndex j = deletedPosition[i]; CoinSimplexInt jColumn = deletedColumns[i]; // swap CoinSimplexInt k = numberInColumn[jColumn]-1; numberInColumn[jColumn]=k; CoinBigIndex k2 = k+startColumnU[jColumn]; int kRow2=indexRowU[k2]; indexRowU[j]=kRow2; CoinFactorizationDouble value2=elementU[k2]; elementU[j]=value2; } #endif #if ABC_SMALL < 2 } #endif } #if ABC_SMALL < 2 if (gotUCopy()) { // Now zero out column of U //take out old pivot column #ifdef ABC_USE_FUNCTION_POINTERS CoinFactorizationDouble * COIN_RESTRICT elementU = elementUColumnPlus+saveStart; saveStart=0; CoinSimplexInt * COIN_RESTRICT indexRowU = reinterpret_cast(elementU+saveEnd); #endif for (CoinBigIndex i = saveStart; i < saveEnd ; i ++ ) { //elementU[i] = 0.0; // If too slow then reverse meaning of convertRowToColumn and use int jRow=indexRowU[i]; CoinBigIndex start = startRowU[jRow]; CoinBigIndex end = start + numberInRowU[jRow]; for (CoinBigIndex j = start; j < end ; j ++ ) { CoinSimplexInt jColumn = indexColumnU[j]; if (jColumn==pivotRow) { // swap numberInRowU[jRow]--; elementRowU[j]=elementRowU[end-1]; #if CONVERTROW convertRowToColumn[j]=convertRowToColumn[end-1]; #endif indexColumnU[j]=indexColumnU[end-1]; break; } } } } #endif //zero out pivot Row (before or after?) //add to R CoinBigIndex * COIN_RESTRICT startColumnR = startColumnRAddress_; CoinBigIndex putR = lengthR_; CoinSimplexInt number = numberR_; startColumnR[number] = putR; //for luck and first time number++; //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2)); startColumnR[number] = putR + numberNonZero; numberR_ = number; lengthR_ = putR + numberNonZero; totalElements_ += numberNonZero; if ( lengthR_ >= lengthAreaR_ ) { //not enough room regionSparse->clear(); return 3; } if ( lengthU_+numberInColumnU2 >= lengthAreaU_ ) { //not enough room regionSparse->clear(); return 3; } #if ABC_SMALL < 2 CoinSimplexInt * COIN_RESTRICT nextRow=NULL; CoinSimplexInt * COIN_RESTRICT lastRow=NULL; CoinSimplexInt next; CoinSimplexInt last; if (gotUCopy()) { //take out row nextRow = nextRowAddress_; lastRow = lastRowAddress_; next = nextRow[pivotRow]; last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; numberInRowU[pivotRow]=0; } #endif //put in pivot //add row counts int n = 0; for (CoinSimplexInt i = 0; i < numberInColumnU2; i++ ) { CoinSimplexInt iRow = indexU2[i]; CoinFactorizationDouble value=elementU2[i]; assert (value); if ( !TEST_LESS_THAN_TOLERANCE(value ) ) { if ( iRow != pivotRow ) { //modify by pivot CoinFactorizationDouble value2 = value*pivotValue; indexU2[n]=iRow; elementU2[n++] = value2; #if ABC_SMALL < 2 if (gotUCopy()) { CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt iNumberInRow = numberInRowU[iRow]; CoinBigIndex space; CoinBigIndex put = startRowU[iRow] + iNumberInRow; space = startRowU[next] - put; if ( space <= 0 ) { getRowSpaceIterate ( iRow, iNumberInRow + 4 ); put = startRowU[iRow] + iNumberInRow; } else if (next==numberRows_) { lastEntryByRowU_=put+1; } indexColumnU[put] = pivotRow; #if CONVERTROW convertRowToColumn[put] = i; #endif elementRowU[put] = value2; numberInRowU[iRow] = iNumberInRow + 1; } #endif } else { //swap and save indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } else { // swap indexU2[i]=indexU2[numberInColumnU2-1]; elementU2[i] = elementU2[numberInColumnU2-1]; numberInColumnU2--; i--; } } numberInColumnU2=n; //do permute permuteAddress_[numberRowsExtra_] = pivotRow; //and for safety permuteAddress_[numberRowsExtra_ + 1] = 0; //pivotColumnAddress_[pivotRow] = numberRowsExtra_; numberU_++; #if ABC_SMALL < 2 if (gotUCopy()) { //in at end last = lastRow[numberRows_]; nextRow[last] = pivotRow; //numberRowsExtra_; lastRow[numberRows_] = pivotRow; //numberRowsExtra_; lastRow[pivotRow] = last; nextRow[pivotRow] = numberRows_; startRowU[pivotRow] = lastEntryByRowU_; } #endif #ifndef ABC_USE_FUNCTION_POINTERS numberInColumn[pivotRow]=numberInColumnU2; #else #if ABC_USE_FUNCTION_POINTERS if (numberInColumnU2<9) { scatter[pivotRow].functionPointer=AbcScatterLowSubtract[numberInColumnU2]; } else { scatter[pivotRow].functionPointer=AbcScatterHighSubtract[numberInColumnU2&3]; } #endif assert(scatter[pivotRow].offset==lastEntryByColumnUPlus_); //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_; //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast(area+numberInColumnU2); if (numberInColumnU2(area)>=0); for (int i=0;i>1; #endif totalElements_ += numberInColumnU2; lengthU_ += numberInColumnU2; #if ABC_SMALL < 2 CoinSimplexInt * COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt * COIN_RESTRICT lastColumn = lastColumnAddress_; if (gotRCopy()) { //column in at beginning (as empty) next = nextColumn[maximumRowsExtra_]; lastColumn[next] = numberRowsExtra_; nextColumn[maximumRowsExtra_] = numberRowsExtra_; nextColumn[numberRowsExtra_] = next; lastColumn[numberRowsExtra_] = maximumRowsExtra_; } #endif #if 0 { int k=-1; for (int i=0;ipivotLinkedForwardsAddress_[-1]); assert (pivotLinkedBackwardsAddress_[numberRows_]>=0); numberRowsExtra_++; numberGoodU_++; numberPivots_++; if ( numberRowsExtra_ > numberRows_ + 50 ) { CoinBigIndex extra = factorElements_ >> 1; if ( numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500 ) { if ( extra < 2 * numberRows_ ) { extra = 2 * numberRows_; } } else { if ( extra < 5 * numberRows_ ) { extra = 5 * numberRows_; } } CoinBigIndex added = totalElements_ - factorElements_; if ( added > extra && added > ( factorElements_ ) << 1 && !status && 3*totalElements_ > 2*(lengthAreaU_+lengthAreaL_)) { status = 3; if ( messageLevel_ & 4 ) { std::cout << "Factorization has "<< totalElements_ << ", basis had " << factorElements_ <numberInR) { // there is space CoinBigIndex put=startRR[iRow]+numberInR; numberInColumnPlus[iRow]=numberInR+1; indexRowRR[put]=pivotRow; elementRR[put]=value; //add 4 for luck if (next==maximumRowsExtra_) startRR[maximumRowsExtra_] = CoinMin(static_cast (put + 4) ,lengthAreaR_); } else { // no space - do we shuffle? if (!getColumnSpaceIterateR(iRow,value,pivotRow)) { // printf("Need more space for R\n"); numberInColumnPlus_.conditionalDelete(); numberInColumnPlusAddress_=NULL; setNoGotRCopy(); regionSparse->clear(); #if ABC_SMALL < 0 status=3; #endif break; } } } } else { #endif for (CoinBigIndex i = 0; i < numberNonZero; i++ ) { CoinSimplexInt iRow = regionIndex[i]; elementR[putR] = region[iRow]; region[iRow]=0.0; indexRowR[putR] = iRow; putR++; } #if ABC_SMALL < 2 } #endif #ifdef ABC_USE_FUNCTION_POINTERS #if 0 { CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; printf("=============================================start\n"); for (int iRow=0;iRow(area+number); CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow]; CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow]; //assert (number==numberInColumn[iRow]); #if ABC_USE_FUNCTION_POINTERS if (number<9) assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]); else assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]); #endif if (number) printf("Row %d %d els\n",iRow,number); int n=0; for (int i=0;isetNumElements(0); //for (int i=0;i(elementU2+numberInColumnU2); #else CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region toLongArray(regionSparse, 3); CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW #ifndef NDEBUG #define CONVERTDEBUG #endif #ifdef CONVERTDEBUG CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #endif #if CONVERTROW > 2 CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL < 2 CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); //CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_; #endif int nInRow; #if ABC_SMALL < 2 CoinBigIndex start = 0; CoinBigIndex end = 0; if (gotUCopy()) { start = startRowU[pivotRow]; nInRow = numberInRowU[pivotRow]; end = start + nInRow; CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1]; CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow < 10) { CoinSimplexInt smallest = numberRowsExtra_; for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn] < smallest) { smallest = pivotRowForward[jColumn]; smallestIndex = jColumn; } #ifndef ABC_USE_FUNCTION_POINTERS #ifdef CONVERTDEBUG CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn]; assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4); #endif region[jColumn] = elementRowU[i]; #else #ifdef CONVERTDEBUG CoinBigIndex j = convertRowToColumn[i]; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #endif region[jColumn] = elementRowU[i]; #endif regionIndex[numberNonZero++] = jColumn; } } else { for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; #ifdef CONVERTDEBUG #ifdef ABC_USE_FUNCTION_POINTERS CoinBigIndex j = convertRowToColumn[i]; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #else CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn]; assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4); #endif #endif region[jColumn] = elementRowU[i]; regionIndex[numberNonZero++] = jColumn; } } //do BTRAN - finding first one to use regionSparse->setNumElements(numberNonZero); if (numberNonZero) { assert(smallestIndex >= 0); #ifndef NDEBUG const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow = pivotLinked[-1]; if (jRow != smallestIndex) { while (jRow >= 0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow = pivotLinked[jRow]; } assert(jRow == smallestIndex); } #endif #if ABC_PARALLEL == 0 //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU(regionSparse, smallestIndex #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif ); #else assert(FACTOR_CPU > 3); updateColumnTransposeU(regionSparse, smallestIndex #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif , 3); #endif } } else { #endif #if ABC_SMALL >= 0 // No row copy check space CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_); CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_); nInRow = replaceColumnU(regionSparse, deletedPosition, deletedColumns, pivotRow); #endif #if ABC_SMALL < 2 } #endif if (lengthR_ + numberRows_ >= lengthAreaR_) { //not enough room return 0.0; } #ifdef ABC_USE_FUNCTION_POINTERS CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2); #endif if (lengthU_ + numberInColumnU2 >= lengthAreaU_) { //not enough room return 0.0; } //CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector ( ); //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; //int numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++) { CoinSimplexInt iRow = indexU2[i]; if (iRow != pivotRow) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } return saveFromU; } /* Checks if can replace one Column to basis, returns update alpha Fills in region for use later partial update in vector */ #ifdef ABC_LONG_FACTORIZATION long #endif double CoinAbcTypeFactorization::checkReplacePart1(CoinIndexedVector *regionSparse, CoinIndexedVector *partialUpdate, int pivotRow) { #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct *COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; #else CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_; #endif CoinSimplexInt *COIN_RESTRICT indexU2 = partialUpdate->getIndices(); CoinFactorizationDouble *COIN_RESTRICT elementU2 = denseVector(partialUpdate); CoinSimplexInt numberInColumnU2 = partialUpdate->getNumElements(); #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region toLongArray(regionSparse, 3); CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW #ifndef NDEBUG #define CONVERTDEBUG #endif #ifdef CONVERTDEBUG CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #endif #if CONVERTROW > 2 CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL < 2 CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); //CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_; #endif int nInRow; #if ABC_SMALL < 2 CoinBigIndex start = 0; CoinBigIndex end = 0; if (gotUCopy()) { start = startRowU[pivotRow]; nInRow = numberInRowU[pivotRow]; end = start + nInRow; CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1]; CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow < 10) { CoinSimplexInt smallest = numberRowsExtra_; for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn] < smallest) { smallest = pivotRowForward[jColumn]; smallestIndex = jColumn; } #ifndef ABC_USE_FUNCTION_POINTERS #ifdef CONVERTDEBUG CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn]; assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4); #endif region[jColumn] = elementRowU[i]; #else #ifdef CONVERTDEBUG CoinBigIndex j = convertRowToColumn[i]; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #endif region[jColumn] = elementRowU[i]; #endif regionIndex[numberNonZero++] = jColumn; } } else { for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; #ifdef CONVERTDEBUG #ifdef ABC_USE_FUNCTION_POINTERS CoinBigIndex j = convertRowToColumn[i]; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #else CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn]; assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4); #endif #endif region[jColumn] = elementRowU[i]; regionIndex[numberNonZero++] = jColumn; } } //do BTRAN - finding first one to use regionSparse->setNumElements(numberNonZero); if (numberNonZero) { assert(smallestIndex >= 0); #ifndef NDEBUG const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow = pivotLinked[-1]; if (jRow != smallestIndex) { while (jRow >= 0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow = pivotLinked[jRow]; } assert(jRow == smallestIndex); } #endif #if ABC_PARALLEL == 0 //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU(regionSparse, smallestIndex #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif ); #else assert(FACTOR_CPU > 3); updateColumnTransposeU(regionSparse, smallestIndex #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif , 3); #endif } } else { #endif #if ABC_SMALL >= 0 // No row copy check space CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_); CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_); nInRow = replaceColumnU(regionSparse, deletedPosition, deletedColumns, pivotRow); #endif #if ABC_SMALL < 2 } #endif if (lengthR_ + numberRows_ >= lengthAreaR_) { //not enough room return 0.0; } if (lengthU_ + numberInColumnU2 >= lengthAreaU_) { //not enough room partialUpdate->clear(); return 0.0; } //CoinSimplexDouble * COIN_RESTRICT region = regionSparse->denseVector ( ); //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; //int numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++) { CoinSimplexInt iRow = indexU2[i]; if (iRow != pivotRow) { saveFromU -= elementU2[iRow] * region[iRow]; } else { saveFromU += elementU2[iRow]; } } return saveFromU; } #ifdef MOVE_REPLACE_PART1A /* Checks if can replace one Column in basis, returns update alpha Fills in region for use later partial update already in U */ void CoinAbcTypeFactorization::checkReplacePart1a(CoinIndexedVector *regionSparse, int pivotRow) { #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct *COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU; //CoinSimplexInt * COIN_RESTRICT indexU2 = reinterpret_cast(elementU2+numberInColumnU2); #else CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif //zeroed out region CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); //CoinFactorizationDouble * COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex saveStart = startColumnU[pivotRow]; CoinBigIndex saveEnd = saveStart + numberInColumn[pivotRow]; #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW #ifndef NDEBUG #define CONVERTDEBUG #endif #ifdef CONVERTDEBUG CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #endif #if CONVERTROW > 2 CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL < 2 CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); //CoinSimplexInt status=0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_; #endif int nInRow; #if ABC_SMALL < 2 CoinBigIndex start = 0; CoinBigIndex end = 0; if (gotUCopy()) { start = startRowU[pivotRow]; nInRow = numberInRowU[pivotRow]; end = start + nInRow; CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1]; CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_; if (nInRow < 10) { CoinSimplexInt smallest = numberRowsExtra_; for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; if (pivotRowForward[jColumn] < smallest) { smallest = pivotRowForward[jColumn]; smallestIndex = jColumn; } #ifndef ABC_USE_FUNCTION_POINTERS #ifdef CONVERTDEBUG CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn]; assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4); #endif region[jColumn] = elementRowU[i]; #else #ifdef CONVERTDEBUG CoinBigIndex j = convertRowToColumn[i]; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #endif region[jColumn] = elementRowU[i]; #endif regionIndex[numberNonZero++] = jColumn; } } else { for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; #ifdef CONVERTDEBUG #ifdef ABC_USE_FUNCTION_POINTERS CoinBigIndex j = convertRowToColumn[i]; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #else CoinBigIndex j = convertRowToColumn[i] + startColumnU[jColumn]; assert(fabs(elementU[j] - elementRowU[i]) < 1.0e-4); #endif #endif region[jColumn] = elementRowU[i]; regionIndex[numberNonZero++] = jColumn; } } //do BTRAN - finding first one to use regionSparse->setNumElements(numberNonZero); if (numberNonZero) { assert(smallestIndex >= 0); #ifndef NDEBUG const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow = pivotLinked[-1]; if (jRow != smallestIndex) { while (jRow >= 0) { CoinFactorizationDouble pivotValue = region[jRow]; if (pivotValue) break; jRow = pivotLinked[jRow]; } assert(jRow == smallestIndex); } #endif #if ABC_PARALLEL == 0 //smallestIndex=pivotLinkedForwardsAddress_[-1]; updateColumnTransposeU(regionSparse, smallestIndex #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif ); #else assert(FACTOR_CPU > 3); updateColumnTransposeU(regionSparse, smallestIndex #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif , 3); #endif } } else { #endif #if ABC_SMALL >= 0 // No row copy check space CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_; CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_; CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_); CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_); nInRow = replaceColumnU(regionSparse, deletedPosition, deletedColumns, pivotRow); #endif #if ABC_SMALL < 2 } #endif } #ifdef ABC_LONG_FACTORIZATION long #endif double CoinAbcTypeFactorization::checkReplacePart1b(CoinIndexedVector *regionSparse, int pivotRow) { if (lengthR_ + numberRows_ >= lengthAreaR_) { //not enough room return 0.0; } #ifdef ABC_USE_FUNCTION_POINTERS scatterStruct *COIN_RESTRICT scatter = scatterUColumn(); CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU; CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2); #else CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_; CoinBigIndex startU = startColumnU[numberRows_]; CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #endif if (lengthU_ + numberInColumnU2 >= lengthAreaU_) { //not enough room return 0.0; } CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); //CoinSimplexInt * COIN_RESTRICT regionIndex = regionSparse->getIndices ( ); //CoinSimplexInt status=0; //int numberNonZero = regionSparse->getNumElements ( ); //printf("replace nels %d\n",numberNonZero); CoinFactorizationDouble saveFromU = 0.0; for (CoinBigIndex i = 0; i < numberInColumnU2; i++) { CoinSimplexInt iRow = indexU2[i]; if (iRow != pivotRow) { saveFromU -= elementU2[i] * region[iRow]; } else { saveFromU += elementU2[i]; } } return saveFromU; } #endif #include "AbcSimplex.hpp" /* Checks if can replace one Column to basis, returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ int CoinAbcTypeFactorization::checkReplacePart2(int pivotRow, CoinSimplexDouble /*btranAlpha*/, CoinSimplexDouble ftranAlpha, #ifdef ABC_LONG_FACTORIZATION long #endif double ftAlpha, double /*acceptablePivot*/) { if (lengthR_ + numberRows_ >= lengthAreaR_) { //not enough room return 3; } CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_; CoinFactorizationDouble oldPivot = pivotRegion[pivotRow]; // for accuracy check CoinFactorizationDouble pivotCheck = ftranAlpha / oldPivot; //check accuracy int status = checkPivot(ftAlpha, pivotCheck); if (status == 1 && !numberPivots_) { printf("check status ok\n"); status = 2; } return status; } /* Replaces one Column to basis, partial update already in U */ void CoinAbcTypeFactorization::replaceColumnPart3(const AbcSimplex * /*model*/, CoinIndexedVector *regionSparse, CoinIndexedVector * /*tableauColumn*/, int pivotRow, #ifdef ABC_LONG_FACTORIZATION long #endif double alpha) { assert(numberU_ <= numberRowsExtra_); #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex *COIN_RESTRICT startColumnU = startColumnUAddress_; CoinSimplexInt *COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinFactorizationDouble *COIN_RESTRICT elementU = elementUAddress_; #endif CoinSimplexInt *COIN_RESTRICT indexRowR = indexRowRAddress_; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT numberInRowU = numberInRowAddress_; #endif #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT numberInColumnPlus = numberInColumnPlusAddress_; #endif CoinSimplexInt *COIN_RESTRICT permuteLookup = pivotColumnAddress_; CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); //take out old pivot column #ifndef ABC_USE_FUNCTION_POINTERS totalElements_ -= numberInColumn[pivotRow]; #else scatterStruct *COIN_RESTRICT scatter = scatterUColumn(); #if ABC_USE_FUNCTION_POINTERS extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; #endif CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = scatter[numberRows_].offset; totalElements_ -= scatter[pivotRow].number; CoinBigIndex saveStart = scatter[pivotRow].offset; CoinBigIndex saveEnd = scatter[pivotRow].number; scatter[pivotRow].offset = startU; CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU; CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2); #endif //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW > 2 CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL < 2 CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinFactorizationDouble pivotValue = 1.0; CoinSimplexInt status = 0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_; #endif CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_; #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow = 9999999; // ? what if ABC_SMALL==0 or ABC_SMALL==1 #if ABC_SMALL < 2 CoinBigIndex start = 0; CoinBigIndex end = 0; if (gotUCopy()) { start = startRowU[pivotRow]; nInRow = numberInRowU[pivotRow]; end = start + nInRow; } #endif CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_; numberNonZero = regionSparse->getNumElements(); //CoinFactorizationDouble saveFromU = 0.0; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startU = startColumnU[numberRows_]; startColumnU[pivotRow] = startU; CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU]; CoinSimplexInt numberInColumnU2 = numberInColumn[numberRows_]; #else //CoinSimplexInt numberInColumnU2 = scatter[numberRows_].number; #endif instrument_do("CoinAbcFactorizationReplaceColumn", 2 * numberRows_ + 4 * numberInColumnU2); pivotValue = 1.0 / alpha; #if ABC_SMALL < 2 if (gotUCopy()) { for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startColumn = startColumnU[jColumn]; #if CONVERTROW CoinBigIndex j = convertRowToColumn[i]; #else CoinBigIndex j; int number = numberInColumn[jColumn]; for (j = 0; j < number; j++) { if (indexRowU[j + startColumn] == pivotRow) break; } assert(j < number); //assert (j==convertRowToColumn[i]); // temp #endif #ifdef CONVERTDEBUG assert(fabs(elementU[j + startColumn] - elementRowU[i]) < 1.0e-4); #endif #else int number = scatter[jColumn].number; CoinSimplexInt k = number - 1; scatter[jColumn].number = k; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; CoinSimplexInt *COIN_RESTRICT indices = reinterpret_cast< CoinSimplexInt * >(area + k + 1); #if CONVERTROW CoinSimplexInt j = convertRowToColumn[i]; #else CoinSimplexInt j; for (j = 0; j < number; j++) { if (indices[j] == pivotRow) break; } assert(j < number); //assert (j==convertRowToColumn[i]); // temp #endif #ifdef CONVERTDEBUG assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #endif #endif // swap #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt k = numberInColumn[jColumn] - 1; numberInColumn[jColumn] = k; CoinBigIndex k2 = k + startColumn; int kRow2 = indexRowU[k2]; indexRowU[j + startColumn] = kRow2; CoinFactorizationDouble value2 = elementU[k2]; elementU[j + startColumn] = value2; #else int kRow2 = indices[k]; CoinFactorizationDouble value2 = area[k]; #if ABC_USE_FUNCTION_POINTERS if (k < 9) { scatter[jColumn].functionPointer = AbcScatterLowSubtract[k]; } else { scatter[jColumn].functionPointer = AbcScatterHighSubtract[k & 3]; } #endif // later more complicated swap to avoid move (don't think we can!) indices[j] = kRow2; area[j] = value2; // move indices -= 2; for (int i = 0; i < k; i++) indices[i] = indices[i + 2]; #endif // move in row copy (slow - as other remark (but shouldn't need to)) CoinBigIndex start2 = startRowU[kRow2]; int n = numberInRowU[kRow2]; CoinBigIndex end2 = start2 + n; #ifndef NDEBUG bool found = false; #endif for (CoinBigIndex i2 = start2; i2 < end2; i2++) { CoinSimplexInt iColumn2 = indexColumnU[i2]; if (jColumn == iColumn2) { #if CONVERTROW convertRowToColumn[i2] = j; #endif #ifndef NDEBUG found = true; #endif break; } } #ifndef NDEBUG assert(found); #endif } } else { #endif #if ABC_SMALL >= 0 assert(nInRow != 9999999); // ? what if ABC_SMALL==0 or ABC_SMALL==1 // no row copy CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_); CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_); for (CoinSimplexInt i = 0; i < nInRow; i++) { CoinBigIndex j = deletedPosition[i]; CoinSimplexInt jColumn = deletedColumns[i]; // swap CoinSimplexInt k = numberInColumn[jColumn] - 1; numberInColumn[jColumn] = k; CoinBigIndex k2 = k + startColumnU[jColumn]; int kRow2 = indexRowU[k2]; indexRowU[j] = kRow2; CoinFactorizationDouble value2 = elementU[k2]; elementU[j] = value2; } #endif #if ABC_SMALL < 2 } #endif #if ABC_SMALL < 2 if (gotUCopy()) { // Now zero out column of U //take out old pivot column #ifdef ABC_USE_FUNCTION_POINTERS CoinFactorizationDouble *COIN_RESTRICT elementU = elementUColumnPlus + saveStart; saveStart = 0; CoinSimplexInt *COIN_RESTRICT indexRowU = reinterpret_cast< CoinSimplexInt * >(elementU + saveEnd); #endif for (CoinBigIndex i = saveStart; i < saveEnd; i++) { //elementU[i] = 0.0; // If too slow then reverse meaning of convertRowToColumn and use int jRow = indexRowU[i]; CoinBigIndex start = startRowU[jRow]; CoinBigIndex end = start + numberInRowU[jRow]; for (CoinBigIndex j = start; j < end; j++) { CoinSimplexInt jColumn = indexColumnU[j]; if (jColumn == pivotRow) { // swap numberInRowU[jRow]--; elementRowU[j] = elementRowU[end - 1]; #if CONVERTROW convertRowToColumn[j] = convertRowToColumn[end - 1]; #endif indexColumnU[j] = indexColumnU[end - 1]; break; } } } } #endif //zero out pivot Row (before or after?) //add to R CoinBigIndex *COIN_RESTRICT startColumnR = startColumnRAddress_; CoinBigIndex putR = lengthR_; CoinSimplexInt number = numberR_; startColumnR[number] = putR; //for luck and first time number++; //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2)); startColumnR[number] = putR + numberNonZero; numberR_ = number; lengthR_ = putR + numberNonZero; totalElements_ += numberNonZero; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT nextRow = NULL; CoinSimplexInt *COIN_RESTRICT lastRow = NULL; CoinSimplexInt next; CoinSimplexInt last; if (gotUCopy()) { //take out row nextRow = nextRowAddress_; lastRow = lastRowAddress_; next = nextRow[pivotRow]; last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; numberInRowU[pivotRow] = 0; } #endif //put in pivot //add row counts int n = 0; for (CoinSimplexInt i = 0; i < numberInColumnU2; i++) { CoinSimplexInt iRow = indexU2[i]; CoinFactorizationDouble value = elementU2[i]; assert(value); if (!TEST_LESS_THAN_TOLERANCE(value)) { if (iRow != pivotRow) { //modify by pivot CoinFactorizationDouble value2 = value * pivotValue; indexU2[n] = iRow; elementU2[n++] = value2; #if ABC_SMALL < 2 if (gotUCopy()) { CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt iNumberInRow = numberInRowU[iRow]; CoinBigIndex space; CoinBigIndex put = startRowU[iRow] + iNumberInRow; space = startRowU[next] - put; if (space <= 0) { getRowSpaceIterate(iRow, iNumberInRow + 4); put = startRowU[iRow] + iNumberInRow; } else if (next == numberRows_) { lastEntryByRowU_ = put + 1; } indexColumnU[put] = pivotRow; #if CONVERTROW convertRowToColumn[put] = i; #endif elementRowU[put] = value2; numberInRowU[iRow] = iNumberInRow + 1; } #endif } else { //swap and save indexU2[i] = indexU2[numberInColumnU2 - 1]; elementU2[i] = elementU2[numberInColumnU2 - 1]; numberInColumnU2--; i--; } } else { // swap indexU2[i] = indexU2[numberInColumnU2 - 1]; elementU2[i] = elementU2[numberInColumnU2 - 1]; numberInColumnU2--; i--; } } numberInColumnU2 = n; //do permute permuteAddress_[numberRowsExtra_] = pivotRow; //and for safety permuteAddress_[numberRowsExtra_ + 1] = 0; //pivotColumnAddress_[pivotRow] = numberRowsExtra_; numberU_++; #if ABC_SMALL < 2 if (gotUCopy()) { //in at end last = lastRow[numberRows_]; nextRow[last] = pivotRow; //numberRowsExtra_; lastRow[numberRows_] = pivotRow; //numberRowsExtra_; lastRow[pivotRow] = last; nextRow[pivotRow] = numberRows_; startRowU[pivotRow] = lastEntryByRowU_; } #endif #ifndef ABC_USE_FUNCTION_POINTERS numberInColumn[pivotRow] = numberInColumnU2; #else #if ABC_USE_FUNCTION_POINTERS if (numberInColumnU2 < 9) { scatter[pivotRow].functionPointer = AbcScatterLowSubtract[numberInColumnU2]; } else { scatter[pivotRow].functionPointer = AbcScatterHighSubtract[numberInColumnU2 & 3]; } #endif assert(scatter[pivotRow].offset == lastEntryByColumnUPlus_); //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_; //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast(area+numberInColumnU2); if (numberInColumnU2 < scatter[numberRows_].number) { int offset = 2 * (scatter[numberRows_].number - numberInColumnU2); indexU2 -= offset; //assert(indexU2-reinterpret_cast(area)>=0); for (int i = 0; i < numberInColumnU2; i++) indexU2[i] = indexU2[i + offset]; } scatter[pivotRow].number = numberInColumnU2; //CoinAbcMemcpy(indices,indexU2,numberInColumnU2); //CoinAbcMemcpy(area,elementU2,numberInColumnU2); lastEntryByColumnUPlus_ += (3 * numberInColumnU2 + 1) >> 1; #endif totalElements_ += numberInColumnU2; lengthU_ += numberInColumnU2; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_; if (gotRCopy()) { //column in at beginning (as empty) next = nextColumn[maximumRowsExtra_]; lastColumn[next] = numberRowsExtra_; nextColumn[maximumRowsExtra_] = numberRowsExtra_; nextColumn[numberRowsExtra_] = next; lastColumn[numberRowsExtra_] = maximumRowsExtra_; } #endif #if 0 { int k=-1; for (int i=0;i pivotLinkedForwardsAddress_[-1]); assert(pivotLinkedBackwardsAddress_[numberRows_] >= 0); numberRowsExtra_++; numberGoodU_++; numberPivots_++; if (numberRowsExtra_ > numberRows_ + 50) { CoinBigIndex extra = factorElements_ >> 1; if (numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500) { if (extra < 2 * numberRows_) { extra = 2 * numberRows_; } } else { if (extra < 5 * numberRows_) { extra = 5 * numberRows_; } } CoinBigIndex added = totalElements_ - factorElements_; if (added > extra && added > (factorElements_) << 1 && !status && 3 * totalElements_ > 2 * (lengthAreaU_ + lengthAreaL_)) { status = 3; if (messageLevel_ & 4) { std::cout << "Factorization has " << totalElements_ << ", basis had " << factorElements_ << std::endl; } } } #if ABC_SMALL < 2 if (gotRCopy() && status < 2) { //if (numberInColumnPlus&&status<2) { // we are going to put another copy of R in R CoinFactorizationDouble *COIN_RESTRICT elementRR = elementRAddress_ + lengthAreaR_; CoinSimplexInt *COIN_RESTRICT indexRowRR = indexRowRAddress_ + lengthAreaR_; CoinBigIndex *COIN_RESTRICT startRR = startColumnRAddress_ + maximumPivots_ + 1; CoinSimplexInt pivotRow = numberRowsExtra_ - 1; for (CoinBigIndex i = 0; i < numberNonZero; i++) { CoinSimplexInt jRow = regionIndex[i]; CoinFactorizationDouble value = region[jRow]; elementR[putR] = value; indexRowR[putR] = jRow; putR++; region[jRow] = 0.0; int iRow = permuteLookup[jRow]; next = nextColumn[iRow]; CoinBigIndex space; if (next != maximumRowsExtra_) space = startRR[next] - startRR[iRow]; else space = lengthAreaR_ - startRR[iRow]; CoinSimplexInt numberInR = numberInColumnPlus[iRow]; if (space > numberInR) { // there is space CoinBigIndex put = startRR[iRow] + numberInR; numberInColumnPlus[iRow] = numberInR + 1; indexRowRR[put] = pivotRow; elementRR[put] = value; //add 4 for luck if (next == maximumRowsExtra_) startRR[maximumRowsExtra_] = CoinMin(static_cast< CoinBigIndex >(put + 4), lengthAreaR_); } else { // no space - do we shuffle? if (!getColumnSpaceIterateR(iRow, value, pivotRow)) { // printf("Need more space for R\n"); numberInColumnPlus_.conditionalDelete(); numberInColumnPlusAddress_ = NULL; setNoGotRCopy(); regionSparse->clear(); #if ABC_SMALL < 0 abort(); status = 3; #endif break; } } } } else { #endif for (CoinBigIndex i = 0; i < numberNonZero; i++) { CoinSimplexInt iRow = regionIndex[i]; elementR[putR] = region[iRow]; region[iRow] = 0.0; indexRowR[putR] = iRow; putR++; } #if ABC_SMALL < 2 } #endif #ifdef ABC_USE_FUNCTION_POINTERS #if 0 { CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; printf("=============================================start\n"); for (int iRow=0;iRow(area+number); CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow]; CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow]; //assert (number==numberInColumn[iRow]); #if ABC_USE_FUNCTION_POINTERS if (number<9) assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]); else assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]); #endif if (number) printf("Row %d %d els\n",iRow,number); int n=0; for (int i=0;isetNumElements(0); fromLongArray(regionSparse); #if 0 static int arrayF[6]={1,1,1,1,1,1}; static int arrayB[6]={1,1,1,1,1,1}; static int arrayF1[6]={1,1,1,1,1,1}; static int arrayB1[6]={1,1,1,1,1,1}; static int itry=0; { const CoinSimplexInt * COIN_RESTRICT back = firstCountAddress_+numberRows_; const CoinSimplexInt * COIN_RESTRICT pivotColumn = pivotColumnAddress_; // no const CoinSimplexInt * COIN_RESTRICT permute = permuteAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLOrder = this->pivotLOrderAddress_; const CoinSimplexInt * COIN_RESTRICT pivotLinkedForwards = this->pivotLinkedForwardsAddress_;//no const CoinSimplexInt * COIN_RESTRICT pivotLinkedBackwards = this->pivotLinkedBackwardsAddress_;//no itry++; int testit[6]; for (int i=0;i<6;i++) testit[i]=1; for (int i=0;igetNumElements(); //take out old pivot column #ifndef ABC_USE_FUNCTION_POINTERS totalElements_ -= numberInColumn[pivotRow]; CoinBigIndex startU = startColumnU[numberRows_]; startColumnU[pivotRow] = startU; CoinSimplexInt *COIN_RESTRICT indexU2 = &indexRowUAddress_[startU]; CoinFactorizationDouble *COIN_RESTRICT elementU2 = &elementUAddress_[startU]; numberInColumn[numberRows_] = numberInColumnU2; #else scatterStruct *COIN_RESTRICT scatter = scatterUColumn(); #if ABC_USE_FUNCTION_POINTERS extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; #endif CoinFactorizationDouble *COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinBigIndex startU = lastEntryByColumnUPlus_; totalElements_ -= scatter[pivotRow].number; CoinBigIndex saveStart = scatter[pivotRow].offset; CoinBigIndex saveEnd = scatter[pivotRow].number; scatter[pivotRow].offset = startU; scatter[numberRows_].number = numberInColumnU2; CoinFactorizationDouble *COIN_RESTRICT elementU2 = elementUColumnPlus + startU; CoinSimplexInt *COIN_RESTRICT indexU2 = reinterpret_cast< CoinSimplexInt * >(elementU2 + numberInColumnU2); #endif // move CoinSimplexInt *COIN_RESTRICT indexU2Save = partialUpdate->getIndices(); CoinFactorizationDouble *COIN_RESTRICT elementU2Save = denseVector(partialUpdate); memcpy(indexU2, indexU2Save, numberInColumnU2 * sizeof(CoinSimplexInt)); for (int i = 0; i < numberInColumnU2; i++) { int iRow = indexU2[i]; elementU2[i] = elementU2Save[iRow]; elementU2Save[iRow] = 0.0; } //memcpy(elementU2,elementU2Save,numberInColumnU2*sizeof(double)); //memset(elementU2Save,0,numberInColumnU2*sizeof(double)); partialUpdate->setNumElements(0); //get entries in row (pivot not stored) CoinSimplexInt numberNonZero = 0; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT indexColumnU = indexColumnUAddress_; #endif #if CONVERTROW CoinBigIndex *COIN_RESTRICT convertRowToColumn = convertRowToColumnUAddress_; #if CONVERTROW > 2 CoinBigIndex *COIN_RESTRICT convertColumnToRow = convertColumnToRowUAddress_; #endif #endif #if ABC_SMALL < 2 CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_; CoinBigIndex *COIN_RESTRICT startRowU = startRowUAddress_; #endif CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinFactorizationDouble pivotValue = 1.0; CoinSimplexInt status = 0; #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt *COIN_RESTRICT indexRowU = indexRowUAddress_; #endif CoinFactorizationDouble *COIN_RESTRICT elementR = elementRAddress_; #ifndef NDEBUG #if CONVERTROW #define CONVERTDEBUG #endif #endif int nInRow = 9999999; // ? what if ABC_SMALL==0 or ABC_SMALL==1 #if ABC_SMALL < 2 CoinBigIndex start = 0; CoinBigIndex end = 0; if (gotUCopy()) { start = startRowU[pivotRow]; nInRow = numberInRowU[pivotRow]; end = start + nInRow; } #endif CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_; numberNonZero = regionSparse->getNumElements(); //CoinFactorizationDouble saveFromU = 0.0; instrument_do("CoinAbcFactorizationReplaceColumn", 2 * numberRows_ + 4 * numberInColumnU2); pivotValue = 1.0 / alpha; #if ABC_SMALL < 2 if (gotUCopy()) { for (CoinBigIndex i = start; i < end; i++) { CoinSimplexInt jColumn = indexColumnU[i]; #ifndef ABC_USE_FUNCTION_POINTERS CoinBigIndex startColumn = startColumnU[jColumn]; #if CONVERTROW CoinBigIndex j = convertRowToColumn[i]; #else CoinBigIndex j; int number = numberInColumn[jColumn]; for (j = 0; j < number; j++) { if (indexRowU[j + startColumn] == pivotRow) break; } assert(j < number); //assert (j==convertRowToColumn[i]); // temp #endif #ifdef CONVERTDEBUG assert(fabs(elementU[j + startColumn] - elementRowU[i]) < 1.0e-4); #endif #else int number = scatter[jColumn].number; CoinSimplexInt k = number - 1; scatter[jColumn].number = k; CoinFactorizationDouble *COIN_RESTRICT area = elementUColumnPlus + scatter[jColumn].offset; CoinSimplexInt *COIN_RESTRICT indices = reinterpret_cast< CoinSimplexInt * >(area + k + 1); #if CONVERTROW CoinSimplexInt j = convertRowToColumn[i]; #else CoinSimplexInt j; for (j = 0; j < number; j++) { if (indices[j] == pivotRow) break; } assert(j < number); //assert (j==convertRowToColumn[i]); // temp #endif #ifdef CONVERTDEBUG assert(fabs(area[j] - elementRowU[i]) < 1.0e-4); #endif #endif // swap #ifndef ABC_USE_FUNCTION_POINTERS CoinSimplexInt k = numberInColumn[jColumn] - 1; numberInColumn[jColumn] = k; CoinBigIndex k2 = k + startColumn; int kRow2 = indexRowU[k2]; indexRowU[j + startColumn] = kRow2; CoinFactorizationDouble value2 = elementU[k2]; elementU[j + startColumn] = value2; #else int kRow2 = indices[k]; CoinFactorizationDouble value2 = area[k]; #if ABC_USE_FUNCTION_POINTERS if (k < 9) { scatter[jColumn].functionPointer = AbcScatterLowSubtract[k]; } else { scatter[jColumn].functionPointer = AbcScatterHighSubtract[k & 3]; } #endif // later more complicated swap to avoid move (don't think we can!) indices[j] = kRow2; area[j] = value2; // move indices -= 2; for (int i = 0; i < k; i++) indices[i] = indices[i + 2]; #endif // move in row copy (slow - as other remark (but shouldn't need to)) CoinBigIndex start2 = startRowU[kRow2]; int n = numberInRowU[kRow2]; CoinBigIndex end2 = start2 + n; #ifndef NDEBUG bool found = false; #endif for (CoinBigIndex i2 = start2; i2 < end2; i2++) { CoinSimplexInt iColumn2 = indexColumnU[i2]; if (jColumn == iColumn2) { #if CONVERTROW convertRowToColumn[i2] = j; #endif #ifndef NDEBUG found = true; #endif break; } } #ifndef NDEBUG assert(found); #endif } } else { #endif #if ABC_SMALL >= 0 assert(nInRow != 9999999); // ? what if ABC_SMALL==0 or ABC_SMALL==1 // no row copy CoinBigIndex COIN_RESTRICT *deletedPosition = reinterpret_cast< CoinBigIndex * >(elementR + lengthR_); CoinSimplexInt COIN_RESTRICT *deletedColumns = reinterpret_cast< CoinSimplexInt * >(indexRowR + lengthR_); for (CoinSimplexInt i = 0; i < nInRow; i++) { CoinBigIndex j = deletedPosition[i]; CoinSimplexInt jColumn = deletedColumns[i]; // swap CoinSimplexInt k = numberInColumn[jColumn] - 1; numberInColumn[jColumn] = k; CoinBigIndex k2 = k + startColumnU[jColumn]; int kRow2 = indexRowU[k2]; indexRowU[j] = kRow2; CoinFactorizationDouble value2 = elementU[k2]; elementU[j] = value2; } #endif #if ABC_SMALL < 2 } #endif #if ABC_SMALL < 2 if (gotUCopy()) { // Now zero out column of U //take out old pivot column #ifdef ABC_USE_FUNCTION_POINTERS CoinFactorizationDouble *COIN_RESTRICT elementU = elementUColumnPlus + saveStart; saveStart = 0; CoinSimplexInt *COIN_RESTRICT indexRowU = reinterpret_cast< CoinSimplexInt * >(elementU + saveEnd); #endif for (CoinBigIndex i = saveStart; i < saveEnd; i++) { //elementU[i] = 0.0; // If too slow then reverse meaning of convertRowToColumn and use int jRow = indexRowU[i]; CoinBigIndex start = startRowU[jRow]; CoinBigIndex end = start + numberInRowU[jRow]; for (CoinBigIndex j = start; j < end; j++) { CoinSimplexInt jColumn = indexColumnU[j]; if (jColumn == pivotRow) { // swap numberInRowU[jRow]--; elementRowU[j] = elementRowU[end - 1]; #if CONVERTROW convertRowToColumn[j] = convertRowToColumn[end - 1]; #endif indexColumnU[j] = indexColumnU[end - 1]; break; } } } } #endif //zero out pivot Row (before or after?) //add to R CoinBigIndex *COIN_RESTRICT startColumnR = startColumnRAddress_; CoinBigIndex putR = lengthR_; CoinSimplexInt number = numberR_; startColumnR[number] = putR; //for luck and first time number++; //assert (startColumnR+number-firstCountAddress_<( CoinMax(5*numberRows_,2*numberRows_+2*maximumPivots_)+2)); startColumnR[number] = putR + numberNonZero; numberR_ = number; lengthR_ = putR + numberNonZero; totalElements_ += numberNonZero; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT nextRow = NULL; CoinSimplexInt *COIN_RESTRICT lastRow = NULL; CoinSimplexInt next; CoinSimplexInt last; if (gotUCopy()) { //take out row nextRow = nextRowAddress_; lastRow = lastRowAddress_; next = nextRow[pivotRow]; last = lastRow[pivotRow]; nextRow[last] = next; lastRow[next] = last; numberInRowU[pivotRow] = 0; } #endif //put in pivot //add row counts int n = 0; for (CoinSimplexInt i = 0; i < numberInColumnU2; i++) { CoinSimplexInt iRow = indexU2[i]; CoinFactorizationDouble value = elementU2[i]; assert(value); if (!TEST_LESS_THAN_TOLERANCE(value)) { if (iRow != pivotRow) { //modify by pivot CoinFactorizationDouble value2 = value * pivotValue; indexU2[n] = iRow; elementU2[n++] = value2; #if ABC_SMALL < 2 if (gotUCopy()) { CoinSimplexInt next = nextRow[iRow]; CoinSimplexInt iNumberInRow = numberInRowU[iRow]; CoinBigIndex space; CoinBigIndex put = startRowU[iRow] + iNumberInRow; space = startRowU[next] - put; if (space <= 0) { getRowSpaceIterate(iRow, iNumberInRow + 4); put = startRowU[iRow] + iNumberInRow; } else if (next == numberRows_) { lastEntryByRowU_ = put + 1; } indexColumnU[put] = pivotRow; #if CONVERTROW convertRowToColumn[put] = i; #endif elementRowU[put] = value2; numberInRowU[iRow] = iNumberInRow + 1; } #endif } else { //swap and save indexU2[i] = indexU2[numberInColumnU2 - 1]; elementU2[i] = elementU2[numberInColumnU2 - 1]; numberInColumnU2--; i--; } } else { // swap indexU2[i] = indexU2[numberInColumnU2 - 1]; elementU2[i] = elementU2[numberInColumnU2 - 1]; numberInColumnU2--; i--; } } numberInColumnU2 = n; //do permute permuteAddress_[numberRowsExtra_] = pivotRow; //and for safety permuteAddress_[numberRowsExtra_ + 1] = 0; //pivotColumnAddress_[pivotRow] = numberRowsExtra_; numberU_++; #if ABC_SMALL < 2 if (gotUCopy()) { //in at end last = lastRow[numberRows_]; nextRow[last] = pivotRow; //numberRowsExtra_; lastRow[numberRows_] = pivotRow; //numberRowsExtra_; lastRow[pivotRow] = last; nextRow[pivotRow] = numberRows_; startRowU[pivotRow] = lastEntryByRowU_; } #endif #ifndef ABC_USE_FUNCTION_POINTERS numberInColumn[pivotRow] = numberInColumnU2; #else #if ABC_USE_FUNCTION_POINTERS if (numberInColumnU2 < 9) { scatter[pivotRow].functionPointer = AbcScatterLowSubtract[numberInColumnU2]; } else { scatter[pivotRow].functionPointer = AbcScatterHighSubtract[numberInColumnU2 & 3]; } #endif assert(scatter[pivotRow].offset == lastEntryByColumnUPlus_); //CoinFactorizationDouble * COIN_RESTRICT area = elementUColumnPlus+lastEntryByColumnUPlus_; //CoinSimplexInt * COIN_RESTRICT indices = reinterpret_cast(area+numberInColumnU2); if (numberInColumnU2 < scatter[numberRows_].number) { int offset = 2 * (scatter[numberRows_].number - numberInColumnU2); indexU2 -= offset; //assert(indexU2-reinterpret_cast(area)>=0); for (int i = 0; i < numberInColumnU2; i++) indexU2[i] = indexU2[i + offset]; } scatter[pivotRow].number = numberInColumnU2; //CoinAbcMemcpy(indices,indexU2,numberInColumnU2); //CoinAbcMemcpy(area,elementU2,numberInColumnU2); lastEntryByColumnUPlus_ += (3 * numberInColumnU2 + 1) >> 1; #endif totalElements_ += numberInColumnU2; lengthU_ += numberInColumnU2; #if ABC_SMALL < 2 CoinSimplexInt *COIN_RESTRICT nextColumn = nextColumnAddress_; CoinSimplexInt *COIN_RESTRICT lastColumn = lastColumnAddress_; if (gotRCopy()) { //column in at beginning (as empty) next = nextColumn[maximumRowsExtra_]; lastColumn[next] = numberRowsExtra_; nextColumn[maximumRowsExtra_] = numberRowsExtra_; nextColumn[numberRowsExtra_] = next; lastColumn[numberRowsExtra_] = maximumRowsExtra_; } #endif #if 0 { int k=-1; for (int i=0;i pivotLinkedForwardsAddress_[-1]); assert(pivotLinkedBackwardsAddress_[numberRows_] >= 0); numberRowsExtra_++; numberGoodU_++; numberPivots_++; if (numberRowsExtra_ > numberRows_ + 50) { CoinBigIndex extra = factorElements_ >> 1; if (numberRowsExtra_ > numberRows_ + 100 + numberRows_ / 500) { if (extra < 2 * numberRows_) { extra = 2 * numberRows_; } } else { if (extra < 5 * numberRows_) { extra = 5 * numberRows_; } } CoinBigIndex added = totalElements_ - factorElements_; if (added > extra && added > (factorElements_) << 1 && !status && 3 * totalElements_ > 2 * (lengthAreaU_ + lengthAreaL_)) { status = 3; if (messageLevel_ & 4) { std::cout << "Factorization has " << totalElements_ << ", basis had " << factorElements_ << std::endl; } } } #if ABC_SMALL < 2 if (gotRCopy() && status < 2) { //if (numberInColumnPlus&&status<2) { // we are going to put another copy of R in R CoinFactorizationDouble *COIN_RESTRICT elementRR = elementRAddress_ + lengthAreaR_; CoinSimplexInt *COIN_RESTRICT indexRowRR = indexRowRAddress_ + lengthAreaR_; CoinBigIndex *COIN_RESTRICT startRR = startColumnRAddress_ + maximumPivots_ + 1; CoinSimplexInt pivotRow = numberRowsExtra_ - 1; for (CoinBigIndex i = 0; i < numberNonZero; i++) { CoinSimplexInt jRow = regionIndex[i]; CoinFactorizationDouble value = region[jRow]; elementR[putR] = value; indexRowR[putR] = jRow; putR++; region[jRow] = 0.0; int iRow = permuteLookup[jRow]; next = nextColumn[iRow]; CoinBigIndex space; if (next != maximumRowsExtra_) space = startRR[next] - startRR[iRow]; else space = lengthAreaR_ - startRR[iRow]; CoinSimplexInt numberInR = numberInColumnPlus[iRow]; if (space > numberInR) { // there is space CoinBigIndex put = startRR[iRow] + numberInR; numberInColumnPlus[iRow] = numberInR + 1; indexRowRR[put] = pivotRow; elementRR[put] = value; //add 4 for luck if (next == maximumRowsExtra_) startRR[maximumRowsExtra_] = CoinMin(static_cast< CoinBigIndex >(put + 4), lengthAreaR_); } else { // no space - do we shuffle? if (!getColumnSpaceIterateR(iRow, value, pivotRow)) { // printf("Need more space for R\n"); numberInColumnPlus_.conditionalDelete(); numberInColumnPlusAddress_ = NULL; setNoGotRCopy(); regionSparse->clear(); #if ABC_SMALL < 0 abort(); status = 3; #endif break; } } } } else { #endif for (CoinBigIndex i = 0; i < numberNonZero; i++) { CoinSimplexInt iRow = regionIndex[i]; elementR[putR] = region[iRow]; region[iRow] = 0.0; indexRowR[putR] = iRow; putR++; } #if ABC_SMALL < 2 } #endif #ifdef ABC_USE_FUNCTION_POINTERS #if 0 { CoinFactorizationDouble * COIN_RESTRICT elementUColumnPlus = elementUColumnPlusAddress_; CoinSimplexInt * COIN_RESTRICT indexRow = indexRowUAddress_; CoinFactorizationDouble * COIN_RESTRICT element = elementUAddress_; CoinSimplexInt * COIN_RESTRICT numberInColumn = numberInColumnAddress_; CoinBigIndex * COIN_RESTRICT startColumnU = startColumnUAddress_; scatterStruct * COIN_RESTRICT scatter = scatterUColumn(); extern scatterUpdate AbcScatterLowSubtract[9]; extern scatterUpdate AbcScatterHighSubtract[4]; printf("=============================================start\n"); for (int iRow=0;iRow(area+number); CoinSimplexInt * COIN_RESTRICT indices2 = indexRow+startColumnU[iRow]; CoinFactorizationDouble * COIN_RESTRICT area2 = element+startColumnU[iRow]; //assert (number==numberInColumn[iRow]); #if ABC_USE_FUNCTION_POINTERS if (number<9) assert (scatter[iRow].functionPointer==AbcScatterLowSubtract[number]); else assert (scatter[iRow].functionPointer==AbcScatterHighSubtract[number&3]); #endif if (number) printf("Row %d %d els\n",iRow,number); int n=0; for (int i=0;isetNumElements(0); } #if ABC_SMALL >= 0 /* Combines BtranU and store which elements are to be deleted */ int CoinAbcTypeFactorization::replaceColumnU(CoinIndexedVector *regionSparse, CoinBigIndex *deletedPosition, CoinSimplexInt *deletedColumns, CoinSimplexInt pivotRow) { instrument_start("CoinAbcFactorizationReplaceColumnU", numberRows_); CoinSimplexDouble *COIN_RESTRICT region = regionSparse->denseVector(); int *COIN_RESTRICT regionIndex = regionSparse->getIndices(); const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_; const CoinSimplexInt COIN_RESTRICT *indexRow = indexRowUAddress_; CoinFactorizationDouble COIN_RESTRICT *element = elementUAddress_; int numberNonZero = 0; const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_; int nPut = 0; const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow = pivotLinked[-1]; while (jRow != numberRows_) { assert(!region[jRow]); CoinFactorizationDouble pivotValue = 0.0; instrument_add(numberInColumn[jRow]); for (CoinBigIndex j = startColumn[jRow]; j < startColumn[jRow] + numberInColumn[jRow]; j++) { int iRow = indexRow[j]; CoinFactorizationDouble value = element[j]; if (iRow != pivotRow) { pivotValue -= value * region[iRow]; } else { assert(!region[iRow]); pivotValue += value; deletedColumns[nPut] = jRow; deletedPosition[nPut++] = j; } } if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) { regionIndex[numberNonZero++] = jRow; region[jRow] = pivotValue; } else { region[jRow] = 0; } jRow = pivotLinked[jRow]; } regionSparse->setNumElements(numberNonZero); instrument_end(); return nPut; } /* Updates part of column transpose (BTRANU) by column assumes index is sorted i.e. region is correct */ void CoinAbcTypeFactorization::updateColumnTransposeUByColumn(CoinIndexedVector *regionSparse, CoinSimplexInt smallestIndex) const { instrument_start("CoinAbcFactorizationUpdateTransposeUByColumn", numberRows_); CoinSimplexDouble *COIN_RESTRICT region = regionSparse->denseVector(); const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_; const CoinSimplexInt COIN_RESTRICT *indexRow = indexRowUAddress_; const CoinFactorizationDouble COIN_RESTRICT *element = elementUAddress_; #if ABC_SMALL < 3 int numberNonZero = 0; int *COIN_RESTRICT regionIndex = regionSparse->getIndices(); #endif const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_; //const CoinFactorizationDouble COIN_RESTRICT *pivotRegion = pivotRegionAddress_; const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow = smallestIndex; while (jRow != numberRows_) { CoinFactorizationDouble pivotValue = region[jRow]; CoinBigIndex start = startColumn[jRow]; instrument_add(numberInColumn[jRow]); #ifndef INLINE_IT2 for (CoinBigIndex j = start; j < start + numberInColumn[jRow]; j++) { int iRow = indexRow[j]; CoinFactorizationDouble value = element[j]; pivotValue -= value * region[iRow]; } #else pivotValue += CoinAbcGatherUpdate(numberInColumn[jRow], element + start, indexRow + start, region); #endif #if ABC_SMALL < 3 if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) { regionIndex[numberNonZero++] = jRow; region[jRow] = pivotValue; } else { region[jRow] = 0; } #else region[jRow] = pivotValue; #endif jRow = pivotLinked[jRow]; } #if ABC_SMALL < 3 regionSparse->setNumElements(numberNonZero); #endif instrument_end(); } #endif // updateColumnTranspose. Updates one column transpose (BTRAN) CoinSimplexInt CoinAbcTypeFactorization::updateColumnTranspose(CoinIndexedVector ®ionSparse) const { toLongArray(®ionSparse, 0); CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse.getIndices(); CoinSimplexInt numberNonZero = regionSparse.getNumElements(); const CoinFactorizationDouble *COIN_RESTRICT pivotRegion = pivotRegionAddress_; #ifndef ABC_ORDERED_FACTORIZATION // can I move this #ifndef INLINE_IT3 for (CoinSimplexInt i = 0; i < numberNonZero; i++) { CoinSimplexInt iRow = regionIndex[i]; CoinSimplexDouble value = region[iRow]; value *= pivotRegion[iRow]; region[iRow] = value; } #else multiplyIndexed(numberNonZero, pivotRegion, regionIndex, region); #endif #else // Permute in for Btran permuteInForBtranAndMultiply(regionSparse); #endif // ******* U // Apply pivot region - could be combined for speed // Can only combine/move inside vector for sparse CoinSimplexInt smallestIndex = pivotLinkedForwardsAddress_[-1]; #if ABC_SMALL < 2 // copy of code inside transposeU bool goSparse = false; #else #define goSparse false #endif #if ABC_SMALL < 2 // Guess at number at end if (gotUCopy()) { assert(btranAverageAfterU_); CoinSimplexInt newNumber = static_cast< CoinSimplexInt >(numberNonZero * btranAverageAfterU_ * twiddleBtranFactor1()); if (newNumber < sparseThreshold_) goSparse = true; } #endif #if 0 static int xxxxxx=0; xxxxxx++; if (xxxxxx%20==0) { int smallestK=-1; int largestK=-1; //const CoinBigIndex COIN_RESTRICT *startColumn = startColumnUAddress_; CoinSimplexInt * COIN_RESTRICT pivotRowForward = pivotColumnAddress_; const CoinSimplexInt COIN_RESTRICT *numberInColumn = numberInColumnAddress_; for (CoinSimplexInt k = numberRows_-1 ; k >= 0; k-- ) { CoinSimplexInt i=pivotRowForward[k]; if (numberInColumn[i]) { if (largestK<0) largestK=k; smallestK=k; } } printf("UByCol %d slacks largestK %d smallestK %d\n",numberSlacks_,largestK,smallestK); //const CoinBigIndex * COIN_RESTRICT startRow = startRowUAddress_; const CoinSimplexInt * COIN_RESTRICT numberInRow = numberInRowAddress_; smallestK=-1; largestK=-1; for (CoinSimplexInt k = numberRows_-1 ; k >= 0; k-- ) { CoinSimplexInt i=pivotRowForward[k]; if (numberInRow[i]) { if (largestK<0) largestK=k; smallestK=k; } } printf("and ByRow largestK %d smallestK %d\n",largestK,smallestK); } #endif if (numberNonZero < 40 && (numberNonZero << 4) < numberRows_ && !goSparse) { CoinSimplexInt *COIN_RESTRICT pivotRowForward = pivotColumnAddress_; CoinSimplexInt smallest = numberRowsExtra_; for (CoinSimplexInt j = 0; j < numberNonZero; j++) { CoinSimplexInt iRow = regionIndex[j]; if (pivotRowForward[iRow] < smallest) { smallest = pivotRowForward[iRow]; smallestIndex = iRow; } } } updateColumnTransposeU(®ionSparse, smallestIndex #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif #if ABC_PARALLEL , 0 #endif ); //row bits here updateColumnTransposeR(®ionSparse #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif ); // ******* L updateColumnTransposeL(®ionSparse #if ABC_SMALL < 2 , reinterpret_cast< CoinAbcStatistics & >(btranCountInput_) #endif #if ABC_PARALLEL , 0 #endif ); #if ABC_SMALL < 3 #ifdef ABC_ORDERED_FACTORIZATION // Permute out for Btran permuteOutForBtran(regionSparse); #endif #if ABC_DEBUG regionSparse.checkClean(); #endif numberNonZero = regionSparse.getNumElements(); #else numberNonZero = 0; for (CoinSimplexInt i = 0; i < numberRows_; i++) { CoinExponent expValue = ABC_EXPONENT(region[i]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; } } } regionSparse.setNumElements(numberNonZero); #endif fromLongArray(static_cast< int >(0)); return numberNonZero; } #if ABC_SMALL < 2 /* Updates part of column transpose (BTRANU) when densish, assumes index is sorted i.e. region is correct */ void CoinAbcTypeFactorization::updateColumnTransposeUDensish(CoinIndexedVector *regionSparse, CoinSimplexInt smallestIndex) const { CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt numberNonZero = regionSparse->getNumElements(); CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); const CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_; const CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_; const CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_; const CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_; numberNonZero = 0; const CoinSimplexInt *COIN_RESTRICT pivotLinked = pivotLinkedForwardsAddress_; CoinSimplexInt jRow = smallestIndex; //pivotLinked[-1]; instrument_start("CoinAbcFactorizationUpdateTransposeUDensish", numberRows_); while (jRow >= 0) { if (TEST_DOUBLE_NONZERO(region[jRow])) { CoinFactorizationDouble pivotValue = region[jRow]; if (!TEST_LESS_THAN_UPDATE_TOLERANCE(pivotValue)) { CoinSimplexInt numberIn = numberInRow[jRow]; instrument_add(numberIn); if (TEST_INT_NONZERO(numberIn)) { CoinBigIndex start = startRow[jRow]; CoinBigIndex end = start + numberIn; #ifndef INLINE_IT for (CoinBigIndex j = start; j < end; j++) { CoinSimplexInt iRow = indexColumn[j]; CoinFactorizationDouble value = elementRowU[j]; assert(value); // isetNumElements(numberNonZero); instrument_end(); } /* Updates part of column transpose (BTRANU) when sparse, assumes index is sorted i.e. region is correct */ void CoinAbcTypeFactorization::updateColumnTransposeUSparse( CoinIndexedVector *regionSparse #if ABC_PARALLEL , int whichSparse #endif ) const { CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt numberNonZero = regionSparse->getNumElements(); CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); const CoinBigIndex *COIN_RESTRICT startRow = startRowUAddress_; const CoinSimplexInt *COIN_RESTRICT indexColumn = indexColumnUAddress_; const CoinSimplexInt *COIN_RESTRICT numberInRow = numberInRowAddress_; const CoinFactorizationDouble *COIN_RESTRICT elementRowU = elementRowUAddress_; // use sparse_ as temporary area // mark known to be zero //printf("PP 0_ %d %s\n",__LINE__,__FILE__); CoinAbcStack *COIN_RESTRICT stackList = reinterpret_cast< CoinAbcStack * >(sparseAddress_); CoinSimplexInt *COIN_RESTRICT list = listAddress_; CoinCheckZero *COIN_RESTRICT mark = markRowAddress_; #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) { //printf("alternative sparse\n"); int addAmount = whichSparse * sizeSparseArray_; stackList = reinterpret_cast< CoinAbcStack * >(reinterpret_cast< char * >(stackList) + addAmount); list = reinterpret_cast< CoinSimplexInt * >(reinterpret_cast< char * >(list) + addAmount); mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + addAmount); } #endif CoinSimplexInt nList; #if 0 //ndef NDEBUG for (CoinSimplexInt i=0;i=startThis;j--) { CoinSimplexInt kPivot3=indexColumn[j--]; if (!mark[kPivot3]) { kPivot=kPivot3; break; } } if (j>=startThis) { /* put back on stack */ stackList[nStack++].next =j; /* and new one */ CoinBigIndex start=startRow[kPivot]; j=start+numberInRow[kPivot]-1; stackList[nStack].stack=kPivot; stackList[nStack].start=start; mark[kPivot]=2; stackList[nStack++].next=j; #else CoinBigIndex j = stackList[nStack].next; if (j >= stackList[nStack].start) { CoinSimplexInt kPivot3 = indexColumn[j--]; /* put back on stack */ stackList[nStack++].next = j; if (!mark[kPivot3]) { /* and new one */ CoinBigIndex start = startRow[kPivot3]; j = start + numberInRow[kPivot3] - 1; stackList[nStack].stack = kPivot3; stackList[nStack].start = start; mark[kPivot3] = 2; stackList[nStack++].next = j; } #endif } else { // finished list[nList++] = kPivot; mark[kPivot] = 1; } } } } instrument_start("CoinAbcFactorizationUpdateTransposeUSparse", 2 * (numberNonZero + nList)); numberNonZero = 0; for (CoinSimplexInt i = nList - 1; i >= 0; i--) { CoinSimplexInt iPivot = list[i]; assert(iPivot >= 0 && iPivot < numberRows_); mark[iPivot] = 0; CoinFactorizationDouble pivotValue = region[iPivot]; if (!TEST_LESS_THAN_UPDATE_TOLERANCE(pivotValue)) { CoinSimplexInt numberIn = numberInRow[iPivot]; instrument_add(numberIn); if (TEST_INT_NONZERO(numberIn)) { CoinBigIndex start = startRow[iPivot]; #ifndef INLINE_IT CoinBigIndex end = start + numberIn; for (CoinBigIndex j = start; j < end; j++) { CoinSimplexInt iRow = indexColumn[j]; CoinFactorizationDouble value = elementRowU[j]; region[iRow] -= value * pivotValue; } #else CoinAbcScatterUpdate(numberIn, pivotValue, elementRowU + start, indexColumn + start, region); #endif } regionIndex[numberNonZero++] = iPivot; } else { region[iPivot] = 0.0; } } //set counts regionSparse->setNumElements(numberNonZero); instrument_end_and_adjust(1.3); } #endif // updateColumnTransposeU. Updates part of column transpose (BTRANU) //assumes index is sorted i.e. region is correct //does not sort by sign void CoinAbcTypeFactorization::updateColumnTransposeU(CoinIndexedVector *regionSparse, CoinSimplexInt smallestIndex #if ABC_SMALL < 2 , CoinAbcStatistics &statistics #endif #if ABC_PARALLEL , int whichCpu #endif ) const { #if CILK_CONFLICT > 0 #if ABC_PARALLEL // for conflicts #if CILK_CONFLICT > 1 printf("file %s line %d which %d\n", __FILE__, __LINE__, whichCpu); #endif abc_assert((cilk_conflict & (1 << whichCpu)) == 0); cilk_conflict |= (1 << whichCpu); #else abc_assert((cilk_conflict & (1 << 0)) == 0); cilk_conflict |= (1 << 0); #endif #endif #if ABC_SMALL < 2 CoinSimplexInt number = regionSparse->getNumElements(); if (factorizationStatistics()) { statistics.numberCounts_++; statistics.countInput_ += static_cast< CoinSimplexDouble >(number); } CoinSimplexInt goSparse; // Guess at number at end if (gotUCopy()) { if (gotSparse()) { assert(statistics.averageAfterU_); CoinSimplexInt newNumber = static_cast< CoinSimplexInt >(number * statistics.averageAfterU_ * twiddleBtranFactor1()); if (newNumber < sparseThreshold_) goSparse = 2; else goSparse = 0; } else { goSparse = 0; } #if ABC_SMALL >= 0 } else { goSparse = -1; #endif } //CoinIndexedVector temp(*regionSparse); switch (goSparse) { #if ABC_SMALL >= 0 case -1: // no row copy updateColumnTransposeUByColumn(regionSparse, smallestIndex); break; #endif case 0: // densish updateColumnTransposeUDensish(regionSparse, smallestIndex); break; case 2: // sparse { updateColumnTransposeUSparse(regionSparse #if ABC_PARALLEL , whichCpu #endif ); } break; } if (factorizationStatistics()) statistics.countAfterU_ += static_cast< CoinSimplexDouble >(regionSparse->getNumElements()); #else updateColumnTransposeUByColumn(regionSparse, smallestIndex); #endif #if CILK_CONFLICT > 0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict & (1 << whichCpu)) != 0); cilk_conflict &= ~(1 << whichCpu); #else abc_assert((cilk_conflict & (1 << 0)) != 0); cilk_conflict &= ~(1 << 0); #endif #endif } /* updateColumnTransposeLDensish. Updates part of column transpose (BTRANL) dense by column */ void CoinAbcTypeFactorization::updateColumnTransposeLDensish(CoinIndexedVector *regionSparse) const { CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt base; CoinSimplexInt first = -1; const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; //const CoinSimplexInt * COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; #if ABC_SMALL < 3 CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinSimplexInt numberNonZero = 0; #endif //scan for (first = numberRows_ - 1; first >= 0; first--) { #ifndef ABC_ORDERED_FACTORIZATION if (region[pivotLOrder[first]]) break; #else if (region[first]) break; #endif } instrument_start("CoinAbcFactorizationUpdateTransposeLDensish", first); if (first >= 0) { base = baseL_; const CoinBigIndex *COIN_RESTRICT startColumn = startColumnLAddress_; const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowLAddress_; const CoinFactorizationDouble *COIN_RESTRICT element = elementLAddress_; CoinSimplexInt last = baseL_ + numberL_; if (first >= last) { first = last - 1; } CoinBigIndex end = startColumn[first + 1]; for (CoinSimplexInt k = first; k >= base; k--) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i = pivotLOrder[k]; #else CoinSimplexInt i = k; #endif CoinFactorizationDouble pivotValue = region[i]; #ifndef INLINE_IT2 CoinBigIndex j = end - 1; end = startColumn[k]; instrument_add(j - end); for (; j >= end; j--) { CoinSimplexInt iRow = indexRow[j]; CoinFactorizationDouble value = element[j]; pivotValue -= value * region[iRow]; } #else CoinBigIndex start = startColumn[k]; instrument_add(end - start); pivotValue += CoinAbcGatherUpdate(end - start, element + start, indexRow + start, region); end = start; #endif #if ABC_SMALL < 3 if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) { region[i] = pivotValue; regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; } #else region[i] = pivotValue; #endif } #if ABC_SMALL < 3 //may have stopped early if (first < base) { base = first + 1; } for (CoinSimplexInt k = base - 1; k >= 0; k--) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i = pivotLOrder[k]; #else CoinSimplexInt i = k; #endif CoinExponent expValue = ABC_EXPONENT(region[i]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; } } } #endif } #if ABC_SMALL < 3 //set counts regionSparse->setNumElements(numberNonZero); #endif instrument_end(); } #if ABC_SMALL < 2 /* updateColumnTransposeLByRow. Updates part of column transpose (BTRANL) densish but by row */ void CoinAbcTypeFactorization::updateColumnTransposeLByRow(CoinIndexedVector *regionSparse) const { CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinSimplexInt numberNonZero; // use row copy of L const CoinFactorizationDouble *COIN_RESTRICT element = elementByRowLAddress_; const CoinBigIndex *COIN_RESTRICT startRow = startRowLAddress_; const CoinSimplexInt *COIN_RESTRICT column = indexColumnLAddress_; const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; numberNonZero = 0; instrument_start("CoinAbcFactorizationUpdateTransposeLByRow", numberRows_ + numberSlacks_); // down to slacks for (CoinSimplexInt k = numberRows_ - 1; k >= numberSlacks_; k--) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i = pivotLOrder[k]; #else CoinSimplexInt i = k; #endif if (TEST_DOUBLE_NONZERO(region[i])) { CoinFactorizationDouble pivotValue = region[i]; if (!TEST_LESS_THAN_TOLERANCE(pivotValue)) { regionIndex[numberNonZero++] = i; CoinBigIndex start = startRow[i]; CoinBigIndex end = startRow[i + 1]; instrument_add(end - start); if (TEST_INT_NONZERO(end - start)) { #ifndef INLINE_IT for (CoinBigIndex j = end - 1; j >= start; j--) { CoinSimplexInt iRow = column[j]; CoinFactorizationDouble value = element[j]; region[iRow] -= pivotValue * value; } #else CoinAbcScatterUpdate(end - start, pivotValue, element + start, column + start, region); #endif } } else { region[i] = 0.0; } } } for (CoinSimplexInt k = numberSlacks_ - 1; k >= 0; k--) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt i = pivotLOrder[k]; #else CoinSimplexInt i = k; #endif CoinExponent expValue = ABC_EXPONENT(region[i]); if (expValue) { if (!TEST_EXPONENT_LESS_THAN_TOLERANCE(expValue)) { regionIndex[numberNonZero++] = i; } else { region[i] = 0.0; } } } //set counts regionSparse->setNumElements(numberNonZero); instrument_end(); } /* updateColumnTransposeLSparse. Updates part of column transpose (BTRANL) sparse */ void CoinAbcTypeFactorization::updateColumnTransposeLSparse(CoinIndexedVector *regionSparse #if ABC_PARALLEL , int whichSparse #endif ) const { CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinSimplexInt numberNonZero = regionSparse->getNumElements(); // use row copy of L const CoinFactorizationDouble *COIN_RESTRICT element = elementByRowLAddress_; const CoinBigIndex *COIN_RESTRICT startRow = startRowLAddress_; const CoinSimplexInt *COIN_RESTRICT column = indexColumnLAddress_; // use sparse_ as temporary area // mark known to be zero //printf("PP 0_ %d %s\n",__LINE__,__FILE__); CoinAbcStack *COIN_RESTRICT stackList = reinterpret_cast< CoinAbcStack * >(sparseAddress_); CoinSimplexInt *COIN_RESTRICT list = listAddress_; CoinCheckZero *COIN_RESTRICT mark = markRowAddress_; #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) { int addAmount = whichSparse * sizeSparseArray_; //printf("alternative sparse\n"); stackList = reinterpret_cast< CoinAbcStack * >(reinterpret_cast< char * >(stackList) + addAmount); list = reinterpret_cast< CoinSimplexInt * >(reinterpret_cast< char * >(list) + addAmount); mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + addAmount); } #endif #ifndef NDEBUG for (CoinSimplexInt i = 0; i < numberRows_; i++) { #if 0 assert (!mark[i]); #else if (mark[i]) { printf("HHHHHHHHHHelp2 %d %d\n", i, mark[i]); usleep(10000000); } #endif } #endif CoinSimplexInt nList; CoinSimplexInt number = numberNonZero; nList = 0; for (CoinSimplexInt k = 0; k < number; k++) { CoinSimplexInt kPivot = regionIndex[k]; //CoinSimplexInt iPivot=pivotLBackwardOrder[kPivot]; if (!mark[kPivot] && region[kPivot]) { stackList[0].stack = kPivot; stackList[0].start = startRow[kPivot]; CoinBigIndex j = startRow[kPivot + 1] - 1; CoinSimplexInt nStack = 0; while (nStack >= 0) { /* take off stack */ if (j >= stackList[nStack].start) { CoinSimplexInt jPivot = column[j--]; /* put back on stack */ stackList[nStack].next = j; if (!mark[jPivot]) { /* and new one */ kPivot = jPivot; //iPivot=pivotLBackwardOrder[kPivot]; j = startRow[kPivot + 1] - 1; stackList[++nStack].stack = kPivot; mark[kPivot] = 1; stackList[nStack].start = startRow[kPivot]; stackList[nStack].next = j; } } else { /* finished so mark */ list[nList++] = kPivot; mark[kPivot] = 1; --nStack; if (nStack >= 0) { kPivot = stackList[nStack].stack; j = stackList[nStack].next; } } } } } instrument_start("CoinAbcFactorizationUpdateTransposeLSparse", 2 * (numberNonZero + nList)); numberNonZero = 0; for (CoinSimplexInt i = nList - 1; i >= 0; i--) { CoinSimplexInt iPivot = list[i]; //CoinSimplexInt kPivot=pivotLOrder[iPivot]; mark[iPivot] = 0; CoinFactorizationDouble pivotValue = region[iPivot]; if (!TEST_LESS_THAN_TOLERANCE(pivotValue)) { regionIndex[numberNonZero++] = iPivot; CoinBigIndex start = startRow[iPivot]; CoinBigIndex end = startRow[iPivot + 1]; instrument_add(end - start); #ifndef INLINE_IT CoinBigIndex j; for (j = start; j < end; j++) { CoinSimplexInt iRow = column[j]; CoinFactorizationDouble value = element[j]; region[iRow] -= value * pivotValue; } #else CoinAbcScatterUpdate(end - start, pivotValue, element + start, column + start, region); #endif } else { region[iPivot] = 0.0; } } //set counts regionSparse->setNumElements(numberNonZero); instrument_end_and_adjust(1.3); } #endif // updateColumnTransposeL. Updates part of column transpose (BTRANL) void CoinAbcTypeFactorization::updateColumnTransposeL(CoinIndexedVector *regionSparse #if ABC_SMALL < 2 , CoinAbcStatistics &statistics #endif #if ABC_PARALLEL , int whichSparse #endif ) const { #if CILK_CONFLICT > 0 #if ABC_PARALLEL // for conflicts #if CILK_CONFLICT > 1 printf("file %s line %d which %d\n", __FILE__, __LINE__, whichSparse); #endif abc_assert((cilk_conflict & (1 << whichSparse)) == 0); cilk_conflict |= (1 << whichSparse); #else abc_assert((cilk_conflict & (1 << 0)) == 0); cilk_conflict |= (1 << 0); #endif #endif #if ABC_SMALL < 3 CoinSimplexInt number = regionSparse->getNumElements(); #endif if (!numberL_ #if ABC_SMALL < 4 && !numberDense_ #endif ) { #if ABC_SMALL < 3 if (number >= numberRows_) { // need scan regionSparse->setNumElements(0); scan(regionSparse); } #endif #if CILK_CONFLICT > 0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict & (1 << whichSparse)) != 0); cilk_conflict &= ~(1 << whichSparse); #else abc_assert((cilk_conflict & (1 << 0)) != 0); cilk_conflict &= ~(1 << 0); #endif #endif return; } #if ABC_SMALL < 2 CoinSimplexInt goSparse; // Guess at number at end // we may need to rethink on dense if (gotLCopy()) { assert(statistics.averageAfterL_); CoinSimplexInt newNumber = static_cast< CoinSimplexInt >(number * statistics.averageAfterL_ * twiddleBtranFactor1()); if (newNumber < sparseThreshold_) goSparse = 2; else if (2 * newNumber < numberRows_) goSparse = 0; else goSparse = -1; } else { goSparse = -1; } #endif #if ABC_SMALL < 4 #if ABC_DENSE_CODE > 0 if (numberDense_) { //take off list CoinSimplexInt lastSparse = numberRows_ - numberDense_; CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; CoinFactorizationDouble *COIN_RESTRICT denseArea = denseAreaAddress_; CoinFactorizationDouble *COIN_RESTRICT denseRegion = denseArea + leadingDimension_ * numberDense_; CoinSimplexInt *COIN_RESTRICT densePermute = reinterpret_cast< CoinSimplexInt * >(denseRegion + FACTOR_CPU * numberDense_); #if ABC_PARALLEL //printf("PP %d %d %s\n",whichSparse,__LINE__,__FILE__); if (whichSparse) denseRegion += whichSparse * numberDense_; #endif CoinFactorizationDouble *COIN_RESTRICT densePut = denseRegion - lastSparse; CoinZeroN(denseRegion, numberDense_); bool doDense = false; #if ABC_SMALL < 3 CoinSimplexInt number = regionSparse->getNumElements(); CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); const CoinSimplexInt *COIN_RESTRICT pivotLBackwardOrder = permuteAddress_; CoinSimplexInt i = 0; #if ABC_SMALL < 0 assert(number <= numberRows_); #else if (number <= numberRows_) { #endif while (i < number) { CoinSimplexInt iRow = regionIndex[i]; #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt jRow = pivotLBackwardOrder[iRow]; #else CoinSimplexInt jRow = iRow; #endif if (jRow >= lastSparse) { doDense = true; regionIndex[i] = regionIndex[--number]; densePut[jRow] = region[iRow]; region[iRow] = 0.0; } else { i++; } } #endif #if ABC_SMALL >= 0 #if ABC_SMALL < 3 } else { #endif for (CoinSimplexInt jRow = lastSparse; jRow < numberRows_; jRow++) { CoinSimplexInt iRow = pivotLOrder[jRow]; if (region[iRow]) { doDense = true; densePut[jRow] = region[iRow]; region[iRow] = 0.0; } } #if ABC_SMALL < 3 // numbers are all wrong - do a scan regionSparse->setNumElements(0); scan(regionSparse); number = regionSparse->getNumElements(); } #endif #endif if (doDense) { instrument_do("CoinAbcFactorizationDenseTranspose", 0.25 * numberDense_ * numberDense_); #if ABC_DENSE_CODE == 1 #ifndef CLAPACK char trans = 'T'; CoinSimplexInt ione = 1; CoinSimplexInt info; LAPACK_FUNC(dgetrs, DGETRS) (&trans, &numberDense_, &ione, denseArea, &leadingDimension_, densePermute, denseRegion, &numberDense_, &info, 1); #else clapack_dgetrs(CblasColMajor, CblasTrans, numberDense_, 1, denseArea, leadingDimension_, densePermute, denseRegion, numberDense_); #endif #elif ABC_DENSE_CODE == 2 CoinAbcDgetrs('T', numberDense_, denseArea, denseRegion); short *COIN_RESTRICT forBtran = reinterpret_cast< short * >(densePermute + numberDense_) + numberDense_ - lastSparse; pivotLOrder += lastSparse; // adjust #endif for (CoinSimplexInt i = lastSparse; i < numberRows_; i++) { CoinSimplexDouble value = densePut[i]; if (value) { if (!TEST_LESS_THAN_TOLERANCE(value)) { #if ABC_DENSE_CODE != 2 CoinSimplexInt iRow = pivotLOrder[i]; #else CoinSimplexInt iRow = pivotLOrder[forBtran[i]]; #endif region[iRow] = value; #if ABC_SMALL < 3 regionIndex[number++] = iRow; #endif } } } #if ABC_SMALL < 3 regionSparse->setNumElements(number); #endif } } //printRegion(*regionSparse,"After BtranL"); #endif #endif #if ABC_SMALL < 2 switch (goSparse) { case -1: // No row copy updateColumnTransposeLDensish(regionSparse); break; case 0: // densish but by row updateColumnTransposeLByRow(regionSparse); break; case 2: // sparse updateColumnTransposeLSparse(regionSparse #if ABC_PARALLEL , whichSparse #endif ); break; } #else updateColumnTransposeLDensish(regionSparse); #endif #if CILK_CONFLICT > 0 #if ABC_PARALLEL // for conflicts abc_assert((cilk_conflict & (1 << whichSparse)) != 0); cilk_conflict &= ~(1 << whichSparse); #else abc_assert((cilk_conflict & (1 << 0)) != 0); cilk_conflict &= ~(1 << 0); #endif #endif } #if ABC_SMALL >= 0 // Updates part of column transpose (BTRANR) when dense void CoinAbcTypeFactorization::updateColumnTransposeRDensish(CoinIndexedVector *regionSparse) const { const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_; CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); #if ABC_SMALL < 3 #ifdef ABC_DEBUG regionSparse->checkClean(); #endif #endif instrument_start("CoinAbcFactorizationUpdateTransposeRDensish", numberRows_); CoinSimplexInt last = numberRowsExtra_ - 1; const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowRAddress_; const CoinFactorizationDouble *COIN_RESTRICT element = elementRAddress_; const CoinSimplexInt *COIN_RESTRICT pivotRowBack = pivotColumnAddress_; for (CoinSimplexInt i = last; i >= numberRows_; i--) { CoinSimplexInt putRow = pivotRowBack[i]; CoinFactorizationDouble pivotValue = region[putRow]; if (pivotValue) { CoinBigIndex start = startColumn[i]; CoinBigIndex end = startColumn[i + 1]; instrument_add(end - start); #ifndef INLINE_IT for (CoinBigIndex j = start; j < end; j++) { CoinFactorizationDouble value = element[j]; CoinSimplexInt iRow = indexRow[j]; assert(iRow < numberRows_); region[iRow] -= value * pivotValue; } #else CoinAbcScatterUpdate(end - start, pivotValue, element + start, indexRow + start, region); #endif region[putRow] = pivotValue; } } instrument_end(); } #endif #if ABC_SMALL < 2 // Updates part of column transpose (BTRANR) when sparse void CoinAbcTypeFactorization::updateColumnTransposeRSparse(CoinIndexedVector *regionSparse) const { CoinFactorizationDouble *COIN_RESTRICT region = denseVector(regionSparse); CoinSimplexInt *COIN_RESTRICT regionIndex = regionSparse->getIndices(); CoinSimplexInt numberNonZero = regionSparse->getNumElements(); instrument_start("CoinAbcFactorizationUpdateTransposeRSparse", numberRows_); #if ABC_SMALL < 3 #ifdef ABC_DEBUG regionSparse->checkClean(); #endif #endif CoinSimplexInt last = numberRowsExtra_ - 1; const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowRAddress_; const CoinFactorizationDouble *COIN_RESTRICT element = elementRAddress_; const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_; //move using lookup const CoinSimplexInt *COIN_RESTRICT pivotRowBack = pivotColumnAddress_; // still need to do in correct order (for now) for (CoinSimplexInt i = last; i >= numberRows_; i--) { CoinSimplexInt putRow = pivotRowBack[i]; CoinFactorizationDouble pivotValue = region[putRow]; if (pivotValue) { instrument_add(startColumn[i + 1] - startColumn[i]); for (CoinBigIndex j = startColumn[i]; j < startColumn[i + 1]; j++) { CoinFactorizationDouble value = element[j]; CoinSimplexInt iRow = indexRow[j]; assert(iRow < numberRows_); bool oldValue = (TEST_DOUBLE_REALLY_NONZERO(region[iRow])); CoinFactorizationDouble newValue = region[iRow] - value * pivotValue; if (oldValue) { if (newValue) region[iRow] = newValue; else region[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } else if (!TEST_LESS_THAN_TOLERANCE_REGISTER(newValue)) { region[iRow] = newValue; regionIndex[numberNonZero++] = iRow; } } region[putRow] = pivotValue; } } instrument_end(); regionSparse->setNumElements(numberNonZero); } #endif // updateColumnTransposeR. Updates part of column (FTRANR) void CoinAbcTypeFactorization::updateColumnTransposeR(CoinIndexedVector *regionSparse #if ABC_SMALL < 2 , CoinAbcStatistics &statistics #endif ) const { if (numberRowsExtra_ == numberRows_) return; #if ABC_SMALL < 3 CoinSimplexInt numberNonZero = regionSparse->getNumElements(); if (numberNonZero) { #endif #if ABC_SMALL < 3 const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_; #endif // Size of R instrument_do("CoinAbcFactorizationTransposeR", startColumnRAddress_[numberR_]); #if ABC_SMALL < 2 if (startColumn[numberRowsExtra_]) { #if ABC_SMALL >= 0 if (numberNonZero < ((sparseThreshold_ << 2) * twiddleBtranFactor2()) || (!numberL_ && gotLCopy() && gotRCopy())) { #endif updateColumnTransposeRSparse(regionSparse); if (factorizationStatistics()) statistics.countAfterR_ += regionSparse->getNumElements(); #if ABC_SMALL >= 0 } else { updateColumnTransposeRDensish(regionSparse); // we have lost indices // make sure won't try and go sparse again if (factorizationStatistics()) statistics.countAfterR_ += CoinMin((numberNonZero << 1), numberRows_); // temp +2 (was +1) regionSparse->setNumElements(numberRows_ + 2); } #endif } else { if (factorizationStatistics()) statistics.countAfterR_ += numberNonZero; } #else updateColumnTransposeRDensish(regionSparse); #if ABC_SMALL < 3 // we have lost indices // make sure won't try and go sparse again // temp +2 (was +1) regionSparse->setNumElements(numberRows_ + 2); #endif #endif #if ABC_SMALL < 3 } #endif } // Update partial Ftran by R update void CoinAbcTypeFactorization::updatePartialUpdate(CoinIndexedVector &partialUpdate) { CoinSimplexDouble *COIN_RESTRICT region = partialUpdate.denseVector(); CoinSimplexInt *COIN_RESTRICT regionIndex = partialUpdate.getIndices(); CoinSimplexInt numberNonZero = partialUpdate.getNumElements(); const CoinSimplexInt *COIN_RESTRICT indexRow = indexRowRAddress_; const CoinFactorizationDouble *COIN_RESTRICT element = elementRAddress_; const CoinSimplexInt *pivotRowBack = pivotColumnAddress_; const CoinBigIndex *COIN_RESTRICT startColumn = startColumnRAddress_ - numberRows_; CoinBigIndex start = startColumn[numberRowsExtra_ - 1]; CoinBigIndex end = startColumn[numberRowsExtra_]; CoinSimplexInt iRow = pivotRowBack[numberRowsExtra_ - 1]; CoinFactorizationDouble pivotValue = region[iRow]; for (CoinBigIndex j = start; j < end; j++) { CoinFactorizationDouble value = element[j]; CoinSimplexInt jRow = indexRow[j]; value *= region[jRow]; pivotValue -= value; } if (!TEST_LESS_THAN_TOLERANCE_REGISTER(pivotValue)) { if (!region[iRow]) regionIndex[numberNonZero++] = iRow; region[iRow] = pivotValue; } else { if (region[iRow]) region[iRow] = COIN_INDEXED_REALLY_TINY_ELEMENT; } partialUpdate.setNumElements(numberNonZero); } #if FACTORIZATION_STATISTICS #ifdef ABC_JUST_ONE_FACTORIZATION #define FACTORS_HERE #endif #ifdef FACTORS_HERE double ftranTwiddleFactor1X = 1.0; double ftranTwiddleFactor2X = 1.0; double ftranFTTwiddleFactor1X = 1.0; double ftranFTTwiddleFactor2X = 1.0; double btranTwiddleFactor1X = 1.0; double btranTwiddleFactor2X = 1.0; double ftranFullTwiddleFactor1X = 1.0; double ftranFullTwiddleFactor2X = 1.0; double btranFullTwiddleFactor1X = 1.0; double btranFullTwiddleFactor2X = 1.0; double denseThresholdX = 31; double twoThresholdX = 1000; double minRowsSparse = 300; double largeRowsSparse = 10000; double mediumRowsDivider = 6; double mediumRowsMinCount = 500; double largeRowsCount = 1000; #else extern double ftranTwiddleFactor1X; extern double ftranTwiddleFactor2X; extern double ftranFTTwiddleFactor1X; extern double ftranFTTwiddleFactor2X; extern double btranTwiddleFactor1X; extern double btranTwiddleFactor2X; extern double ftranFullTwiddleFactor1X; extern double ftranFullTwiddleFactor2X; extern double btranFullTwiddleFactor1X; extern double btranFullTwiddleFactor2X; extern double denseThresholdX; extern double twoThresholdX; extern double minRowsSparse; extern double largeRowsSparse; extern double mediumRowsDivider; extern double mediumRowsMinCount; extern double largeRowsCount; #endif #else #define minRowsSparse 300 #define largeRowsSparse 10000 #define mediumRowsDivider 6 #define mediumRowsMinCount 500 #define largeRowsCount 1000 #endif // makes a row copy of L void CoinAbcTypeFactorization::goSparse2() { #if ABC_SMALL < 2 #if ABC_SMALL >= 0 if (numberRows_ > minRowsSparse) { #endif if (numberRows_ < largeRowsSparse) { sparseThreshold_ = CoinMin(numberRows_ / mediumRowsDivider, mediumRowsMinCount); sparseThreshold_ = CoinMin(numberRows_ / 6, 500); } else { sparseThreshold_ = CoinMax(largeRowsCount, numberRows_ >> 3); sparseThreshold_ = 500; } #if FACTORIZATION_STATISTICS ftranTwiddleFactor1_ = ftranTwiddleFactor1X; ftranTwiddleFactor2_ = ftranTwiddleFactor2X; ftranFTTwiddleFactor1_ = ftranFTTwiddleFactor1X; ftranFTTwiddleFactor2_ = ftranFTTwiddleFactor2X; btranTwiddleFactor1_ = btranTwiddleFactor1X; btranTwiddleFactor2_ = btranTwiddleFactor2X; ftranFullTwiddleFactor1_ = ftranFullTwiddleFactor1X; ftranFullTwiddleFactor2_ = ftranFullTwiddleFactor2X; btranFullTwiddleFactor1_ = btranFullTwiddleFactor1X; btranFullTwiddleFactor2_ = btranFullTwiddleFactor2X; #endif setYesGotLCopy(); setYesGotUCopy(); setYesGotSparse(); // allow for stack, list, next, starts and char map of mark CoinSimplexInt nRowIndex = (numberRows_ + CoinSizeofAsInt(CoinSimplexInt) - 1) / CoinSizeofAsInt(char); CoinSimplexInt nInBig = static_cast< CoinSimplexInt >(sizeof(CoinBigIndex) / sizeof(CoinSimplexInt)); assert(nInBig >= 1); sizeSparseArray_ = (2 + 2 * nInBig) * numberRows_ + nRowIndex; sparse_.conditionalNew(FACTOR_CPU * sizeSparseArray_); sparseAddress_ = sparse_.array(); // zero out mark CoinAbcStack *stackList = reinterpret_cast< CoinAbcStack * >(sparseAddress_); listAddress_ = reinterpret_cast< CoinSimplexInt * >(stackList + numberRows_); markRowAddress_ = reinterpret_cast< CoinCheckZero * >(listAddress_ + numberRows_); assert(reinterpret_cast< CoinCheckZero * >(sparseAddress_ + (2 + 2 * nInBig) * numberRows_) == markRowAddress_); CoinAbcMemset0(markRowAddress_, nRowIndex); #if ABC_PARALLEL //printf("PP 0__ %d %s\n",__LINE__,__FILE__); // convert to bytes sizeSparseArray_ *= sizeof(CoinSimplexInt); char *mark = reinterpret_cast< char * >(reinterpret_cast< char * >(markRowAddress_) + sizeSparseArray_); for (int i = 1; i < FACTOR_CPU; i++) { CoinAbcMemset0(mark, nRowIndex); mark = reinterpret_cast< char * >(reinterpret_cast< char * >(mark) + sizeSparseArray_); } #endif elementByRowL_.conditionalDelete(); indexColumnL_.conditionalDelete(); startRowL_.conditionalNew(numberRows_ + 1); if (lengthAreaL_) { elementByRowL_.conditionalNew(lengthAreaL_); indexColumnL_.conditionalNew(lengthAreaL_); } elementByRowLAddress_ = elementByRowL_.array(); indexColumnLAddress_ = indexColumnL_.array(); startRowLAddress_ = startRowL_.array(); // counts CoinBigIndex *COIN_RESTRICT startRowL = startRowLAddress_; CoinZeroN(startRowL, numberRows_); const CoinBigIndex *startColumnL = startColumnLAddress_; CoinFactorizationDouble *COIN_RESTRICT elementL = elementLAddress_; const CoinSimplexInt *indexRowL = indexRowLAddress_; for (CoinSimplexInt i = baseL_; i < baseL_ + numberL_; i++) { for (CoinBigIndex j = startColumnL[i]; j < startColumnL[i + 1]; j++) { CoinSimplexInt iRow = indexRowL[j]; startRowL[iRow]++; } } const CoinSimplexInt *COIN_RESTRICT pivotLOrder = pivotLOrderAddress_; // convert count to lasts CoinBigIndex count = 0; for (CoinSimplexInt i = 0; i < numberRows_; i++) { CoinSimplexInt numberInRow = startRowL[i]; count += numberInRow; startRowL[i] = count; } startRowL[numberRows_] = count; // now insert CoinFactorizationDouble *COIN_RESTRICT elementByRowL = elementByRowLAddress_; CoinSimplexInt *COIN_RESTRICT indexColumnL = indexColumnLAddress_; for (CoinSimplexInt i = baseL_ + numberL_ - 1; i >= baseL_; i--) { #ifndef ABC_ORDERED_FACTORIZATION CoinSimplexInt iPivot = pivotLOrder[i]; #else CoinSimplexInt iPivot = i; #endif for (CoinBigIndex j = startColumnL[i]; j < startColumnL[i + 1]; j++) { CoinSimplexInt iRow = indexRowL[j]; CoinBigIndex start = startRowL[iRow] - 1; startRowL[iRow] = start; elementByRowL[start] = elementL[j]; indexColumnL[start] = iPivot; } } #if ABC_SMALL >= 0 } else { sparseThreshold_ = 0; setNoGotLCopy(); //setYesGotUCopy(); setNoGotUCopy(); setNoGotSparse(); } #endif #endif } // set sparse threshold void CoinAbcTypeFactorization::sparseThreshold(CoinSimplexInt /*value*/) { return; #if 0 if (value>0&&sparseThreshold_) { sparseThreshold_=value; } else if (!value&&sparseThreshold_) { // delete copy sparseThreshold_=0; elementByRowL_.conditionalDelete(); startRowL_.conditionalDelete(); indexColumnL_.conditionalDelete(); sparse_.conditionalDelete(); } else if (value>0&&!sparseThreshold_) { if (value>1) sparseThreshold_=value; else sparseThreshold_=0; goSparse(); } #endif } void CoinAbcTypeFactorization::maximumPivots(CoinSimplexInt value) { if (value > 0) { if (numberRows_) maximumMaximumPivots_ = CoinMax(maximumMaximumPivots_, value); else maximumMaximumPivots_ = value; maximumPivots_ = value; } //printf("max %d maxmax %d\n",maximumPivots_,maximumMaximumPivots_); } void CoinAbcTypeFactorization::messageLevel(CoinSimplexInt value) { if (value > 0 && value < 16) { messageLevel_ = value; } } // Reset all sparsity etc statistics void CoinAbcTypeFactorization::resetStatistics() { #if ABC_SMALL < 2 setStatistics(true); /// Below are all to collect ftranCountInput_ = 0.0; ftranCountAfterL_ = 0.0; ftranCountAfterR_ = 0.0; ftranCountAfterU_ = 0.0; ftranFTCountInput_ = 0.0; ftranFTCountAfterL_ = 0.0; ftranFTCountAfterR_ = 0.0; ftranFTCountAfterU_ = 0.0; btranCountInput_ = 0.0; btranCountAfterU_ = 0.0; btranCountAfterR_ = 0.0; btranCountAfterL_ = 0.0; ftranFullCountInput_ = 0.0; ftranFullCountAfterL_ = 0.0; ftranFullCountAfterR_ = 0.0; ftranFullCountAfterU_ = 0.0; btranFullCountInput_ = 0.0; btranFullCountAfterL_ = 0.0; btranFullCountAfterR_ = 0.0; btranFullCountAfterU_ = 0.0; /// We can roll over factorizations numberFtranCounts_ = 0; numberFtranFTCounts_ = 0; numberBtranCounts_ = 0; numberFtranFullCounts_ = 0; numberFtranFullCounts_ = 0; /// While these are averages collected over last ftranAverageAfterL_ = INITIAL_AVERAGE; ftranAverageAfterR_ = INITIAL_AVERAGE; ftranAverageAfterU_ = INITIAL_AVERAGE; ftranFTAverageAfterL_ = INITIAL_AVERAGE; ftranFTAverageAfterR_ = INITIAL_AVERAGE; ftranFTAverageAfterU_ = INITIAL_AVERAGE; btranAverageAfterU_ = INITIAL_AVERAGE; btranAverageAfterR_ = INITIAL_AVERAGE; btranAverageAfterL_ = INITIAL_AVERAGE; ftranFullAverageAfterL_ = INITIAL_AVERAGE; ftranFullAverageAfterR_ = INITIAL_AVERAGE; ftranFullAverageAfterU_ = INITIAL_AVERAGE; btranFullAverageAfterL_ = INITIAL_AVERAGE; btranFullAverageAfterR_ = INITIAL_AVERAGE; btranFullAverageAfterU_ = INITIAL_AVERAGE; #endif } // See if worth going sparse void CoinAbcTypeFactorization::checkSparse() { #if ABC_SMALL < 2 // See if worth going sparse and when if (numberFtranCounts_ > 50) { ftranCountInput_ = CoinMax(ftranCountInput_, 1.0); ftranAverageAfterL_ = CoinMax(ftranCountAfterL_ / ftranCountInput_, INITIAL_AVERAGE2); ftranAverageAfterR_ = CoinMax(ftranCountAfterR_ / ftranCountAfterL_, INITIAL_AVERAGE2); ftranAverageAfterU_ = CoinMax(ftranCountAfterU_ / ftranCountAfterR_, INITIAL_AVERAGE2); ftranFTCountInput_ = CoinMax(ftranFTCountInput_, INITIAL_AVERAGE2); ftranFTAverageAfterL_ = CoinMax(ftranFTCountAfterL_ / ftranFTCountInput_, INITIAL_AVERAGE2); ftranFTAverageAfterR_ = CoinMax(ftranFTCountAfterR_ / ftranFTCountAfterL_, INITIAL_AVERAGE2); ftranFTAverageAfterU_ = CoinMax(ftranFTCountAfterU_ / ftranFTCountAfterR_, INITIAL_AVERAGE2); if (btranCountInput_ && btranCountAfterU_ && btranCountAfterR_) { btranAverageAfterU_ = CoinMax(btranCountAfterU_ / btranCountInput_, INITIAL_AVERAGE2); btranAverageAfterR_ = CoinMax(btranCountAfterR_ / btranCountAfterU_, INITIAL_AVERAGE2); btranAverageAfterL_ = CoinMax(btranCountAfterL_ / btranCountAfterR_, INITIAL_AVERAGE2); } else { // we have not done any useful btrans (values pass?) btranAverageAfterU_ = INITIAL_AVERAGE2; btranAverageAfterR_ = INITIAL_AVERAGE2; btranAverageAfterL_ = INITIAL_AVERAGE2; btranFullCountAfterL_ = INITIAL_AVERAGE2; btranFullCountAfterR_ = INITIAL_AVERAGE2; btranFullCountAfterU_ = INITIAL_AVERAGE2; } ftranFullCountInput_ = CoinMax(ftranFullCountInput_, 1.0); ftranFullAverageAfterL_ = CoinMax(ftranFullCountAfterL_ / ftranFullCountInput_, INITIAL_AVERAGE2); ftranFullAverageAfterR_ = CoinMax(ftranFullCountAfterR_ / ftranFullCountAfterL_, INITIAL_AVERAGE2); ftranFullAverageAfterU_ = CoinMax(ftranFullCountAfterU_ / ftranFullCountAfterR_, INITIAL_AVERAGE2); btranFullCountInput_ = CoinMax(btranFullCountInput_, 1.0); btranFullAverageAfterL_ = CoinMax(btranFullCountAfterL_ / btranFullCountInput_, INITIAL_AVERAGE2); btranFullAverageAfterR_ = CoinMax(btranFullCountAfterR_ / btranFullCountAfterL_, INITIAL_AVERAGE2); btranFullAverageAfterU_ = CoinMax(btranFullCountAfterU_ / btranFullCountAfterR_, INITIAL_AVERAGE2); } // scale back ftranCountInput_ *= AVERAGE_SCALE_BACK; ftranCountAfterL_ *= AVERAGE_SCALE_BACK; ftranCountAfterR_ *= AVERAGE_SCALE_BACK; ftranCountAfterU_ *= AVERAGE_SCALE_BACK; ftranFTCountInput_ *= AVERAGE_SCALE_BACK; ftranFTCountAfterL_ *= AVERAGE_SCALE_BACK; ftranFTCountAfterR_ *= AVERAGE_SCALE_BACK; ftranFTCountAfterU_ *= AVERAGE_SCALE_BACK; btranCountInput_ *= AVERAGE_SCALE_BACK; btranCountAfterU_ *= AVERAGE_SCALE_BACK; btranCountAfterR_ *= AVERAGE_SCALE_BACK; btranCountAfterL_ *= AVERAGE_SCALE_BACK; ftranFullCountInput_ *= AVERAGE_SCALE_BACK; ftranFullCountAfterL_ *= AVERAGE_SCALE_BACK; ftranFullCountAfterR_ *= AVERAGE_SCALE_BACK; ftranFullCountAfterU_ *= AVERAGE_SCALE_BACK; btranFullCountInput_ *= AVERAGE_SCALE_BACK; btranFullCountAfterL_ *= AVERAGE_SCALE_BACK; btranFullCountAfterR_ *= AVERAGE_SCALE_BACK; btranFullCountAfterU_ *= AVERAGE_SCALE_BACK; #endif } // Condition number - product of pivots after factorization CoinSimplexDouble CoinAbcTypeFactorization::conditionNumber() const { CoinSimplexDouble condition = 1.0; const CoinFactorizationDouble *pivotRegion = pivotRegionAddress_; for (CoinSimplexInt i = 0; i < numberRows_; i++) { condition *= pivotRegion[i]; } condition = CoinMax(fabs(condition), 1.0e-50); return 1.0 / condition; } #ifndef NDEBUG void CoinAbcTypeFactorization::checkMarkArrays() const { CoinCheckZero *COIN_RESTRICT mark = markRowAddress_; for (CoinSimplexInt i = 0; i < numberRows_; i++) { assert(!mark[i]); } #if ABC_PARALLEL mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + sizeSparseArray_); for (CoinSimplexInt i = 0; i < numberRows_; i++) { assert(!mark[i]); } for (int i = 1; i < FACTOR_CPU; i++) { for (CoinSimplexInt i = 0; i < numberRows_; i++) { assert(!mark[i]); } mark = reinterpret_cast< CoinCheckZero * >(reinterpret_cast< char * >(mark) + sizeSparseArray_); } #endif } #endif #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */