/* Returns reduced gradient.Returns an offset (to be added to current one). */ double ClpLinearObjective::reducedGradient(ClpSimplex * model, double * region, bool /*useFeasibleCosts*/) { int numberRows = model->numberRows(); //work space CoinIndexedVector * workSpace = model->rowArray(0); CoinIndexedVector arrayVector; arrayVector.reserve(numberRows + 1); int iRow; #ifdef CLP_DEBUG workSpace->checkClear(); #endif double * array = arrayVector.denseVector(); int * index = arrayVector.getIndices(); int number = 0; const double * cost = model->costRegion(); //assert (!useFeasibleCosts); const int * pivotVariable = model->pivotVariable(); for (iRow = 0; iRow < numberRows; iRow++) { int iPivot = pivotVariable[iRow]; double value = cost[iPivot]; if (value) { array[iRow] = value; index[number++] = iRow; } } arrayVector.setNumElements(number); int numberColumns = model->numberColumns(); // Btran basic costs double * work = workSpace->denseVector(); model->factorization()->updateColumnTranspose(workSpace, &arrayVector); ClpFillN(work, numberRows, 0.0); // now look at dual solution double * rowReducedCost = region + numberColumns; double * dual = rowReducedCost; double * rowCost = model->costRegion(0); for (iRow = 0; iRow < numberRows; iRow++) { dual[iRow] = array[iRow]; } double * dj = region; ClpDisjointCopyN(model->costRegion(1), numberColumns, dj); model->transposeTimes(-1.0, dual, dj); for (iRow = 0; iRow < numberRows; iRow++) { // slack double value = dual[iRow]; value += rowCost[iRow]; rowReducedCost[iRow] = value; } return 0.0; }
/* Return <code>x *A</code> in <code>z</code> but just for number indices in y. Default cheats with fake CoinIndexedVector and then calls subsetTransposeTimes */ void ClpMatrixBase::listTransposeTimes(const ClpSimplex * model, double * x, int * y, int number, double * z) const { CoinIndexedVector pi; CoinIndexedVector list; CoinIndexedVector output; int * saveIndices = list.getIndices(); list.setNumElements(number); list.setIndexVector(y); double * savePi = pi.denseVector(); pi.setDenseVector(x); double * saveOutput = output.denseVector(); output.setDenseVector(z); output.setPacked(); subsetTransposeTimes(model, &pi, &list, &output); // restore settings list.setIndexVector(saveIndices); pi.setDenseVector(savePi); output.setDenseVector(saveOutput); }
//-------------------------------------------------------------------------- void CoinIndexedVectorUnitTest() { int i; // Test default constructor { CoinIndexedVector r; assert( r.indices_==NULL ); assert( r.elements_==NULL ); assert( r.getNumElements()==0 ); assert( r.capacity_==0); } // Test set and get methods const int ne = 4; int inx[ne] = { 1, 3, 4, 7 }; double el[ne] = { 1.2, 3.4, 5.6, 7.8 }; { CoinIndexedVector r; assert( r.getNumElements()==0 ); // Test setting/getting elements with int* & float* vectors r.setVector( ne, inx, el ); assert( r.getNumElements()==ne ); for ( i=0; i<ne; i++ ) { assert( r.getIndices()[i] == inx[i] ); assert( r[inx[i]] == el[i] ); } // Test setting/getting elements with indices out of order const int ne2 = 5; int inx2[ne2] = { 2, 4, 8, 14, 3 }; double el2[ne2] = { 2.2, 4.4, 6.6, 8.8, 3.3 }; r.setVector(ne2,inx2,el2); assert( r.getNumElements()==ne2 ); assert( r.getIndices()[0]==inx2[0] ); assert( r.getIndices()[1]==inx2[1] ); assert( r.getIndices()[2]==inx2[2] ); assert( r.getIndices()[3]==inx2[3] ); assert( r.getIndices()[4]==inx2[4] ); CoinIndexedVector r1(ne2,inx2,el2); assert( r == r1 ); } CoinIndexedVector r; { CoinIndexedVector r; const int ne = 3; int inx[ne] = { 1, 2, 3 }; double el[ne] = { 2.2, 4.4, 8.8}; r.setVector(ne,inx,el); int c = r.capacity(); // Test swap function r.swap(0,2); assert( r.getIndices()[0]==3 ); assert( r.getIndices()[1]==2 ); assert( r.getIndices()[2]==1 ); assert( r.capacity() == c ); // Test the append function CoinIndexedVector s; const int nes = 4; int inxs[nes] = { 11, 12, 13, 14 }; double els[nes] = { .122, 14.4, 18.8, 19.9}; s.setVector(nes,inxs,els); r.append(s); assert( r.getNumElements()==7 ); assert( r.getIndices()[0]==3 ); assert( r.getIndices()[1]==2 ); assert( r.getIndices()[2]==1 ); assert( r.getIndices()[3]==11 ); assert( r.getIndices()[4]==12 ); assert( r.getIndices()[5]==13 ); assert( r.getIndices()[6]==14 ); // Test the resize function c = r.capacity(); r.truncate(4); // we will lose 11 assert( r.getNumElements()==3 ); assert( r.getIndices()[0]==3 ); assert( r.getIndices()[1]==2 ); assert( r.getIndices()[2]==1 ); assert( r.getMaxIndex() == 3 ); assert( r.getMinIndex() == 1 ); assert( r.capacity() == c ); } // Test borrow and return vector { CoinIndexedVector r,r2; const int ne = 3; int inx[ne] = { 1, 2, 3 }; double el[ne] = { 2.2, 4.4, 8.8}; double els[4] = { 0.0,2.2, 4.4, 8.8}; r.setVector(ne,inx,el); r2.borrowVector(4,ne,inx,els); assert (r==r2); r2.returnVector(); assert (!r2.capacity()); assert (!r2.getNumElements()); assert (!r2.denseVector()); assert (!r2.getIndices()); } // Test copy constructor and assignment operator { CoinIndexedVector rhs; { CoinIndexedVector r; { CoinIndexedVector rC1(r); assert( 0==r.getNumElements() ); assert( 0==rC1.getNumElements() ); r.setVector( ne, inx, el ); assert( ne==r.getNumElements() ); assert( 0==rC1.getNumElements() ); } CoinIndexedVector rC2(r); assert( ne==r.getNumElements() ); assert( ne==rC2.getNumElements() ); for ( i=0; i<ne; i++ ) { assert( r.getIndices()[i] == rC2.getIndices()[i] ); } rhs=rC2; } // Test that rhs has correct values even though lhs has gone out of scope assert( rhs.getNumElements()==ne ); for ( i=0; i<ne; i++ ) { assert( inx[i] == rhs.getIndices()[i] ); } } // Test operator== { CoinIndexedVector v1,v2; assert( v1==v2 ); assert( v2==v1 ); assert( v1==v1 ); assert( !(v1!=v2) ); v1.setVector( ne, inx, el ); assert ( !(v1==v2) ); assert ( v1!=v2 ); CoinIndexedVector v3(v1); assert( v3==v1 ); assert( v3!=v2 ); CoinIndexedVector v4(v2); assert( v4!=v1 ); assert( v4==v2 ); } { // Test sorting of indexed vectors const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 20. }; CoinIndexedVector r; r.setVector(ne,inx,el); // Test that indices are in increasing order r.sort(); for ( i=1; i<ne; i++ ) assert( r.getIndices()[i-1] < r.getIndices()[i] ); } { // Test operator[] and indexExists() const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinIndexedVector r; bool errorThrown = false; try { assert( r[1]==0. ); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); r.setVector(ne,inx,el); errorThrown = false; try { assert( r[-1]==0. ); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); assert( r[ 0]==1. ); assert( r[ 1]==10.); assert( r[ 2]==50.); assert( r[ 3]==0. ); assert( r[ 4]==40.); errorThrown = false; try { assert( r[5]==0. ); } catch (CoinError& e) { errorThrown = true; } assert( errorThrown ); assert ( r.getMaxIndex()==4 ); assert ( r.getMinIndex()==0 ); } // Test that attemping to get min/max index of a 0, // length vector { CoinIndexedVector nullVec; assert( nullVec.getMaxIndex() == -COIN_INT_MAX/*0*/ ); assert( nullVec.getMinIndex() == COIN_INT_MAX/*0*/ ); } // Test CoinFltEq with equivalent method { const int ne = 4; int inx1[ne] = { 1, 3, 4, 7 }; double el1[ne] = { 1.2, 3.4, 5.6, 7.8 }; int inx2[ne] = { 7, 4, 3, 1 }; double el2[ne] = { 7.8+.5, 5.6+.5, 3.4+.5, 1.2+.5 }; CoinIndexedVector v1,v2; v1.setVector(ne,inx1,el1); v2.setVector(ne,inx2,el2); } { // Test reserve CoinIndexedVector v1,v2; assert( v1.capacity()==0 ); v1.reserve(6); assert( v1.capacity()==6 ); assert( v1.getNumElements()==0 ); v2=v1; assert( v2.capacity() == 6 ); assert( v2.getNumElements()==0 ); assert( v2==v1 ); v1.setVector(0,NULL,NULL); assert( v1.capacity()==6 ); assert( v1.getNumElements()==0 ); assert( v2==v1 ); v2=v1; assert( v2.capacity() == 6 ); assert( v2.getNumElements()==0 ); assert( v2==v1 ); const int ne = 2; int inx[ne] = { 1, 3 }; double el[ne] = { 1.2, 3.4 }; v1.setVector(ne,inx,el); assert( v1.capacity()==6 ); assert( v1.getNumElements()==2 ); v2=v1; assert( v2.capacity()==6 ); assert( v2.getNumElements()==2 ); assert( v2==v1 ); const int ne1 = 5; int inx1[ne1] = { 1, 3, 4, 5, 6 }; double el1[ne1] = { 1.2, 3.4, 5., 6., 7. }; v1.setVector(ne1,inx1,el1); assert( v1.capacity()==7 ); assert( v1.getNumElements()==5 ); v2=v1; assert( v2.capacity()==7 ); assert( v2.getNumElements()==5 ); assert( v2==v1 ); const int ne2 = 8; int inx2[ne2] = { 1, 3, 4, 5, 6, 7, 8, 9 }; double el2[ne2] = { 1.2, 3.4, 5., 6., 7., 8., 9., 10. }; v1.setVector(ne2,inx2,el2); assert( v1.capacity()==10 ); assert( v1.getNumElements()==8 ); v2=v1; assert( v2.getNumElements()==8 ); assert( v2==v1 ); v1.setVector(ne1,inx1,el1); assert( v1.capacity()==10 ); assert( v1.getNumElements()==5 ); v2=v1; assert( v2.capacity()==10 ); assert( v2.getNumElements()==5 ); assert( v2==v1 ); v1.reserve(7); assert( v1.capacity()==10 ); assert( v1.getNumElements()==5 ); v2=v1; assert( v2.capacity()==10 ); assert( v2.getNumElements()==5 ); assert( v2==v1 ); } // Test the insert method { CoinIndexedVector v1; assert( v1.getNumElements()==0 ); assert( v1.capacity()==0 ); v1.insert(1,1.); assert( v1.getNumElements()==1 ); assert( v1.capacity()==2 ); assert( v1.getIndices()[0] == 1 ); v1.insert(10,10.); assert( v1.getNumElements()==2 ); assert( v1.capacity()==11 ); assert( v1.getIndices()[1] == 10 ); v1.insert(20,20.); assert( v1.getNumElements()==3 ); assert( v1.capacity()==21 ); assert( v1.getIndices()[2] == 20 ); v1.insert(30,30.); assert( v1.getNumElements()==4 ); assert( v1.capacity()==31 ); assert( v1.getIndices()[3] == 30 ); v1.insert(40,40.); assert( v1.getNumElements()==5 ); assert( v1.capacity()==41 ); assert( v1.getIndices()[4] == 40 ); v1.insert(50,50.); assert( v1.getNumElements()==6 ); assert( v1.capacity()==51 ); assert( v1.getIndices()[5] == 50 ); CoinIndexedVector v2; const int ne1 = 3; int inx1[ne1] = { 1, 3, 4 }; double el1[ne1] = { 1.2, 3.4, 5. }; v2.setVector(ne1,inx1,el1); assert( v2.getNumElements()==3 ); assert( v2.capacity()==5 ); // Test clean method - get rid of 1.2 assert(v2.clean(3.0)==2); assert(v2.denseVector()[1]==0.0); // Below are purely for debug - so use assert // so we won't try with false // Test checkClean #ifndef NO_CHECK_CL v2.checkClean(); assert( v2.getNumElements()==2 ); // Get rid of all int numberRemaining = v2.clean(10.0); assert(numberRemaining==0); v2.checkClear(); #endif } { //Test setConstant and setElement CoinIndexedVector v2; const int ne1 = 3; int inx1[ne1] = { 1, 3, 4 }; v2.setConstant(ne1,inx1,3.14); assert( v2.getNumElements()==3 ); assert( v2.capacity()==5 ); assert( v2.getIndices()[0]==1 ); assert( v2.getIndices()[1]==3 ); assert( v2.getIndices()[2]==4 ); assert( v2[3] == 3.14 ); CoinIndexedVector v2X(ne1,inx1,3.14); assert( v2 == v2X ); } { //Test setFull CoinIndexedVector v2; const int ne2 = 3; double el2[ne2] = { 1., 3., 4. }; v2.setFull(ne2,el2); assert( v2.getNumElements()==3 ); assert( v2.capacity()==3 ); assert( v2.getIndices()[0]==0 ); assert( v2.getIndices()[1]==1 ); assert( v2.getIndices()[2]==2 ); assert( v2[1] == 3. ); CoinIndexedVector v2X(ne2,el2); assert( v2 == v2X ); v2.setFull(0,el2); assert( v2[2] == 0. ); } #if 0 // what happens when someone sets // the number of elements to be a negative number { const int ne = 4; int inx1[ne] = { 1, 3, 4, 7 }; double el1[ne] = { 1.2, 3.4, 5.6, 7.8 }; CoinIndexedVector v1; v1.set(-ne,inx1,el1); } #endif // Test copy constructor from ShallowPackedVector { const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinIndexedVector std(ne,inx,el); CoinShallowPackedVector * spvP = new CoinShallowPackedVector(ne,inx,el); CoinIndexedVector pv(*spvP); assert( pv == std ); delete spvP; assert( pv == std ); } // Test assignment from ShallowPackedVector { const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinIndexedVector std(ne,inx,el); CoinShallowPackedVector * spvP = new CoinShallowPackedVector(ne,inx,el); CoinIndexedVector pv; pv = *spvP; assert( pv == std ); delete spvP; assert( pv == std ); } { // Test that sample usage works const int ne = 4; int inx[ne] = { 1, 4, 0, 2 }; double el[ne] = { 10., 40., 1., 50. }; CoinIndexedVector r(ne,inx,el); assert( r.getIndices()[0]== 1 ); assert( r.getIndices()[1]== 4 ); assert( r.getIndices()[2]== 0 ); assert( r.getIndices()[3]== 2 ); assert( r[ 0]==1. ); assert( r[ 1]==10.); assert( r[ 2]==50.); assert( r[ 3]==0. ); assert( r[ 4]==40.); r.sortIncrElement(); assert( r.getIndices()[0]== 0 ); assert( r.getIndices()[1]== 1 ); assert( r.getIndices()[2]== 4 ); assert( r.getIndices()[3]== 2 ); assert( r[ 0]==1. ); assert( r[ 1]==10.); assert( r[ 2]==50.); assert( r[ 3]==0. ); assert( r[ 4]==40.); CoinIndexedVector r1; r1=r; assert( r==r1 ); CoinIndexedVector add = r + r1; assert( add[0] == 1.+ 1. ); assert( add[1] == 10.+10. ); assert( add[2] == 50.+50. ); assert( add[3] == 0.+ 0. ); assert( add[4] == 40.+40. ); } }
void CglGMI::generateCuts(OsiCuts &cs) { isInteger = new bool[ncol]; computeIsInteger(); cstat = new int[ncol]; rstat = new int[nrow]; solver->getBasisStatus(cstat, rstat); // 0: free 1: basic // 2: upper 3: lower #if defined GMI_TRACETAB printvecINT("cstat", cstat, ncol); printvecINT("rstat", rstat, nrow); #endif // list of basic integer fractional variables int *listFracBasic = new int[nrow]; int numFracBasic = 0; for (int i = 0; i < ncol; ++i) { // j is the variable which is basic in row i if ((cstat[i] == 1) && (isInteger[i])) { if (CoinMin(aboveInteger(xlp[i]), 1-aboveInteger(xlp[i])) > param.getAway()) { listFracBasic[numFracBasic] = i; numFracBasic++; } #if defined TRACK_REJECT || defined TRACK_REJECT_SIMPLE else if (trackRejection) { // Say that we tried to generate a cut, but it was discarded // because of small fractionality if (!isIntegerValue(xlp[i])) { fracFail++; numGeneratedCuts++; } } #endif } } #if defined GMI_TRACE printf("CglGMI::generateCuts() : %d fractional rows\n", numFracBasic); #endif if (numFracBasic == 0) { delete[] listFracBasic; delete[] cstat; delete[] rstat; delete[] isInteger; return; } // there are rows with basic integer fractional variables, so we can // generate cuts // Basis index for columns and rows; each element is -1 if corresponding // variable is nonbasic, and contains the basis index if basic. // The basis index is the row in which the variable is basic. int* colBasisIndex = new int[ncol]; int* rowBasisIndex = new int[nrow]; #if defined OSI_TABLEAU memset(colBasisIndex, -1, ncol*sizeof(int)); memset(rowBasisIndex, -1, nrow*sizeof(int)); solver->enableFactorization(); int* basicVars = new int[nrow]; solver->getBasics(basicVars); for (int i = 0; i < nrow; ++i) { if (basicVars[i] < ncol) { colBasisIndex[basicVars[i]] = i; } else { rowBasisIndex[basicVars[i] - ncol] = i; } } #else CoinFactorization factorization; if (factorize(factorization, colBasisIndex, rowBasisIndex)) { printf("### WARNING: CglGMI::generateCuts(): error during factorization!\n"); return; } #endif // cut in sparse form double* cutElem = new double[ncol]; int* cutIndex = new int[ncol]; int cutNz = 0; double cutRhs; // cut in dense form double* cut = new double[ncol]; double *slackVal = new double[nrow]; for (int i = 0; i < nrow; ++i) { slackVal[i] = rowRhs[i] - rowActivity[i]; } #if defined OSI_TABLEAU // Column part and row part of a row of the simplex tableau double* tableauColPart = new double[ncol]; double* tableauRowPart = new double[nrow]; #else // Need some more data for simplex tableau computation const int * row = byCol->getIndices(); const CoinBigIndex * columnStart = byCol->getVectorStarts(); const int * columnLength = byCol->getVectorLengths(); const double * columnElements = byCol->getElements(); // Create work arrays for factorization // two vectors for updating: the first one is needed to do the computations // but we do not use it, the second one contains a row of the basis inverse CoinIndexedVector work; CoinIndexedVector array; // Make sure they large enough work.reserve(nrow); array.reserve(nrow); int * arrayRows = array.getIndices(); double * arrayElements = array.denseVector(); // End of code to create work arrays double one = 1.0; #endif // Matrix elements by row for slack substitution const double *elements = byRow->getElements(); const int *rowStart = byRow->getVectorStarts(); const int *indices = byRow->getIndices(); const int *rowLength = byRow->getVectorLengths(); // Indices of basic and slack variables, and cut elements int iBasic, slackIndex; double cutCoeff; double rowElem; // Now generate the cuts: obtain a row of the simplex tableau // where an integer variable is basic and fractional, and compute the cut for (int i = 0; i < numFracBasic; ++i) { if (!computeCutFractionality(xlp[listFracBasic[i]], cutRhs)) { // cut is discarded because of the small fractionalities involved #if defined TRACK_REJECT || defined TRACK_REJECT_SIMPLE if (trackRejection) { // Say that we tried to generate a cut, but it was discarded // because of small fractionality fracFail++; numGeneratedCuts++; } #endif continue; } // the variable listFracBasic[i] is basic in row iBasic iBasic = colBasisIndex[listFracBasic[i]]; #if defined GMI_TRACE printf("Row %d with var %d basic, f0 = %f\n", i, listFracBasic[i], f0); #endif #if defined OSI_TABLEAU solver->getBInvARow(iBasic, tableauColPart, tableauRowPart); #else array.clear(); array.setVector(1, &iBasic, &one); factorization.updateColumnTranspose (&work, &array); int numberInArray=array.getNumElements(); #endif // reset the cut memset(cut, 0, ncol*sizeof(double)); // columns for (int j = 0; j < ncol; ++j) { if ((colBasisIndex[j] >= 0) || (areEqual(colLower[j], colUpper[j], param.getEPS(), param.getEPS()))) { // Basic or fixed variable -- skip continue; } #ifdef OSI_TABLEAU rowElem = tableauColPart[j]; #else rowElem = 0.0; // add in row of tableau for (int h = columnStart[j]; h < columnStart[j]+columnLength[j]; ++h) { rowElem += columnElements[h]*arrayElements[row[h]]; } #endif if (!isZero(fabs(rowElem))) { // compute cut coefficient flip(rowElem, j); cutCoeff = computeCutCoefficient(rowElem, j); if (isZero(cutCoeff)) { continue; } unflipOrig(cutCoeff, j, cutRhs); cut[j] = cutCoeff; #if defined GMI_TRACE printf("var %d, row %f, cut %f\n", j, rowElem, cutCoeff); #endif } } // now do slacks part #if defined OSI_TABLEAU for (int j = 0 ; j < nrow; ++j) { // index of the row corresponding to the slack variable slackIndex = j; if (rowBasisIndex[j] >= 0) { // Basic variable -- skip it continue; } rowElem = tableauRowPart[j]; #else for (int j = 0 ; j < numberInArray ; ++j) { // index of the row corresponding to the slack variable slackIndex = arrayRows[j]; rowElem = arrayElements[slackIndex]; #endif if (!isZero(fabs(rowElem))) { slackIndex += ncol; // compute cut coefficient flip(rowElem, slackIndex); cutCoeff = computeCutCoefficient(rowElem, slackIndex); if (isZero(fabs(cutCoeff))) { continue; } unflipSlack(cutCoeff, slackIndex, cutRhs, slackVal); eliminateSlack(cutCoeff, slackIndex, cut, cutRhs, elements, rowStart, indices, rowLength, rowRhs); #if defined GMI_TRACE printf("var %d, row %f, cut %f\n", slackIndex, rowElem, cutCoeff); #endif } } packRow(cut, cutElem, cutIndex, cutNz); if (cutNz == 0) continue; #if defined GMI_TRACE printvecDBL("final cut:", cutElem, cutIndex, cutNz); printf("cutRhs: %f\n", cutRhs); #endif #if defined TRACK_REJECT || defined TRACK_REJECT_SIMPLE if (trackRejection) { numGeneratedCuts++; } #endif if (cleanCut(cutElem, cutIndex, cutNz, cutRhs, xlp) && cutNz > 0) { OsiRowCut rc; rc.setRow(cutNz, cutIndex, cutElem); rc.setLb(-param.getINFINIT()); rc.setUb(cutRhs); if (!param.getCHECK_DUPLICATES()) { cs.insert(rc); } else{ cs.insertIfNotDuplicate(rc, CoinAbsFltEq(param.getEPS_COEFF())); } } } #if defined GMI_TRACE printf("CglGMI::generateCuts() : number of cuts : %d\n", cs.sizeRowCuts()); #endif #if defined OSI_TABLEAU solver->disableFactorization(); delete[] basicVars; delete[] tableauColPart; delete[] tableauRowPart; #endif delete[] colBasisIndex; delete[] rowBasisIndex; delete[] cut; delete[] slackVal; delete[] cutElem; delete[] cutIndex; delete[] listFracBasic; delete[] cstat; delete[] rstat; delete[] isInteger; } /* generateCuts */ /***********************************************************************/ void CglGMI::setParam(const CglGMIParam &source) { param = source; } /* setParam */ /***********************************************************************/ void CglGMI::computeIsInteger() { for (int i = 0; i < ncol; ++i) { if(solver->isInteger(i)) { isInteger[i] = true; } else { if((areEqual(colLower[i], colUpper[i], param.getEPS(), param.getEPS())) && (isIntegerValue(colUpper[i]))) { // continuous variable fixed to an integer value isInteger[i] = true; } else { isInteger[i] = false; } } } } /* computeIsInteger */ /***********************************************************************/ void CglGMI::printOptTab(OsiSolverInterface *lclSolver) const { int *cstat = new int[ncol]; int *rstat = new int[nrow]; lclSolver->enableFactorization(); lclSolver->getBasisStatus(cstat, rstat); // 0: free 1: basic // 2: upper 3: lower int *basisIndex = new int[nrow]; // basisIndex[i] = // index of pivot var in row i // (slack if number >= ncol) lclSolver->getBasics(basisIndex); double *z = new double[ncol]; // workspace to get row of the tableau double *slack = new double[nrow]; // workspace to get row of the tableau double *slackVal = new double[nrow]; for (int i = 0; i < nrow; i++) { slackVal[i] = rowRhs[i] - rowActivity[i]; } const double *rc = lclSolver->getReducedCost(); const double *dual = lclSolver->getRowPrice(); const double *solution = lclSolver->getColSolution(); printvecINT("cstat", cstat, ncol); printvecINT("rstat", rstat, nrow); printvecINT("basisIndex", basisIndex, nrow); printvecDBL("solution", solution, ncol); printvecDBL("slackVal", slackVal, nrow); printvecDBL("reduced_costs", rc, ncol); printvecDBL("dual solution", dual, nrow); printf("Optimal Tableau:\n"); for (int i = 0; i < nrow; i++) { lclSolver->getBInvARow(i, z, slack); for (int ii = 0; ii < ncol; ++ii) { printf("%5.2f ", z[ii]); } printf(" | "); for (int ii = 0; ii < nrow; ++ii) { printf("%5.2f ", slack[ii]); } printf(" | "); if(basisIndex[i] < ncol) { printf("%5.2f ", solution[basisIndex[i]]); } else { printf("%5.2f ", slackVal[basisIndex[i]-ncol]); } printf("\n"); } for (int ii = 0; ii < 7*(ncol+nrow+1); ++ii) { printf("-"); } printf("\n"); for (int ii = 0; ii < ncol; ++ii) { printf("%5.2f ", rc[ii]); } printf(" | "); for (int ii = 0; ii < nrow; ++ii) { printf("%5.2f ", -dual[ii]); } printf(" | "); printf("%5.2f\n", -lclSolver->getObjValue()); lclSolver->disableFactorization(); delete[] cstat; delete[] rstat; delete[] basisIndex; delete[] slack; delete[] z; delete[] slackVal; } /* printOptTab */