/* $Id$ */ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include "ClpNetworkBasis.hpp" #include "CoinHelperFunctions.hpp" #include "ClpSimplex.hpp" #include "ClpMatrixBase.hpp" #include "CoinIndexedVector.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpNetworkBasis::ClpNetworkBasis() { #ifndef COIN_FAST_CODE slackValue_ = -1.0; #endif numberRows_ = 0; numberColumns_ = 0; parent_ = NULL; descendant_ = NULL; pivot_ = NULL; rightSibling_ = NULL; leftSibling_ = NULL; sign_ = NULL; stack_ = NULL; permute_ = NULL; permuteBack_ = NULL; stack2_ = NULL; depth_ = NULL; mark_ = NULL; model_ = NULL; } // Constructor from CoinFactorization ClpNetworkBasis::ClpNetworkBasis(const ClpSimplex *model, int numberRows, const CoinFactorizationDouble *pivotRegion, const int *permuteBack, const int *startColumn, const int *numberInColumn, const int *indexRow, const CoinFactorizationDouble * /*element*/) { #ifndef COIN_FAST_CODE slackValue_ = -1.0; #endif numberRows_ = numberRows; numberColumns_ = numberRows; parent_ = new int[numberRows_ + 1]; descendant_ = new int[numberRows_ + 1]; pivot_ = new int[numberRows_ + 1]; rightSibling_ = new int[numberRows_ + 1]; leftSibling_ = new int[numberRows_ + 1]; sign_ = new double[numberRows_ + 1]; stack_ = new int[numberRows_ + 1]; stack2_ = new int[numberRows_ + 1]; depth_ = new int[numberRows_ + 1]; mark_ = new char[numberRows_ + 1]; permute_ = new int[numberRows_ + 1]; permuteBack_ = new int[numberRows_ + 1]; int i; for (i = 0; i < numberRows_ + 1; i++) { parent_[i] = -1; descendant_[i] = -1; pivot_[i] = -1; rightSibling_[i] = -1; leftSibling_[i] = -1; sign_[i] = -1.0; stack_[i] = -1; permute_[i] = i; permuteBack_[i] = i; stack2_[i] = -1; depth_[i] = -1; mark_[i] = 0; } mark_[numberRows_] = 1; // pivotColumnBack gives order of pivoting into basis // so pivotColumnback[0] is first slack in basis and // it pivots on row permuteBack[0] // a known root is given by permuteBack[numberRows_-1] for (i = 0; i < numberRows_; i++) { int iPivot = permuteBack[i]; double sign; if (pivotRegion[i] > 0.0) sign = 1.0; else sign = -1.0; int other; if (numberInColumn[i] > 0) { int iRow = indexRow[startColumn[i]]; other = permuteBack[iRow]; //assert (parent_[other]!=-1); } else { other = numberRows_; } sign_[iPivot] = sign; int iParent = other; parent_[iPivot] = other; if (descendant_[iParent] >= 0) { // we have a sibling int iRight = descendant_[iParent]; rightSibling_[iPivot] = iRight; leftSibling_[iRight] = iPivot; } else { rightSibling_[iPivot] = -1; } descendant_[iParent] = iPivot; leftSibling_[iPivot] = -1; } // do depth int nStack = 1; stack_[0] = descendant_[numberRows_]; depth_[numberRows_] = -1; // root while (nStack) { // take off int iNext = stack_[--nStack]; if (iNext >= 0) { depth_[iNext] = nStack; int iRight = rightSibling_[iNext]; stack_[nStack++] = iRight; if (descendant_[iNext] >= 0) stack_[nStack++] = descendant_[iNext]; } } model_ = model; check(); } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpNetworkBasis::ClpNetworkBasis(const ClpNetworkBasis &rhs) { #ifndef COIN_FAST_CODE slackValue_ = rhs.slackValue_; #endif numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; if (rhs.parent_) { parent_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.parent_, (numberRows_ + 1), parent_); } else { parent_ = NULL; } if (rhs.descendant_) { descendant_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.descendant_, (numberRows_ + 1), descendant_); } else { descendant_ = NULL; } if (rhs.pivot_) { pivot_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.pivot_, (numberRows_ + 1), pivot_); } else { pivot_ = NULL; } if (rhs.rightSibling_) { rightSibling_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.rightSibling_, (numberRows_ + 1), rightSibling_); } else { rightSibling_ = NULL; } if (rhs.leftSibling_) { leftSibling_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.leftSibling_, (numberRows_ + 1), leftSibling_); } else { leftSibling_ = NULL; } if (rhs.sign_) { sign_ = new double[numberRows_ + 1]; CoinMemcpyN(rhs.sign_, (numberRows_ + 1), sign_); } else { sign_ = NULL; } if (rhs.stack_) { stack_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.stack_, (numberRows_ + 1), stack_); } else { stack_ = NULL; } if (rhs.permute_) { permute_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.permute_, (numberRows_ + 1), permute_); } else { permute_ = NULL; } if (rhs.permuteBack_) { permuteBack_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.permuteBack_, (numberRows_ + 1), permuteBack_); } else { permuteBack_ = NULL; } if (rhs.stack2_) { stack2_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.stack2_, (numberRows_ + 1), stack2_); } else { stack2_ = NULL; } if (rhs.depth_) { depth_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.depth_, (numberRows_ + 1), depth_); } else { depth_ = NULL; } if (rhs.mark_) { mark_ = new char[numberRows_ + 1]; CoinMemcpyN(rhs.mark_, (numberRows_ + 1), mark_); } else { mark_ = NULL; } model_ = rhs.model_; } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpNetworkBasis::~ClpNetworkBasis() { delete[] parent_; delete[] descendant_; delete[] pivot_; delete[] rightSibling_; delete[] leftSibling_; delete[] sign_; delete[] stack_; delete[] permute_; delete[] permuteBack_; delete[] stack2_; delete[] depth_; delete[] mark_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpNetworkBasis & ClpNetworkBasis::operator=(const ClpNetworkBasis &rhs) { if (this != &rhs) { delete[] parent_; delete[] descendant_; delete[] pivot_; delete[] rightSibling_; delete[] leftSibling_; delete[] sign_; delete[] stack_; delete[] permute_; delete[] permuteBack_; delete[] stack2_; delete[] depth_; delete[] mark_; #ifndef COIN_FAST_CODE slackValue_ = rhs.slackValue_; #endif numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; if (rhs.parent_) { parent_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.parent_, (numberRows_ + 1), parent_); } else { parent_ = NULL; } if (rhs.descendant_) { descendant_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.descendant_, (numberRows_ + 1), descendant_); } else { descendant_ = NULL; } if (rhs.pivot_) { pivot_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.pivot_, (numberRows_ + 1), pivot_); } else { pivot_ = NULL; } if (rhs.rightSibling_) { rightSibling_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.rightSibling_, (numberRows_ + 1), rightSibling_); } else { rightSibling_ = NULL; } if (rhs.leftSibling_) { leftSibling_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.leftSibling_, (numberRows_ + 1), leftSibling_); } else { leftSibling_ = NULL; } if (rhs.sign_) { sign_ = new double[numberRows_ + 1]; CoinMemcpyN(rhs.sign_, (numberRows_ + 1), sign_); } else { sign_ = NULL; } if (rhs.stack_) { stack_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.stack_, (numberRows_ + 1), stack_); } else { stack_ = NULL; } if (rhs.permute_) { permute_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.permute_, (numberRows_ + 1), permute_); } else { permute_ = NULL; } if (rhs.permuteBack_) { permuteBack_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.permuteBack_, (numberRows_ + 1), permuteBack_); } else { permuteBack_ = NULL; } if (rhs.stack2_) { stack2_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.stack2_, (numberRows_ + 1), stack2_); } else { stack2_ = NULL; } if (rhs.depth_) { depth_ = new int[numberRows_ + 1]; CoinMemcpyN(rhs.depth_, (numberRows_ + 1), depth_); } else { depth_ = NULL; } if (rhs.mark_) { mark_ = new char[numberRows_ + 1]; CoinMemcpyN(rhs.mark_, (numberRows_ + 1), mark_); } else { mark_ = NULL; } } return *this; } // checks looks okay void ClpNetworkBasis::check() { // check depth int nStack = 1; stack_[0] = descendant_[numberRows_]; depth_[numberRows_] = -1; // root while (nStack) { // take off int iNext = stack_[--nStack]; if (iNext >= 0) { //assert (depth_[iNext]==nStack); depth_[iNext] = nStack; int iRight = rightSibling_[iNext]; stack_[nStack++] = iRight; if (descendant_[iNext] >= 0) stack_[nStack++] = descendant_[iNext]; } } } // prints void ClpNetworkBasis::print() { int i; printf(" parent descendant left right sign depth\n"); for (i = 0; i < numberRows_ + 1; i++) printf("%4d %7d %8d %7d %7d %5g %7d\n", i, parent_[i], descendant_[i], leftSibling_[i], rightSibling_[i], sign_[i], depth_[i]); } /* Replaces one Column to basis, returns 0=OK */ int ClpNetworkBasis::replaceColumn(CoinIndexedVector *regionSparse, int pivotRow) { // When things have settled down then redo this to make more elegant // I am sure lots of loops can be combined // regionSparse is empty assert(!regionSparse->getNumElements()); model_->unpack(regionSparse, model_->sequenceIn()); // arc given by pivotRow is leaving basis //int kParent = parent_[pivotRow]; // arc coming in has these two nodes int *indices = regionSparse->getIndices(); int iRow0 = indices[0]; int iRow1; if (regionSparse->getNumElements() == 2) iRow1 = indices[1]; else iRow1 = numberRows_; double sign = -regionSparse->denseVector()[iRow0]; regionSparse->clear(); // and outgoing model_->unpack(regionSparse, model_->pivotVariable()[pivotRow]); int jRow0 = indices[0]; int jRow1; if (regionSparse->getNumElements() == 2) jRow1 = indices[1]; else jRow1 = numberRows_; regionSparse->clear(); // get correct pivotRow //#define FULL_DEBUG #ifdef FULL_DEBUG printf("irow %d %d, jrow %d %d\n", iRow0, iRow1, jRow0, jRow1); #endif if (parent_[jRow0] == jRow1) { int newPivot = jRow0; if (newPivot != pivotRow) { #ifdef FULL_DEBUG printf("pivot row of %d permuted to %d\n", pivotRow, newPivot); #endif pivotRow = newPivot; } } else { //assert (parent_[jRow1]==jRow0); int newPivot = jRow1; if (newPivot != pivotRow) { #ifdef FULL_DEBUG printf("pivot row of %d permuted to %d\n", pivotRow, newPivot); #endif pivotRow = newPivot; } } bool extraPrint = (model_->numberIterations() > -3) && (model_->logLevel() > 10); if (extraPrint) print(); #ifdef FULL_DEBUG printf("In %d (region= %g, stored %g) %d (%g) pivoting on %d (%g)\n", iRow1, sign, sign_[iRow1], iRow0, sign_[iRow0], pivotRow, sign_[pivotRow]); #endif // see which path outgoing pivot is on int kRow = -1; int jRow = iRow1; while (jRow != numberRows_) { if (jRow == pivotRow) { kRow = iRow1; break; } else { jRow = parent_[jRow]; } } if (kRow < 0) { jRow = iRow0; while (jRow != numberRows_) { if (jRow == pivotRow) { kRow = iRow0; break; } else { jRow = parent_[jRow]; } } } //assert (kRow>=0); if (iRow0 == kRow) { iRow0 = iRow1; iRow1 = kRow; sign = -sign; } // pivot row is on path from iRow1 back to root // get stack of nodes to change // Also get precursors for cleaning order int nStack = 1; stack_[0] = iRow0; while (kRow != pivotRow) { stack_[nStack++] = kRow; if (sign * sign_[kRow] < 0.0) { sign_[kRow] = -sign_[kRow]; } else { sign = -sign; } kRow = parent_[kRow]; //sign *= sign_[kRow]; } stack_[nStack++] = pivotRow; if (sign * sign_[pivotRow] < 0.0) { sign_[pivotRow] = -sign_[pivotRow]; } else { sign = -sign; } int iParent = parent_[pivotRow]; while (nStack > 1) { int iLeft; int iRight; kRow = stack_[--nStack]; int newParent = stack_[nStack - 1]; #ifdef FULL_DEBUG printf("row %d, old parent %d, new parent %d, pivotrow %d\n", kRow, iParent, newParent, pivotRow); #endif int i1 = permuteBack_[pivotRow]; int i2 = permuteBack_[kRow]; permuteBack_[pivotRow] = i2; permuteBack_[kRow] = i1; // do Btran permutation permute_[i1] = kRow; permute_[i2] = pivotRow; pivotRow = kRow; // Take out of old parent iLeft = leftSibling_[kRow]; iRight = rightSibling_[kRow]; if (iLeft < 0) { // take out of tree if (iRight >= 0) { leftSibling_[iRight] = iLeft; descendant_[iParent] = iRight; } else { #ifdef FULL_DEBUG printf("Saying %d (old parent of %d) has no descendants\n", iParent, kRow); #endif descendant_[iParent] = -1; } } else { // take out of tree rightSibling_[iLeft] = iRight; if (iRight >= 0) leftSibling_[iRight] = iLeft; } leftSibling_[kRow] = -1; rightSibling_[kRow] = -1; // now insert new one // make this descendant of that if (descendant_[newParent] >= 0) { // we will have a sibling int jRight = descendant_[newParent]; rightSibling_[kRow] = jRight; leftSibling_[jRight] = kRow; } else { rightSibling_[kRow] = -1; } descendant_[newParent] = kRow; leftSibling_[kRow] = -1; parent_[kRow] = newParent; iParent = kRow; } // now redo all depths from stack_[1] // This must be possible to combine - but later { int iPivot = stack_[1]; int iDepth = depth_[parent_[iPivot]]; //depth of parent iDepth++; //correct for this one int nStack = 1; stack_[0] = iPivot; while (nStack) { // take off int iNext = stack_[--nStack]; if (iNext >= 0) { // add stack level depth_[iNext] = nStack + iDepth; stack_[nStack++] = rightSibling_[iNext]; if (descendant_[iNext] >= 0) stack_[nStack++] = descendant_[iNext]; } } } if (extraPrint) print(); //check(); return 0; } /* Updates one column (FTRAN) from region2 */ double ClpNetworkBasis::updateColumn(CoinIndexedVector *regionSparse, CoinIndexedVector *regionSparse2, int pivotRow) { regionSparse->clear(); double *region = regionSparse->denseVector(); double *region2 = regionSparse2->denseVector(); int *regionIndex2 = regionSparse2->getIndices(); int numberNonZero = regionSparse2->getNumElements(); int *regionIndex = regionSparse->getIndices(); int i; bool doTwo = (numberNonZero == 2); int i0 = -1; int i1 = -1; if (doTwo) { i0 = regionIndex2[0]; i1 = regionIndex2[1]; } double returnValue = 0.0; bool packed = regionSparse2->packedMode(); if (packed) { if (doTwo && region2[0] * region2[1] < 0.0) { region[i0] = region2[0]; region2[0] = 0.0; region[i1] = region2[1]; region2[1] = 0.0; int iDepth0 = depth_[i0]; int iDepth1 = depth_[i1]; if (iDepth1 > iDepth0) { int temp = i0; i0 = i1; i1 = temp; temp = iDepth0; iDepth0 = iDepth1; iDepth1 = temp; } numberNonZero = 0; if (pivotRow < 0) { while (iDepth0 > iDepth1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; region2[numberNonZero] = pivotValue * sign_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; iDepth0--; i0 = otherRow; } while (i0 != i1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; region2[numberNonZero] = pivotValue * sign_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; i0 = otherRow; double pivotValue1 = region[i1]; // put back now ? int iBack1 = permuteBack_[i1]; region2[numberNonZero] = pivotValue1 * sign_[i1]; regionIndex2[numberNonZero++] = iBack1; int otherRow1 = parent_[i1]; region[i1] = 0.0; region[otherRow1] += pivotValue1; i1 = otherRow1; } } else { while (iDepth0 > iDepth1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; double value = pivotValue * sign_[i0]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack; if (iBack == pivotRow) returnValue = value; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; iDepth0--; i0 = otherRow; } while (i0 != i1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; double value = pivotValue * sign_[i0]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack; if (iBack == pivotRow) returnValue = value; int otherRow = parent_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; i0 = otherRow; double pivotValue1 = region[i1]; // put back now ? int iBack1 = permuteBack_[i1]; value = pivotValue1 * sign_[i1]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack1; if (iBack1 == pivotRow) returnValue = value; int otherRow1 = parent_[i1]; region[i1] = 0.0; region[otherRow1] += pivotValue1; i1 = otherRow1; } } } else { // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero; i++) { int j = regionIndex2[i]; double value = region2[i]; region2[i] = 0.0; region[j] = value; regionIndex[i] = j; int iDepth = depth_[j]; if (iDepth > greatestDepth) greatestDepth = iDepth; // and back until marked while (!mark_[j]) { int iNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = iNext; mark_[j] = 1; iDepth--; j = parent_[j]; } } numberNonZero = 0; if (pivotRow < 0) { for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; region2[numberNonZero] = pivotValue * sign_[iPivot]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } } else { for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; double value = pivotValue * sign_[iPivot]; region2[numberNonZero] = value; regionIndex2[numberNonZero++] = iBack; if (iBack == pivotRow) returnValue = value; int otherRow = parent_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } } } } else { if (doTwo && region2[i0] * region2[i1] < 0.0) { // If just +- 1 then could go backwards on depth until join region[i0] = region2[i0]; region2[i0] = 0.0; region[i1] = region2[i1]; region2[i1] = 0.0; int iDepth0 = depth_[i0]; int iDepth1 = depth_[i1]; if (iDepth1 > iDepth0) { int temp = i0; i0 = i1; i1 = temp; temp = iDepth0; iDepth0 = iDepth1; iDepth1 = temp; } numberNonZero = 0; while (iDepth0 > iDepth1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region2[iBack] = pivotValue * sign_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; iDepth0--; i0 = otherRow; } while (i0 != i1) { double pivotValue = region[i0]; // put back now ? int iBack = permuteBack_[i0]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[i0]; region2[iBack] = pivotValue * sign_[i0]; region[i0] = 0.0; region[otherRow] += pivotValue; i0 = otherRow; double pivotValue1 = region[i1]; // put back now ? int iBack1 = permuteBack_[i1]; regionIndex2[numberNonZero++] = iBack1; int otherRow1 = parent_[i1]; region2[iBack1] = pivotValue1 * sign_[i1]; region[i1] = 0.0; region[otherRow1] += pivotValue1; i1 = otherRow1; } } else { // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero; i++) { int j = regionIndex2[i]; double value = region2[j]; region2[j] = 0.0; region[j] = value; regionIndex[i] = j; int iDepth = depth_[j]; if (iDepth > greatestDepth) greatestDepth = iDepth; // and back until marked while (!mark_[j]) { int iNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = iNext; mark_[j] = 1; iDepth--; j = parent_[j]; } } numberNonZero = 0; for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; regionIndex2[numberNonZero++] = iBack; int otherRow = parent_[iPivot]; region2[iBack] = pivotValue * sign_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } } if (pivotRow >= 0) returnValue = region2[pivotRow]; } region[numberRows_] = 0.0; regionSparse2->setNumElements(numberNonZero); #ifdef FULL_DEBUG { int i; for (i = 0; i < numberRows_; i++) { assert(!mark_[i]); assert(stack2_[i] == -1); } } #endif return returnValue; } /* Updates one column (FTRAN) to/from array ** For large problems you should ALWAYS know where the nonzeros are, so please try and migrate to previous method after you have got code working using this simple method - thank you! (the only exception is if you know input is dense e.g. rhs) */ int ClpNetworkBasis::updateColumn(CoinIndexedVector *regionSparse, double region2[]) const { regionSparse->clear(); double *region = regionSparse->denseVector(); int numberNonZero = 0; int *regionIndex = regionSparse->getIndices(); int i; // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; for (i = 0; i < numberRows_; i++) { double value = region2[i]; if (value) { region2[i] = 0.0; region[i] = value; regionIndex[numberNonZero++] = i; int j = i; int iDepth = depth_[j]; if (iDepth > greatestDepth) greatestDepth = iDepth; // and back until marked while (!mark_[j]) { int iNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = iNext; mark_[j] = 1; iDepth--; j = parent_[j]; } } } numberNonZero = 0; for (; greatestDepth >= 0; greatestDepth--) { int iPivot = stack2_[greatestDepth]; stack2_[greatestDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; if (pivotValue) { // put back now ? int iBack = permuteBack_[iPivot]; numberNonZero++; int otherRow = parent_[iPivot]; region2[iBack] = pivotValue * sign_[iPivot]; region[iPivot] = 0.0; region[otherRow] += pivotValue; } iPivot = stack_[iPivot]; } } region[numberRows_] = 0.0; return numberNonZero; } /* Updates one column transpose (BTRAN) For large problems you should ALWAYS know where the nonzeros are, so please try and migrate to previous method after you have got code working using this simple method - thank you! (the only exception is if you know input is dense e.g. dense objective) returns number of nonzeros */ int ClpNetworkBasis::updateColumnTranspose(CoinIndexedVector *regionSparse, double region2[]) const { // permute in after copying // so will end up in right place double *region = regionSparse->denseVector(); int *regionIndex = regionSparse->getIndices(); int i; int numberNonZero = 0; CoinMemcpyN(region2, numberRows_, region); for (i = 0; i < numberRows_; i++) { double value = region[i]; if (value) { int k = permute_[i]; region[i] = 0.0; region2[k] = value; regionIndex[numberNonZero++] = k; mark_[k] = 1; } } // copy back // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; int smallestDepth = numberRows_; for (i = 0; i < numberNonZero; i++) { int j = regionIndex[i]; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth); greatestDepth = CoinMax(iDepth, greatestDepth); int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } numberNonZero = 0; region2[numberRows_] = 0.0; int iDepth; for (iDepth = smallestDepth; iDepth <= greatestDepth; iDepth++) { int iPivot = stack2_[iDepth]; stack2_[iDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region2[iPivot]; int otherRow = parent_[iPivot]; double otherValue = region2[otherRow]; pivotValue = sign_[iPivot] * pivotValue + otherValue; region2[iPivot] = pivotValue; if (pivotValue) numberNonZero++; iPivot = stack_[iPivot]; } } return numberNonZero; } /* Updates one column (BTRAN) from region2 */ int ClpNetworkBasis::updateColumnTranspose(CoinIndexedVector *regionSparse, CoinIndexedVector *regionSparse2) const { // permute in - presume small number so copy back // so will end up in right place regionSparse->clear(); double *region = regionSparse->denseVector(); double *region2 = regionSparse2->denseVector(); int *regionIndex2 = regionSparse2->getIndices(); int numberNonZero2 = regionSparse2->getNumElements(); int *regionIndex = regionSparse->getIndices(); int i; int numberNonZero = 0; bool packed = regionSparse2->packedMode(); if (packed) { for (i = 0; i < numberNonZero2; i++) { int k = regionIndex2[i]; int j = permute_[k]; double value = region2[i]; region2[i] = 0.0; region[j] = value; mark_[j] = 1; regionIndex[numberNonZero++] = j; } // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; int smallestDepth = numberRows_; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero2; i++) { int j = regionIndex[i]; regionIndex2[i] = j; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth); greatestDepth = CoinMax(iDepth, greatestDepth); int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } for (; i < numberNonZero; i++) { int j = regionIndex2[i]; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth); greatestDepth = CoinMax(iDepth, greatestDepth); int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } numberNonZero2 = 0; region[numberRows_] = 0.0; int iDepth; for (iDepth = smallestDepth; iDepth <= greatestDepth; iDepth++) { int iPivot = stack2_[iDepth]; stack2_[iDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region[iPivot]; int otherRow = parent_[iPivot]; double otherValue = region[otherRow]; pivotValue = sign_[iPivot] * pivotValue + otherValue; region[iPivot] = pivotValue; if (pivotValue) { region2[numberNonZero2] = pivotValue; regionIndex2[numberNonZero2++] = iPivot; } iPivot = stack_[iPivot]; } } // zero out for (i = 0; i < numberNonZero2; i++) { int k = regionIndex2[i]; region[k] = 0.0; } } else { for (i = 0; i < numberNonZero2; i++) { int k = regionIndex2[i]; int j = permute_[k]; double value = region2[k]; region2[k] = 0.0; region[j] = value; mark_[j] = 1; regionIndex[numberNonZero++] = j; } // copy back // set up linked lists at each depth // stack2 is start, stack is next int greatestDepth = -1; int smallestDepth = numberRows_; //mark_[numberRows_]=1; for (i = 0; i < numberNonZero2; i++) { int j = regionIndex[i]; double value = region[j]; region[j] = 0.0; region2[j] = value; regionIndex2[i] = j; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth); greatestDepth = CoinMax(iDepth, greatestDepth); int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } for (; i < numberNonZero; i++) { int j = regionIndex2[i]; // add in int iDepth = depth_[j]; smallestDepth = CoinMin(iDepth, smallestDepth); greatestDepth = CoinMax(iDepth, greatestDepth); int jNext = stack2_[iDepth]; stack2_[iDepth] = j; stack_[j] = jNext; // and put all descendants on list int iChild = descendant_[j]; while (iChild >= 0) { if (!mark_[iChild]) { regionIndex2[numberNonZero++] = iChild; mark_[iChild] = 1; } iChild = rightSibling_[iChild]; } } numberNonZero2 = 0; region2[numberRows_] = 0.0; int iDepth; for (iDepth = smallestDepth; iDepth <= greatestDepth; iDepth++) { int iPivot = stack2_[iDepth]; stack2_[iDepth] = -1; while (iPivot >= 0) { mark_[iPivot] = 0; double pivotValue = region2[iPivot]; int otherRow = parent_[iPivot]; double otherValue = region2[otherRow]; pivotValue = sign_[iPivot] * pivotValue + otherValue; region2[iPivot] = pivotValue; if (pivotValue) regionIndex2[numberNonZero2++] = iPivot; iPivot = stack_[iPivot]; } } } regionSparse2->setNumElements(numberNonZero2); #ifdef FULL_DEBUG { int i; for (i = 0; i < numberRows_; i++) { assert(!mark_[i]); assert(stack2_[i] == -1); } } #endif return numberNonZero2; } /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */