void vctMatrixRotation3Test::TestConstructorFromVectors(void) { typedef vctMatrixRotation3<_elementType> MatRotType; MatRotType matrix; vctRandom(matrix); MatRotType matrixByColumn(matrix.Column(0), matrix.Column(1), matrix.Column(2)); CPPUNIT_ASSERT(matrix == matrixByColumn); MatRotType matrixByRow(matrix.Row(0), matrix.Row(1), matrix.Row(2), false); CPPUNIT_ASSERT(matrix == matrixByRow); CPPUNIT_ASSERT(matrixByColumn == matrixByRow); }
int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment, bool changeInt, CoinMessageHandler * generalMessageHandler, bool noPrinting) { bool noPrinting_ = noPrinting; OsiSolverInterface * solver = solverMod->clone(); char generalPrint[200]; if (0) { // just get increment CbcModel model(*solver); model.analyzeObjective(); double increment2 = model.getCutoffIncrement(); printf("initial cutoff increment %g\n", increment2); } const double *objective = solver->getObjCoefficients() ; const double *lower = solver->getColLower() ; const double *upper = solver->getColUpper() ; int numberColumns = solver->getNumCols() ; int numberRows = solver->getNumRows(); double direction = solver->getObjSense(); int iRow, iColumn; // Row copy CoinPackedMatrix matrixByRow(*solver->getMatrixByRow()); const double * elementByRow = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); // Column copy CoinPackedMatrix matrixByCol(*solver->getMatrixByCol()); const double * element = matrixByCol.getElements(); const int * row = matrixByCol.getIndices(); const CoinBigIndex * columnStart = matrixByCol.getVectorStarts(); const int * columnLength = matrixByCol.getVectorLengths(); const double * rowLower = solver->getRowLower(); const double * rowUpper = solver->getRowUpper(); char * ignore = new char [numberRows]; int * changed = new int[numberColumns]; int * which = new int[numberRows]; double * changeRhs = new double[numberRows]; memset(changeRhs, 0, numberRows*sizeof(double)); memset(ignore, 0, numberRows); numberChanged = 0; int numberInteger = 0; for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8 && solver->isInteger(iColumn)) numberInteger++; } bool finished = false; while (!finished) { int saveNumberChanged = numberChanged; for (iRow = 0; iRow < numberRows; iRow++) { int numberContinuous = 0; double value1 = 0.0, value2 = 0.0; bool allIntegerCoeff = true; double sumFixed = 0.0; int jColumn1 = -1, jColumn2 = -1; for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) { int jColumn = column[j]; double value = elementByRow[j]; if (upper[jColumn] > lower[jColumn] + 1.0e-8) { if (!solver->isInteger(jColumn)) { if (numberContinuous == 0) { jColumn1 = jColumn; value1 = value; } else { jColumn2 = jColumn; value2 = value; } numberContinuous++; } else { if (fabs(value - floor(value + 0.5)) > 1.0e-12) allIntegerCoeff = false; } } else { sumFixed += lower[jColumn] * value; } } double low = rowLower[iRow]; if (low > -1.0e20) { low -= sumFixed; if (fabs(low - floor(low + 0.5)) > 1.0e-12) allIntegerCoeff = false; } double up = rowUpper[iRow]; if (up < 1.0e20) { up -= sumFixed; if (fabs(up - floor(up + 0.5)) > 1.0e-12) allIntegerCoeff = false; } if (!allIntegerCoeff) continue; // can't do if (numberContinuous == 1) { // see if really integer // This does not allow for complicated cases if (low == up) { if (fabs(value1) > 1.0e-3) { value1 = 1.0 / value1; if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) { // integer changed[numberChanged++] = jColumn1; solver->setInteger(jColumn1); if (upper[jColumn1] > 1.0e20) solver->setColUpper(jColumn1, 1.0e20); if (lower[jColumn1] < -1.0e20) solver->setColLower(jColumn1, -1.0e20); } } } else { if (fabs(value1) > 1.0e-3) { value1 = 1.0 / value1; if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) { // This constraint will not stop it being integer ignore[iRow] = 1; } } } } else if (numberContinuous == 2) { if (low == up) { /* need general theory - for now just look at 2 cases - 1 - +- 1 one in column and just costs i.e. matching objective 2 - +- 1 two in column but feeds into G/L row which will try and minimize */ if (fabs(value1) == 1.0 && value1*value2 == -1.0 && !lower[jColumn1] && !lower[jColumn2]) { int n = 0; int i; double objChange = direction * (objective[jColumn1] + objective[jColumn2]); double bound = CoinMin(upper[jColumn1], upper[jColumn2]); bound = CoinMin(bound, 1.0e20); for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) { int jRow = row[i]; double value = element[i]; if (jRow != iRow) { which[n++] = jRow; changeRhs[jRow] = value; } } for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) { int jRow = row[i]; double value = element[i]; if (jRow != iRow) { if (!changeRhs[jRow]) { which[n++] = jRow; changeRhs[jRow] = value; } else { changeRhs[jRow] += value; } } } if (objChange >= 0.0) { // see if all rows OK bool good = true; for (i = 0; i < n; i++) { int jRow = which[i]; double value = changeRhs[jRow]; if (value) { value *= bound; if (rowLength[jRow] == 1) { if (value > 0.0) { double rhs = rowLower[jRow]; if (rhs > 0.0) { double ratio = rhs / value; if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12) good = false; } } else { double rhs = rowUpper[jRow]; if (rhs < 0.0) { double ratio = rhs / value; if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12) good = false; } } } else if (rowLength[jRow] == 2) { if (value > 0.0) { if (rowLower[jRow] > -1.0e20) good = false; } else { if (rowUpper[jRow] < 1.0e20) good = false; } } else { good = false; } } } if (good) { // both can be integer changed[numberChanged++] = jColumn1; solver->setInteger(jColumn1); if (upper[jColumn1] > 1.0e20) solver->setColUpper(jColumn1, 1.0e20); if (lower[jColumn1] < -1.0e20) solver->setColLower(jColumn1, -1.0e20); changed[numberChanged++] = jColumn2; solver->setInteger(jColumn2); if (upper[jColumn2] > 1.0e20) solver->setColUpper(jColumn2, 1.0e20); if (lower[jColumn2] < -1.0e20) solver->setColLower(jColumn2, -1.0e20); } } // clear for (i = 0; i < n; i++) { changeRhs[which[i]] = 0.0; } } } } } for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (upper[iColumn] > lower[iColumn] + 1.0e-8 && !solver->isInteger(iColumn)) { double value; value = upper[iColumn]; if (value < 1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12) continue; value = lower[iColumn]; if (value > -1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12) continue; bool integer = true; for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int iRow = row[j]; if (!ignore[iRow]) { integer = false; break; } } if (integer) { // integer changed[numberChanged++] = iColumn; solver->setInteger(iColumn); if (upper[iColumn] > 1.0e20) solver->setColUpper(iColumn, 1.0e20); if (lower[iColumn] < -1.0e20) solver->setColLower(iColumn, -1.0e20); } } } finished = numberChanged == saveNumberChanged; } delete [] which; delete [] changeRhs; delete [] ignore; //if (numberInteger&&!noPrinting_) //printf("%d integer variables",numberInteger); if (changeInt) { //if (!noPrinting_) { //if (numberChanged) // printf(" and %d variables made integer\n",numberChanged); //else // printf("\n"); //} //increment=0.0; if (!numberChanged) { delete [] changed; delete solver; return NULL; } else { for (iColumn = 0; iColumn < numberColumns; iColumn++) { if (solver->isInteger(iColumn)) solverMod->setInteger(iColumn); } delete solver; return changed; } } else { //if (!noPrinting_) { //if (numberChanged) // printf(" and %d variables could be made integer\n",numberChanged); //else // printf("\n"); //} // just get increment int logLevel = generalMessageHandler->logLevel(); CbcModel model(*solver); if (!model.defaultHandler()) model.passInMessageHandler(generalMessageHandler); if (noPrinting_) model.setLogLevel(0); model.analyzeObjective(); generalMessageHandler->setLogLevel(logLevel); double increment2 = model.getCutoffIncrement(); if (increment2 > increment && increment2 > 0.0) { if (!noPrinting_) { sprintf(generalPrint, "Cutoff increment increased from %g to %g", increment, increment2); CoinMessages generalMessages = solverMod->getModelPtr()->messages(); generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol; } increment = increment2; } delete solver; numberChanged = 0; delete [] changed; return NULL; } }
//------------------------------------------------------------------- // Determine row types. Find the VUBS and VLBS. //------------------------------------------------------------------- void CglFlowCover::flowPreprocess(const OsiSolverInterface& si) const { CoinPackedMatrix matrixByRow(*si.getMatrixByRow()); int numRows = si.getNumRows(); int numCols = si.getNumCols(); const char* sense = si.getRowSense(); const double* RHS = si.getRightHandSide(); const double* coefByRow = matrixByRow.getElements(); const int* colInds = matrixByRow.getIndices(); const int* rowStarts = matrixByRow.getVectorStarts(); const int* rowLengths = matrixByRow.getVectorLengths(); int iRow = -1; int iCol = -1; numCols_ = numCols; // Record col and row numbers for copy constructor numRows_ = numRows; if (rowTypes_ != 0) { delete [] rowTypes_; rowTypes_ = 0; } rowTypes_ = new CglFlowRowType [numRows];// Destructor will free memory // Get integer types const char * columnType = si.getColType (true); // Summarize the row type infomation. int numUNDEFINED = 0; int numVARUB = 0; int numVARLB = 0; int numVAREQ = 0; int numMIXUB = 0; int numMIXEQ = 0; int numNOBINUB = 0; int numNOBINEQ = 0; int numSUMVARUB = 0; int numSUMVAREQ = 0; int numUNINTERSTED = 0; int* ind = new int [numCols]; double* coef = new double [numCols]; for (iRow = 0; iRow < numRows; ++iRow) { int rowLen = rowLengths[iRow]; char sen = sense[iRow]; double rhs = RHS[iRow]; CoinDisjointCopyN(colInds + rowStarts[iRow], rowLen, ind); CoinDisjointCopyN(coefByRow + rowStarts[iRow], rowLen, coef); CglFlowRowType rowType = determineOneRowType(si, rowLen, ind, coef, sen, rhs); rowTypes_[iRow] = rowType; switch(rowType) { case CGLFLOW_ROW_UNDEFINED: ++numUNDEFINED; break; case CGLFLOW_ROW_VARUB: ++numVARUB; break; case CGLFLOW_ROW_VARLB: ++numVARLB; break; case CGLFLOW_ROW_VAREQ: ++numVAREQ; break; case CGLFLOW_ROW_MIXUB: ++numMIXUB; break; case CGLFLOW_ROW_MIXEQ: ++numMIXEQ; break; case CGLFLOW_ROW_NOBINUB: ++numNOBINUB; break; case CGLFLOW_ROW_NOBINEQ: ++numNOBINEQ; break; case CGLFLOW_ROW_SUMVARUB: ++numSUMVARUB; break; case CGLFLOW_ROW_SUMVAREQ: ++numSUMVAREQ; break; case CGLFLOW_ROW_UNINTERSTED: ++numUNINTERSTED; break; default: throw CoinError("Unknown row type", "flowPreprocess", "CglFlowCover"); } } delete [] ind; ind = NULL; delete [] coef; coef = NULL; if(CGLFLOW_DEBUG) { std::cout << "The num of rows = " << numRows << std::endl; std::cout << "Summary of Row Type" << std::endl; std::cout << "numUNDEFINED = " << numUNDEFINED << std::endl; std::cout << "numVARUB = " << numVARUB << std::endl; std::cout << "numVARLB = " << numVARLB << std::endl; std::cout << "numVAREQ = " << numVAREQ << std::endl; std::cout << "numMIXUB = " << numMIXUB << std::endl; std::cout << "numMIXEQ = " << numMIXEQ << std::endl; std::cout << "numNOBINUB = " << numNOBINUB << std::endl; std::cout << "numNOBINEQ = " << numNOBINEQ << std::endl; std::cout << "numSUMVARUB = " << numSUMVARUB << std::endl; std::cout << "numSUMVAREQ = " << numSUMVAREQ << std::endl; std::cout << "numUNINTERSTED = " << numUNINTERSTED << std::endl; } //--------------------------------------------------------------------------- // Setup vubs_ and vlbs_ if (vubs_ != 0) { delete [] vubs_; vubs_ = 0; } vubs_ = new CglFlowVUB [numCols]; // Destructor will free memory if (vlbs_ != 0) { delete [] vlbs_; vlbs_ = 0; } vlbs_ = new CglFlowVLB [numCols]; // Destructor will free memory for (iCol = 0; iCol < numCols; ++iCol) { // Initilized in constructor vubs_[iCol].setVar(UNDEFINED_); // but, need redo since may call vlbs_[iCol].setVar(UNDEFINED_); // preprocess(...) more than once } for (iRow = 0; iRow < numRows; ++iRow) { CglFlowRowType rowType2 = rowTypes_[iRow]; if ( (rowType2 == CGLFLOW_ROW_VARUB) || (rowType2 == CGLFLOW_ROW_VARLB) || (rowType2 == CGLFLOW_ROW_VAREQ) ) { int startPos = rowStarts[iRow]; int index0 = colInds[startPos]; int index1 = colInds[startPos + 1]; double coef0 = coefByRow[startPos]; double coef1 = coefByRow[startPos + 1]; int xInd, yInd; // x is binary double xCoef, yCoef; if ( columnType[index0]==1 ) { xInd = index0; yInd = index1; xCoef = coef0; yCoef = coef1; } else { xInd = index1; yInd = index0; xCoef = coef1; yCoef = coef0; } switch (rowType2) { case CGLFLOW_ROW_VARUB: // Inequality: y <= ? * x vubs_[yInd].setVar(xInd); vubs_[yInd].setVal(-xCoef / yCoef); break; case CGLFLOW_ROW_VARLB: // Inequality: y >= ? * x vlbs_[yInd].setVar(xInd); vlbs_[yInd].setVal(-xCoef / yCoef); break; case CGLFLOW_ROW_VAREQ: // Inequality: y >= AND <= ? * x vubs_[yInd].setVar(xInd); vubs_[yInd].setVal(-xCoef / yCoef); vlbs_[yInd].setVar(xInd); vlbs_[yInd].setVal(-xCoef / yCoef); break; default: throw CoinError("Unknown row type: impossible", "flowPreprocess", "CglFlowCover"); } } } if(CGLFLOW_DEBUG) { printVubs(std::cout); } }
//----------------------------------------------------------------------------- // Generate LSGFC cuts //------------------------------------------------------------------- void CglFlowCover::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, const CglTreeInfo info) const { static int count=0; if (getMaxNumCuts() <= 0) return; if (getNumFlowCuts() >= getMaxNumCuts()) return; ++count; #if 0 bool preInit = false; bool preReso = false; si.getHintParam(OsiDoPresolveInInitial, preInit); si.getHintParam(OsiDoPresolveInResolve, preReso); if (preInit == false && preReso == false) { // Do once if (doneInitPre_ == false) { flowPreprocess(si); doneInitPre_ = true; } } else #endif int numberRowCutsBefore = cs.sizeRowCuts(); flowPreprocess(si); CoinPackedMatrix matrixByRow(*si.getMatrixByRow()); const char* sense = si.getRowSense(); const double* rhs = si.getRightHandSide(); const double* elementByRow = matrixByRow.getElements(); const int* colInd = matrixByRow.getIndices(); const CoinBigIndex* rowStart = matrixByRow.getVectorStarts(); const int* rowLength = matrixByRow.getVectorLengths(); int* ind = 0; double* coef = 0; int iRow, iCol; CglFlowRowType rType; for (iRow = 0; iRow < numRows_; ++iRow) { rType = getRowType(iRow); if( ( rType != CGLFLOW_ROW_MIXUB ) && ( rType != CGLFLOW_ROW_MIXEQ ) && ( rType != CGLFLOW_ROW_NOBINUB ) && ( rType != CGLFLOW_ROW_NOBINEQ ) && ( rType != CGLFLOW_ROW_SUMVARUB ) && ( rType != CGLFLOW_ROW_SUMVAREQ ) ) continue; const int sta = rowStart[iRow]; // Start position of iRow const int rowLen = rowLength[iRow]; // iRow length / non-zero elements if (ind != 0) { delete [] ind; ind = 0; } ind = new int [rowLen]; if (coef != 0) { delete [] coef; coef = 0; } coef = new double [rowLen]; int lastPos = sta + rowLen; for (iCol = sta; iCol < lastPos; ++iCol) { ind[iCol - sta] = colInd[iCol]; coef[iCol - sta] = elementByRow[iCol]; } OsiRowCut flowCut1, flowCut2, flowCut3; double violation = 0.0; bool hasCut = false; if (sense[iRow] == 'E') { hasCut = generateOneFlowCut(si, rowLen, ind, coef, 'L', rhs[iRow], flowCut1, violation); if (hasCut) { // If find a cut cs.insert(flowCut1); incNumFlowCuts(); if (getNumFlowCuts() >= getMaxNumCuts()) break; } hasCut = false; hasCut = generateOneFlowCut(si, rowLen, ind, coef, 'G', rhs[iRow], flowCut2, violation); if (hasCut) { cs.insert(flowCut2); incNumFlowCuts(); if (getNumFlowCuts() >= getMaxNumCuts()) break; } } if (sense[iRow] == 'L' || sense[iRow] == 'G') { hasCut = generateOneFlowCut(si, rowLen, ind, coef, sense[iRow], rhs[iRow], flowCut3, violation); if (hasCut) { cs.insert(flowCut3); incNumFlowCuts(); if (getNumFlowCuts() >= getMaxNumCuts()) break; } } } #ifdef CGLFLOW_DEBUG2 if(CGLFLOW_DEBUG) { std::cout << "\nnumFlowCuts = "<< getNumFlowCuts() << std::endl; std::cout << "CGLFLOW_COL_BINNEG = "<< CGLFLOW_COL_BINNEG << std::endl; } #endif if (!info.inTree&&((info.options&4)==4||((info.options&8)&&!info.pass))) { int numberRowCutsAfter = cs.sizeRowCuts(); for (int i=numberRowCutsBefore;i<numberRowCutsAfter;i++) cs.rowCutPtr(i)->setGloballyValid(); } if (ind != 0) { delete [] ind; ind = 0; } if (coef != 0) { delete [] coef; coef = 0; } }