int OsiVolSolverInterface::readMps(const char *filename, const char *extension) { CoinMpsIO reader; reader.setInfinity(getInfinity()); int retVal = reader.readMps(filename, extension); loadProblem(*reader.getMatrixByCol(), reader.getColLower(), reader.getColUpper(), reader.getObjCoefficients(), reader.getRowLower(), reader.getRowUpper()); int nc = getNumCols(); assert (continuous_); CoinFillN(continuous_, nc, true); return retVal; }
int main(int argc, const char *argv[]) { int status; CoinMpsIO m; if (argc < 2) status = m.readMps("model1.mps", ""); else status = m.readMps(argv[1], ""); if (status) { fprintf(stdout, "Bad readMps %s\n", argv[1]); exit(1); } // Load up model1 - so we can use known good solution ClpSimplex model1; model1.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); model1.dual(); // Get data arrays const CoinPackedMatrix * matrix1 = m.getMatrixByCol(); const int * start1 = matrix1->getVectorStarts(); const int * length1 = matrix1->getVectorLengths(); const int * row1 = matrix1->getIndices(); const double * element1 = matrix1->getElements(); const double * columnLower1 = m.getColLower(); const double * columnUpper1 = m.getColUpper(); const double * rowLower1 = m.getRowLower(); const double * rowUpper1 = m.getRowUpper(); const double * objective1 = m.getObjCoefficients(); int numberColumns = m.getNumCols(); int numberRows = m.getNumRows(); int numberElements = m.getNumElements(); // Get new arrays int numberColumns2 = (numberColumns + 1); int * start2 = new int[numberColumns2+1]; int * row2 = new int[numberElements]; double * element2 = new double[numberElements]; int * segstart = new int[numberColumns+1]; double * breakpt = new double[2*numberColumns]; double * slope = new double[2*numberColumns]; double * objective2 = new double[numberColumns2]; double * columnLower2 = new double[numberColumns2]; double * columnUpper2 = new double[numberColumns2]; double * rowLower2 = new double[numberRows]; double * rowUpper2 = new double[numberRows]; // We need to modify rhs memcpy(rowLower2, rowLower1, numberRows * sizeof(double)); memcpy(rowUpper2, rowUpper1, numberRows * sizeof(double)); double objectiveOffset = 0.0; // For new solution double * newSolution = new double [numberColumns]; const double * oldSolution = model1.primalColumnSolution(); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) printf("%g ", oldSolution[iColumn]); printf("\n"); numberColumns2 = 0; numberElements = 0; start2[0] = 0; int segptr = 0; segstart[0] = 0; // Now check for duplicates for (iColumn = 0; iColumn < numberColumns; iColumn++) { // test if column identical to next column bool ifcopy = 1; if (iColumn < numberColumns - 1) { int joff = length1[iColumn]; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { if (row1[j] != row1[j+joff]) { ifcopy = 0; break; } if (element1[j] != element1[j+joff]) { ifcopy = 0; break; } } } else { ifcopy = 0; } //if (iColumn>47||iColumn<45) //ifcopy=0; if (ifcopy) { double lo1 = columnLower1[iColumn]; double up1 = columnUpper1[iColumn]; double obj1 = objective1[iColumn]; double sol1 = oldSolution[iColumn]; double lo2 = columnLower1[iColumn+1]; double up2 = columnUpper1[iColumn+1]; double obj2 = objective1[iColumn+1]; double sol2 = oldSolution[iColumn+1]; if (fabs(up1 - lo2) > 1.0e-8) { // try other way double temp; temp = lo1; lo1 = lo2; lo2 = temp; temp = up1; up1 = up2; up2 = temp; temp = obj1; obj1 = obj2; obj2 = temp; temp = sol1; sol1 = sol2; sol2 = temp; assert(fabs(up1 - lo2) < 1.0e-8); } // subtract out from rhs double fixed = up1; // do offset objectiveOffset += fixed * obj2; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { int iRow = row1[j]; double value = element1[j]; if (rowLower2[iRow] > -1.0e30) rowLower2[iRow] -= value * fixed; if (rowUpper2[iRow] < 1.0e30) rowUpper2[iRow] -= value * fixed; } newSolution[numberColumns2] = fixed; if (fabs(sol1 - fixed) > 1.0e-8) newSolution[numberColumns2] = sol1; if (fabs(sol2 - fixed) > 1.0e-8) newSolution[numberColumns2] = sol2; columnLower2[numberColumns2] = lo1; columnUpper2[numberColumns2] = up2; objective2[numberColumns2] = 0.0; breakpt[segptr] = lo1; slope[segptr++] = obj1; breakpt[segptr] = lo2; slope[segptr++] = obj2; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { row2[numberElements] = row1[j]; element2[numberElements++] = element1[j]; } start2[++numberColumns2] = numberElements; breakpt[segptr] = up2; slope[segptr++] = COIN_DBL_MAX; segstart[numberColumns2] = segptr; iColumn++; // skip next column } else { // normal column columnLower2[numberColumns2] = columnLower1[iColumn]; columnUpper2[numberColumns2] = columnUpper1[iColumn]; objective2[numberColumns2] = objective1[iColumn]; breakpt[segptr] = columnLower1[iColumn]; slope[segptr++] = objective1[iColumn]; for (int j = start1[iColumn]; j < start1[iColumn] + length1[iColumn]; j++) { row2[numberElements] = row1[j]; element2[numberElements++] = element1[j]; } newSolution[numberColumns2] = oldSolution[iColumn]; start2[++numberColumns2] = numberElements; breakpt[segptr] = columnUpper1[iColumn]; slope[segptr++] = COIN_DBL_MAX; segstart[numberColumns2] = segptr; } } // print new number of columns, elements printf("New number of columns = %d\n", numberColumns2); printf("New number of elements = %d\n", numberElements); printf("Objective offset is %g\n", objectiveOffset); ClpSimplex model; // load up model.loadProblem(numberColumns2, numberRows, start2, row2, element2, columnLower2, columnUpper2, objective2, rowLower2, rowUpper2); model.scaling(0); model.setDblParam(ClpObjOffset, -objectiveOffset); // Create nonlinear objective int returnCode = model.createPiecewiseLinearCosts(segstart, breakpt, slope); assert(!returnCode); // delete delete [] segstart; delete [] breakpt; delete [] slope; delete [] start2; delete [] row2 ; delete [] element2; delete [] objective2; delete [] columnLower2; delete [] columnUpper2; delete [] rowLower2; delete [] rowUpper2; // copy in solution - (should be optimal) model.allSlackBasis(); memcpy(model.primalColumnSolution(), newSolution, numberColumns2 * sizeof(double)); //memcpy(model.columnLower(),newSolution,numberColumns2*sizeof(double)); //memcpy(model.columnUpper(),newSolution,numberColumns2*sizeof(double)); delete [] newSolution; //model.setLogLevel(63); const double * solution = model.primalColumnSolution(); double * saveSol = new double[numberColumns2]; memcpy(saveSol, solution, numberColumns2 * sizeof(double)); for (iColumn = 0; iColumn < numberColumns2; iColumn++) printf("%g ", solution[iColumn]); printf("\n"); // solve model.primal(1); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.primal(1); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.primal(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.allSlackBasis(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); model.setLogLevel(63); model.primal(); for (iColumn = 0; iColumn < numberColumns2; iColumn++) { if (fabs(solution[iColumn] - saveSol[iColumn]) > 1.0e-3) printf(" ** was %g ", saveSol[iColumn]); printf("%g ", solution[iColumn]); } printf("\n"); return 0; }
//-------------------------------------------------------------------------- // Test building a model void CoinModelUnitTest(const std::string & mpsDir, const std::string & netlibDir, const std::string & testModel) { // Get a model CoinMpsIO m; std::string fn = mpsDir+"exmip1"; int numErr = m.readMps(fn.c_str(),"mps"); assert( numErr== 0 ); int numberRows = m.getNumRows(); int numberColumns = m.getNumCols(); // Build by row from scratch { CoinPackedMatrix matrixByRow = * m.getMatrixByRow(); const double * element = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); const double * rowLower = m.getRowLower(); const double * rowUpper = m.getRowUpper(); const double * columnLower = m.getColLower(); const double * columnUpper = m.getColUpper(); const double * objective = m.getObjCoefficients(); int i; CoinModel temp; for (i=0; i<numberRows; i++) { temp.addRow(rowLength[i],column+rowStart[i], element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i)); } // Now do column part for (i=0; i<numberColumns; i++) { temp.setColumnBounds(i,columnLower[i],columnUpper[i]); temp.setColumnObjective(i,objective[i]); if (m.isInteger(i)) temp.setColumnIsInteger(i,true);; } // write out temp.writeMps("byRow.mps"); } // Build by column from scratch and save CoinModel model; { CoinPackedMatrix matrixByColumn = * m.getMatrixByCol(); const double * element = matrixByColumn.getElements(); const int * row = matrixByColumn.getIndices(); const CoinBigIndex * columnStart = matrixByColumn.getVectorStarts(); const int * columnLength = matrixByColumn.getVectorLengths(); const double * rowLower = m.getRowLower(); const double * rowUpper = m.getRowUpper(); const double * columnLower = m.getColLower(); const double * columnUpper = m.getColUpper(); const double * objective = m.getObjCoefficients(); int i; for (i=0; i<numberColumns; i++) { model.addColumn(columnLength[i],row+columnStart[i], element+columnStart[i],columnLower[i],columnUpper[i], objective[i],m.columnName(i),m.isInteger(i)); } // Now do row part for (i=0; i<numberRows; i++) { model.setRowBounds(i,rowLower[i],rowUpper[i]); } // write out model.writeMps("byColumn.mps"); } // model was created by column - play around { CoinModel temp; int i; for (i=numberRows-1; i>=0; i--) temp.setRowLower(i,model.getRowLower(i)); for (i=0; i<numberColumns; i++) { temp.setColumnUpper(i,model.getColumnUpper(i)); temp.setColumnName(i,model.getColumnName(i)); } for (i=numberColumns-1; i>=0; i--) { temp.setColumnLower(i,model.getColumnLower(i)); temp.setColumnObjective(i,model.getColumnObjective(i)); temp.setColumnIsInteger(i,model.getColumnIsInteger(i)); } for (i=0; i<numberRows; i++) { temp.setRowUpper(i,model.getRowUpper(i)); temp.setRowName(i,model.getRowName(i)); } // Now elements for (i=0; i<numberRows; i++) { CoinModelLink triple=model.firstInRow(i); while (triple.column()>=0) { temp(i,triple.column(),triple.value()); triple=model.next(triple); } } // and by column for (i=numberColumns-1; i>=0; i--) { CoinModelLink triple=model.lastInColumn(i); while (triple.row()>=0) { assert (triple.value()==temp(triple.row(),i)); temp(triple.row(),i,triple.value()); triple=model.previous(triple); } } // check equal model.setLogLevel(1); assert (!model.differentModel(temp,false)); } // Try creating model with strings { CoinModel temp; int i; for (i=numberRows-1; i>=0; i--) { double value = model.getRowLower(i); if (value==-1.0) temp.setRowLower(i,"minusOne"); else if (value==1.0) temp.setRowLower(i,"sqrt(plusOne)"); else if (value==4.0) temp.setRowLower(i,"abs(4*plusOne)"); else temp.setRowLower(i,value); } for (i=0; i<numberColumns; i++) { double value; value = model.getColumnUpper(i); if (value==-1.0) temp.setColumnUpper(i,"minusOne"); else if (value==1.0) temp.setColumnUpper(i,"plusOne"); else temp.setColumnUpper(i,value); temp.setColumnName(i,model.getColumnName(i)); } for (i=numberColumns-1; i>=0; i--) { temp.setColumnLower(i,model.getColumnLower(i)); temp.setColumnObjective(i,model.getColumnObjective(i)); temp.setColumnIsInteger(i,model.getColumnIsInteger(i)); } for (i=0; i<numberRows; i++) { double value = model.getRowUpper(i); if (value==-1.0) temp.setRowUpper(i,"minusOne"); else if (value==1.0) temp.setRowUpper(i,"plusOne"); else temp.setRowUpper(i,value); temp.setRowName(i,model.getRowName(i)); } // Now elements for (i=0; i<numberRows; i++) { CoinModelLink triple=model.firstInRow(i); while (triple.column()>=0) { double value = triple.value(); if (value==-1.0) temp(i,triple.column(),"minusOne"); else if (value==1.0) temp(i,triple.column(),"plusOne"); else if (value==-2.0) temp(i,triple.column(),"minusOne-1.0"); else if (value==2.0) temp(i,triple.column(),"plusOne+1.0+minusOne+(2.0-plusOne)"); else temp(i,triple.column(),value); triple=model.next(triple); } } temp.associateElement("minusOne",-1.0); temp.associateElement("plusOne",1.0); temp.setProblemName("fromStrings"); temp.writeMps("string.mps"); // check equal model.setLogLevel(1); assert (!model.differentModel(temp,false)); } // Test with various ways of generating { /* Get a model. Try first with netlibDir, fall back to mpsDir (sampleDir) if that fails. */ CoinMpsIO m; std::string fn = netlibDir+testModel; double time1 = CoinCpuTime(); int numErr = m.readMps(fn.c_str(),""); if (numErr != 0) { std::cout << "Could not read " << testModel << " in " << netlibDir << "; falling back to " << mpsDir << "." << std::endl ; fn = mpsDir+testModel ; numErr = m.readMps(fn.c_str(),"") ; if (numErr != 0) { std::cout << "Could not read " << testModel << "; skipping test." << std::endl ; } } if (numErr == 0) { std::cout << "Time for readMps is " << (CoinCpuTime()-time1) << " seconds." << std::endl ; int numberRows = m.getNumRows(); int numberColumns = m.getNumCols(); // Build model CoinModel model; CoinPackedMatrix matrixByRow = * m.getMatrixByRow(); const double * element = matrixByRow.getElements(); const int * column = matrixByRow.getIndices(); const CoinBigIndex * rowStart = matrixByRow.getVectorStarts(); const int * rowLength = matrixByRow.getVectorLengths(); const double * rowLower = m.getRowLower(); const double * rowUpper = m.getRowUpper(); const double * columnLower = m.getColLower(); const double * columnUpper = m.getColUpper(); const double * objective = m.getObjCoefficients(); int i; for (i=0; i<numberRows; i++) { model.addRow(rowLength[i],column+rowStart[i], element+rowStart[i],rowLower[i],rowUpper[i],m.rowName(i)); } // Now do column part for (i=0; i<numberColumns; i++) { model.setColumnBounds(i,columnLower[i],columnUpper[i]); model.setColumnObjective(i,objective[i]); model.setColumnName(i,m.columnName(i)); if (m.isInteger(i)) model.setColumnIsInteger(i,true);; } // Test CoinSeedRandom(11111); time1 = 0.0; int nPass=50; for (i=0; i<nPass; i++) { double random = CoinDrand48(); int iSeed = (int) (random*1000000); //iSeed = 776151; CoinSeedRandom(iSeed); std::cout << "before pass " << i << " with seed of " << iSeed << std::endl ; buildRandom(model,CoinDrand48(),time1,i); model.validateLinks(); } std::cout << "Time for " << nPass << " CoinModel passes is " << time1 << " seconds\n" << std::endl ; } } }
int main(int argc, const char *argv[]) { /* Read quadratic model in two stages to test loadQuadraticObjective. And is also possible to just read into ClpSimplex/Interior which sets it all up in one go. But this is only if it is in QUADOBJ format. If no arguments does share2qp using ClpInterior (also creates quad.mps which is in QUADOBJ format) If one argument uses simplex e.g. testit quad.mps If > one uses barrier via ClpSimplex input and then ClpInterior borrow */ if (argc < 2) { CoinMpsIO m; #if defined(SAMPLEDIR) int status = m.readMps(SAMPLEDIR "/share2qp", "mps"); #else fprintf(stderr, "Do not know where to find sample MPS files.\n"); exit(1); #endif if (status) { printf("errors on input\n"); exit(77); } ClpInterior model; model.loadProblem(*m.getMatrixByCol(), m.getColLower(), m.getColUpper(), m.getObjCoefficients(), m.getRowLower(), m.getRowUpper()); // get quadratic part int * start = NULL; int * column = NULL; double * element = NULL; m.readQuadraticMps(NULL, start, column, element, 2); int j; for (j = 0; j < 79; j++) { if (start[j] < start[j+1]) { int i; printf("Column %d ", j); for (i = start[j]; i < start[j+1]; i++) { printf("( %d, %g) ", column[i], element[i]); } printf("\n"); } } model.loadQuadraticObjective(model.numberColumns(), start, column, element); // share2qp is in old style qp format - convert to new so other options can use model.writeMps("quad.mps"); ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); model.setCholesky(cholesky); model.primalDual(); double *primal; double *dual; primal = model.primalColumnSolution(); dual = model.dualRowSolution(); int i; int numberColumns = model.numberColumns(); int numberRows = model.numberRows(); for (i = 0; i < numberColumns; i++) { if (fabs(primal[i]) > 1.0e-8) printf("%d primal %g\n", i, primal[i]); } for (i = 0; i < numberRows; i++) { if (fabs(dual[i]) > 1.0e-8) printf("%d dual %g\n", i, dual[i]); } } else { // Could read into ClpInterior ClpSimplex model; if (model.readMps(argv[1])) { printf("errors on input\n"); exit(77); } model.writeMps("quad"); if (argc < 3) { // simplex - just primal as dual does not work // also I need to fix scaling of duals on output // (Was okay in first place - can't mix and match scaling techniques) // model.scaling(0); model.primal(); } else { // barrier ClpInterior barrier; barrier.borrowModel(model); ClpCholeskyBase * cholesky = new ClpCholeskyBase(); cholesky->setKKT(true); barrier.setCholesky(cholesky); barrier.primalDual(); barrier.returnModel(model); } // Just check if share2qp (quad.mps here) // this is because I am not checking if variables at ub if (model.numberColumns() == 79) { double *primal; double *dual; primal = model.primalColumnSolution(); dual = model.dualRowSolution(); // Check duals by hand const ClpQuadraticObjective * quadraticObj = (dynamic_cast<const ClpQuadraticObjective*>(model.objectiveAsObject())); assert(quadraticObj); CoinPackedMatrix * quad = quadraticObj->quadraticObjective(); const int * columnQuadratic = quad->getIndices(); const CoinBigIndex * columnQuadraticStart = quad->getVectorStarts(); const int * columnQuadraticLength = quad->getVectorLengths(); const double * quadraticElement = quad->getElements(); int numberColumns = model.numberColumns(); int numberRows = model.numberRows(); double * gradient = new double [numberColumns]; // move linear objective memcpy(gradient, quadraticObj->linearObjective(), numberColumns * sizeof(double)); int iColumn; for (iColumn = 0; iColumn < numberColumns; iColumn++) { double valueI = primal[iColumn]; CoinBigIndex j; for (j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; double valueJ = primal[jColumn]; double elementValue = quadraticElement[j]; if (iColumn != jColumn) { double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; gradient[iColumn] += gradientI; gradient[jColumn] += gradientJ; } else { double gradientI = valueI * elementValue; gradient[iColumn] += gradientI; } } if (fabs(primal[iColumn]) > 1.0e-8) printf("%d primal %g\n", iColumn, primal[iColumn]); } for (int i = 0; i < numberRows; i++) { if (fabs(dual[i]) > 1.0e-8) printf("%d dual %g\n", i, dual[i]); } // Now use duals to get reduced costs // Can't use this as will try and use scaling // model.transposeTimes(-1.0,dual,gradient); // So ... CoinPackedMatrix * matrix = model.matrix(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); const double * element = matrix->getElements(); for (iColumn = 0; iColumn < numberColumns; iColumn++) { double dj = gradient[iColumn]; CoinBigIndex j; for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) { int jRow = row[j]; dj -= element[j] * dual[jRow]; } if (model.getColumnStatus(iColumn) == ClpSimplex::basic) { assert(fabs(dj) < 1.0e-5); } else { assert(dj > -1.0e-5); } } delete [] gradient; } } return 0; }