// Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. #include "ClpConfig.h" #include "CoinPragma.hpp" #include #include #include #include #include #include #include "CoinMpsIO.hpp" #include "CoinPackedMatrix.hpp" #include "CoinPackedVector.hpp" #include "CoinHelperFunctions.hpp" #include "CoinTime.hpp" #include "ClpFactorization.hpp" #include "ClpSimplex.hpp" #include "ClpSimplexOther.hpp" #include "ClpSimplexNonlinear.hpp" #include "ClpInterior.hpp" #include "ClpLinearObjective.hpp" #include "ClpDualRowSteepest.hpp" #include "ClpDualRowDantzig.hpp" #include "ClpPrimalColumnSteepest.hpp" #include "ClpPrimalColumnDantzig.hpp" #include "ClpParameters.hpp" #include "ClpNetworkMatrix.hpp" #include "ClpPlusMinusOneMatrix.hpp" #include "MyMessageHandler.hpp" #include "MyEventHandler.hpp" #include "ClpPresolve.hpp" #include "Idiot.hpp" //############################################################################# #ifdef NDEBUG #undef NDEBUG #endif // Function Prototypes. Function definitions is in this file. void testingMessage( const char * const msg ); #if UFL_BARRIER static int barrierAvailable=1; static std::string nameBarrier="barrier-UFL"; #elif WSSMP_BARRIER static int barrierAvailable=2; static std::string nameBarrier="barrier-WSSMP"; #else static int barrierAvailable=0; static std::string nameBarrier="barrier-slow"; #endif #define NUMBER_ALGORITHMS 12 // If you just want a subset then set some to 1 static int switchOff[NUMBER_ALGORITHMS]={0,0,0,0,0,0,0,0,0,0,0,0}; // shortName - 0 no , 1 yes ClpSolve setupForSolve(int algorithm, std::string & nameAlgorithm, int shortName) { ClpSolve solveOptions; /* algorithms are 0 barrier 1 dual with volumne crash 2,3 dual with and without crash 4,5 primal with and without 6,7 automatic with and without 8,9 primal with idiot 1 and 5 10,11 primal with 70, dual with volume */ switch (algorithm) { case 0: if (shortName) nameAlgorithm="ba"; else nameAlgorithm="nameBarrier"; solveOptions.setSolveType(ClpSolve::useBarrier); if (barrierAvailable==1) solveOptions.setSpecialOption(4,4); else if (barrierAvailable==2) solveOptions.setSpecialOption(4,2); break; case 1: #ifdef COIN_HAS_VOL if (shortName) nameAlgorithm="du-vol-50"; else nameAlgorithm="dual-volume-50"; solveOptions.setSolveType(ClpSolve::useDual); solveOptions.setSpecialOption(0,2,50); // volume #else solveOptions.setSolveType(ClpSolve::notImplemented); #endif break; case 2: if (shortName) nameAlgorithm="du-cr"; else nameAlgorithm="dual-crash"; solveOptions.setSolveType(ClpSolve::useDual); solveOptions.setSpecialOption(0,1); break; case 3: if (shortName) nameAlgorithm="du"; else nameAlgorithm="dual"; solveOptions.setSolveType(ClpSolve::useDual); break; case 4: if (shortName) nameAlgorithm="pr-cr"; else nameAlgorithm="primal-crash"; solveOptions.setSolveType(ClpSolve::usePrimal); solveOptions.setSpecialOption(1,1); break; case 5: if (shortName) nameAlgorithm="pr"; else nameAlgorithm="primal"; solveOptions.setSolveType(ClpSolve::usePrimal); break; case 6: if (shortName) nameAlgorithm="au-cr"; else nameAlgorithm="either-crash"; solveOptions.setSolveType(ClpSolve::automatic); solveOptions.setSpecialOption(1,1); break; case 7: if (shortName) nameAlgorithm="au"; else nameAlgorithm="either"; solveOptions.setSolveType(ClpSolve::automatic); break; case 8: if (shortName) nameAlgorithm="pr-id-1"; else nameAlgorithm="primal-idiot-1"; solveOptions.setSolveType(ClpSolve::usePrimalorSprint); solveOptions.setSpecialOption(1,2,1); // idiot break; case 9: if (shortName) nameAlgorithm="pr-id-5"; else nameAlgorithm="primal-idiot-5"; solveOptions.setSolveType(ClpSolve::usePrimalorSprint); solveOptions.setSpecialOption(1,2,5); // idiot break; case 10: if (shortName) nameAlgorithm="pr-id-70"; else nameAlgorithm="primal-idiot-70"; solveOptions.setSolveType(ClpSolve::usePrimalorSprint); solveOptions.setSpecialOption(1,2,70); // idiot break; case 11: #ifdef COIN_HAS_VOL if (shortName) nameAlgorithm="du-vol"; else nameAlgorithm="dual-volume"; solveOptions.setSolveType(ClpSolve::useDual); solveOptions.setSpecialOption(0,2,3000); // volume #else solveOptions.setSolveType(ClpSolve::notImplemented); #endif break; default: abort(); } if (shortName) { // can switch off if (switchOff[algorithm]) solveOptions.setSolveType(ClpSolve::notImplemented); } return solveOptions; } static void printSol(ClpSimplex & model) { int numberRows = model.numberRows(); int numberColumns = model.numberColumns(); double * rowPrimal = model.primalRowSolution(); double * rowDual = model.dualRowSolution(); double * rowLower = model.rowLower(); double * rowUpper = model.rowUpper(); int iRow; double objValue = model.getObjValue(); printf("Objvalue %g Rows (%d)\n",objValue,numberRows); for (iRow=0;iRowgradient(&model, // columnPrimal,offset,true,1); const double * gradient = model.objective(columnPrimal,offset); int iColumn; objValue = -offset-model.objectiveOffset(); printf("offset %g (%g)\n",offset,model.objectiveOffset()); printf("Columns (%d)\n",numberColumns); for (iColumn=0;iColumn1.0e-8) printf("obj -> %g gradient %g\n",objValue,gradient[iColumn]); } printf("Computed objective %g\n",objValue); } void usage(const std::string& key) { std::cerr <<"Undefined parameter \"" <0) { // switch off some int iTest; for (iTest=0;iTest definedKeyWords; definedKeyWords.insert("-dirSample"); definedKeyWords.insert("-dirNetlib"); definedKeyWords.insert("-netlib"); // Create a map of parameter keys and associated data std::map parms; for ( i=1; i mpsName; std::vector min; std::vector nRows; std::vector nCols; std::vector objValue; std::vector objValueTol; // 100 added means no presolve std::vector bestStrategy; if(empty.numberRows()) { std::string alg; for (int iTest=0;iTest(matrix)) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); } } solution.initialSolve(solveOptions); double time2 = CoinCpuTime()-time1; testTime[iTest]=time2; printf("Took %g seconds - status %d\n",time2,solution.problemStatus()); if (solution.problemStatus()) testTime[iTest]=1.0e20; } else { testTime[iTest]=1.0e30; } } int iBest=-1; double dBest=1.0e10; printf("%s",fn.c_str()); for (iTest=0;iTest=0) printf("Best strategy for %s is %s (%d) which takes %g seconds\n", fn.c_str(),alg[iBest].c_str(),iBest,testTime[iBest]); else printf("No strategy finished in time limit\n"); continue; } double time1 = CoinCpuTime(); ClpSimplex solution=solutionBase; #if 0 solution.setOptimizationDirection(-1); { int j; double * obj = solution.objective(); int n=solution.numberColumns(); for (j=0;j(matrix)) { ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix); clpMatrix->makeSpecialColumnCopy(); } } solution.initialSolve(solveOptions); double time2 = CoinCpuTime()-time1; timeTaken += time2; printf("%s took %g seconds using algorithm %s\n",fn.c_str(),time2,nameAlgorithm.c_str()); // Test objective solution value { double soln = solution.objectiveValue(); CoinRelFltEq eq(objValueTol[m]); std::cerr <setDetailMessage(1,102); model.setFactorizationFrequency(10); model.primal(); model.primal(0,3); model.setObjCoeff(3,-2.9473684210526314); model.primal(0,3); // Write saved solutions int nc = model.getNumCols(); int s; std::deque fep = messageHandler.getFeasibleExtremePoints(); int numSavedSolutions = fep.size(); for ( s=0; s1.0e-8) std::cout <<"Saved Solution: " <1.0e-8) std::cout <<"Saved Solution: " <scaling(0); model2->setLogLevel(63); model2->parametrics(0.0,endingTheta,0.1, NULL,NULL,rhs,rhs,NULL); #endif } // Test binv etc { /* Wolsey : Page 130 max 4x1 - x2 7x1 - 2x2 <= 14 x2 <= 3 2x1 - 2x2 <= 3 x1 in Z+, x2 >= 0 note slacks are -1 in Clp so signs may be different */ int n_cols = 2; int n_rows = 3; double obj[2] = {-4.0, 1.0}; double collb[2] = {0.0, 0.0}; double colub[2] = {COIN_DBL_MAX, COIN_DBL_MAX}; double rowlb[3] = {-COIN_DBL_MAX, -COIN_DBL_MAX, -COIN_DBL_MAX}; double rowub[3] = {14.0, 3.0, 3.0}; int rowIndices[5] = {0, 2, 0, 1, 2}; int colIndices[5] = {0, 0, 1, 1, 1}; double elements[5] = {7.0, 2.0, -2.0, 1.0, -2.0}; CoinPackedMatrix M(true, rowIndices, colIndices, elements, 5); ClpSimplex model; model.loadProblem(M, collb, colub, obj, rowlb, rowub); model.dual(0,1); // keep factorization //check that the tableau matches wolsey (B-1 A) // slacks in second part of binvA double * binvA = (double*) malloc((n_cols+n_rows) * sizeof(double)); printf("B-1 A by row\n"); int i; for( i = 0; i < n_rows; i++){ model.getBInvARow(i, binvA,binvA+n_cols); printf("row: %d -> ",i); for(int j=0; j < n_cols+n_rows; j++){ printf("%g, ", binvA[j]); } printf("\n"); } // See if can re-use factorization AND arrays model.primal(0,3+4); // keep factorization // And do by column printf("B-1 A by column\n"); for( i = 0; i < n_rows+n_cols; i++){ model.getBInvACol(i, binvA); printf("column: %d -> ",i); for(int j=0; j < n_rows; j++){ printf("%g, ", binvA[j]); } printf("\n"); } /* Do twice - without and with scaling */ // set scaling off model.scaling(0); for (int iPass=0;iPass<2;iPass++) { model.primal(0,3+4); // keep factorization const double * rowScale = model.rowScale(); const double * columnScale = model.columnScale(); if (!iPass) assert (!rowScale); else assert (rowScale); // only true for this example /* has to be exactly correct as in OsiClpsolverInterface.cpp (also redo each pass as may change */ printf("B-1 A"); for( i = 0; i < n_rows; i++){ model.getBInvARow(i, binvA,binvA+n_cols); printf("\nrow: %d -> ",i); int j; // First columns for(j=0; j < n_cols; j++){ if (binvA[j]) { printf("(%d %g), ", j, binvA[j]); } } // now rows for(j=0; j < n_rows; j++){ if (binvA[j+n_cols]) { printf("(%d %g), ", j+n_cols, binvA[j+n_cols]); } } } printf("\n"); printf("And by column (trickier)"); const int * pivotVariable = model.pivotVariable(); for( i = 0; i < n_cols+n_rows; i++){ model.getBInvACol(i, binvA); printf("\ncolumn: %d -> ",i); for(int j=0; j < n_rows; j++){ if (binvA[j]) { // need to know pivot variable for +1/-1 (slack) and row/column scaling int pivot = pivotVariable[j]; if (pivot ",i); int j; for (j=0;j ",i); int j; for (j=0;jmaximumPivots(1); //solution.setLogLevel(3); solution.setDualTolerance(1.0e-7); // set objective sense, ClpDualRowSteepest steep; solution.setDualRowPivotAlgorithm(steep); solution.setDblParam(ClpObjOffset,m.objectiveOffset()); solution.dual(); } // test normal solution { CoinMpsIO m; std::string fn = dirSample+"afiro"; m.readMps(fn.c_str(),"mps"); ClpSimplex solution; ClpModel model; // do twice - without and with scaling int iPass; for (iPass=0;iPass<2;iPass++) { // explicit row objective for testing int nr = m.getNumRows(); double * rowObj = new double[nr]; CoinFillN(rowObj,nr,0.0); model.loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(), m.getObjCoefficients(), m.getRowLower(),m.getRowUpper(),rowObj); delete [] rowObj; solution = ClpSimplex(model); if (iPass) { solution.scaling(); } solution.dual(); solution.dual(); // test optimal assert (solution.status()==0); int numberColumns = solution.numberColumns(); int numberRows = solution.numberRows(); CoinPackedVector colsol(numberColumns,solution.primalColumnSolution()); double * objective = solution.objective(); double objValue = colsol.dotProduct(objective); CoinRelFltEq eq(1.0e-8); assert(eq(objValue,-4.6475314286e+02)); // Test auxiliary model //solution.scaling(0); solution.auxiliaryModel(63-2); // bounds may change solution.dual(); solution.primal(); solution.allSlackBasis(); solution.dual(); assert(eq(solution.objectiveValue(),-4.6475314286e+02)); solution.auxiliaryModel(-1); solution.dual(); assert(eq(solution.objectiveValue(),-4.6475314286e+02)); double * lower = solution.columnLower(); double * upper = solution.columnUpper(); double * sol = solution.primalColumnSolution(); double * result = new double[numberColumns]; CoinFillN ( result, numberColumns,0.0); solution.matrix()->transposeTimes(solution.dualRowSolution(), result); int iRow , iColumn; // see if feasible and dual feasible for (iColumn=0;iColumnlower[iColumn]-1.0e-8); value = objective[iColumn]-result[iColumn]; assert (value>-1.0e-5); if (sol[iColumn]>1.0e-5) assert (value<1.0e-5); } delete [] result; result = new double[numberRows]; CoinFillN ( result, numberRows,0.0); solution.matrix()->times(colsol, result); lower = solution.rowLower(); upper = solution.rowUpper(); sol = solution.primalRowSolution(); for (iRow=0;iRowlower[iRow]-1.0e-8); } delete [] result; // test row objective double * rowObjective = solution.rowObjective(); CoinDisjointCopyN(solution.dualRowSolution(),numberRows,rowObjective); CoinDisjointCopyN(solution.dualColumnSolution(),numberColumns,objective); // this sets up all slack basis solution.createStatus(); solution.dual(); CoinFillN(rowObjective,numberRows,0.0); CoinDisjointCopyN(m.getObjCoefficients(),numberColumns,objective); solution.dual(); } } // test unbounded { CoinMpsIO m; std::string fn = dirSample+"brandy"; m.readMps(fn.c_str(),"mps"); ClpSimplex solution; // do twice - without and with scaling int iPass; for (iPass=0;iPass<2;iPass++) { solution.loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(), m.getObjCoefficients(), m.getRowLower(),m.getRowUpper()); if (iPass) solution.scaling(); solution.setOptimizationDirection(-1); // test unbounded and ray #ifdef DUAL solution.setDualBound(100.0); solution.dual(); #else solution.primal(); #endif assert (solution.status()==2); int numberColumns = solution.numberColumns(); int numberRows = solution.numberRows(); double * lower = solution.columnLower(); double * upper = solution.columnUpper(); double * sol = solution.primalColumnSolution(); double * ray = solution.unboundedRay(); double * objective = solution.objective(); double objChange=0.0; int iRow , iColumn; // make sure feasible and columns form ray for (iColumn=0;iColumnlower[iColumn]-1.0e-8); value = ray[iColumn]; if (value>0.0) assert(upper[iColumn]>1.0e30); else if (value<0.0) assert(lower[iColumn]<-1.0e30); objChange += value*objective[iColumn]; } // make sure increasing objective assert(objChange>0.0); double * result = new double[numberRows]; CoinFillN ( result, numberRows,0.0); solution.matrix()->times(sol, result); lower = solution.rowLower(); upper = solution.rowUpper(); sol = solution.primalRowSolution(); for (iRow=0;iRowlower[iRow]-2.0e-8); } CoinFillN ( result, numberRows,0.0); solution.matrix()->times(ray, result); // there may be small differences (especially if scaled) for (iRow=0;iRow1.0e-8) assert(upper[iRow]>1.0e30); else if (value<-1.0e-8) assert(lower[iRow]<-1.0e30); } delete [] result; delete [] ray; } } // test infeasible { CoinMpsIO m; std::string fn = dirSample+"brandy"; m.readMps(fn.c_str(),"mps"); ClpSimplex solution; // do twice - without and with scaling int iPass; for (iPass=0;iPass<2;iPass++) { solution.loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(), m.getObjCoefficients(), m.getRowLower(),m.getRowUpper()); if (iPass) solution.scaling(); // test infeasible and ray solution.columnUpper()[0]=0.0; #ifdef DUAL solution.setDualBound(100.0); solution.dual(); #else solution.primal(); #endif assert (solution.status()==1); int numberColumns = solution.numberColumns(); int numberRows = solution.numberRows(); double * lower = solution.rowLower(); double * upper = solution.rowUpper(); double * ray = solution.infeasibilityRay(); assert(ray); // construct proof of infeasibility int iRow , iColumn; double lo=0.0,up=0.0; int nl=0,nu=0; for (iRow=0;iRow-1.0e20) { lo += ray[iRow]*lower[iRow]; } else { if (ray[iRow]>1.0e-8) nl++; } if (upper[iRow]<1.0e20) { up += ray[iRow]*upper[iRow]; } else { if (ray[iRow]>1.0e-8) nu++; } } if (nl) lo=-1.0e100; if (nu) up=1.0e100; double * result = new double[numberColumns]; double lo2=0.0,up2=0.0; CoinFillN ( result, numberColumns,0.0); solution.matrix()->transposeTimes(ray, result); lower = solution.columnLower(); upper = solution.columnUpper(); nl=nu=0; for (iColumn=0;iColumn1.0e-8) { if (lower[iColumn]>-1.0e20) lo2 += result[iColumn]*lower[iColumn]; else nl++; if (upper[iColumn]<1.0e20) up2 += result[iColumn]*upper[iColumn]; else nu++; } else if (result[iColumn]<-1.0e-8) { if (lower[iColumn]>-1.0e20) up2 += result[iColumn]*lower[iColumn]; else nu++; if (upper[iColumn]<1.0e20) lo2 += result[iColumn]*upper[iColumn]; else nl++; } } if (nl) lo2=-1.0e100; if (nu) up2=1.0e100; // make sure inconsistency assert(lo2>up||up2getNumElements(); int * starts = new int[numberRows+numberColumns]; int * index = new int[numberElements]; double * element = new double[numberElements]; const CoinBigIndex * startM; const int * lengthM; const int * indexM; const double * elementM; int n,nel; // delete non basic columns n=0; nel=0; int iRow , iColumn; const double * lower = m.getColLower(); const double * upper = m.getColUpper(); const double * objective = m.getObjCoefficients(); startM = m.getMatrixByCol()->getVectorStarts(); lengthM = m.getMatrixByCol()->getVectorLengths(); indexM = m.getMatrixByCol()->getIndices(); elementM = m.getMatrixByCol()->getElements(); starts[0]=0; for (iColumn=0;iColumngetVectorStarts(); lengthM = m.getMatrixByRow()->getVectorLengths(); indexM = m.getMatrixByRow()->getIndices(); elementM = m.getMatrixByRow()->getElements(); starts[0]=0; for (iRow=0;iRowmaximumPivots(200+model.numberRows()/100); model.createStatus(); double time1 = CoinCpuTime(); model.dual(); std::cout<<"Network problem, ClpPackedMatrix took "<getIndices()); // would be zero if not +- one //ClpPlusMinusOneMatrix *plusminus_matrix; //plusminus_matrix = new ClpPlusMinusOneMatrix; //plusminus_matrix->passInCopy(numberRows, numberColumns, true, plusMinus->getMutableIndices(), // plusMinus->startPositive(),plusMinus->startNegative()); model.loadProblem(*plusMinus, lowerColumn,upperColumn,objective, lower,upper); //model.replaceMatrix( plusminus_matrix , true); delete plusMinus; //model.createStatus(); //model.initialSolve(); //model.writeMps("xx.mps"); model.factorization()->maximumPivots(200+model.numberRows()/100); model.createStatus(); time1 = CoinCpuTime(); model.dual(); std::cout<<"Network problem, ClpPlusMinusOneMatrix took "<maximumPivots(200+model.numberRows()/100); model.createStatus(); time1 = CoinCpuTime(); model.dual(); std::cout<<"Network problem, ClpNetworkMatrix took "<=kk) { column[n]=i; if (i>=kk2) element[n]=1.0e-1; else element[n]=0.0; n++; } start[i+1]=n; } // Load up objective solution.loadQuadraticObjective(numberColumns,start,column,element); delete [] start; delete [] column; delete [] element; //solution.quadraticSLP(50,1.0e-4); CoinRelFltEq eq(1.0e-4); //assert(eq(objValue,820.0)); //solution.setLogLevel(63); solution.primal(); printSol(solution); //assert(eq(objValue,3.2368421)); //exit(77); } // Test quadratic if (1) { CoinMpsIO m; std::string fn = dirSample+"share2qp"; //fn = "share2qpb"; m.readMps(fn.c_str(),"mps"); ClpSimplex model; model.loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(), m.getObjCoefficients(), m.getRowLower(),m.getRowUpper()); model.dual(); // get quadratic part int * start=NULL; int * column = NULL; double * element = NULL; m.readQuadraticMps(NULL,start,column,element,2); int column2[200]; double element2[200]; int start2[80]; int j; start2[0]=0; int nel=0; bool good=false; for (j=0;j<79;j++) { if (start[j]==start[j+1]) { column2[nel]=j; element2[nel]=0.0; nel++; } else { int i; for (i=start[j];iclone(); ClpLinearObjective zeroObjective(NULL,numberColumns); model.setObjective(&zeroObjective); model.dual(); model.setObjective(saveObjective); delete saveObjective; #endif //model.setLogLevel(63); //exit(77); model.setFactorizationFrequency(10); model.primal(); printSol(model); double objValue = model.getObjValue(); CoinRelFltEq eq(1.0e-4); assert(eq(objValue,-400.92)); // and again for barrier model.barrier(false); //printSol(model); model.allSlackBasis(); model.primal(); //printSol(model); } if (0) { CoinMpsIO m; std::string fn = "./beale"; //fn = "./jensen"; m.readMps(fn.c_str(),"mps"); ClpSimplex solution; solution.loadProblem(*m.getMatrixByCol(),m.getColLower(),m.getColUpper(), m.getObjCoefficients(), m.getRowLower(),m.getRowUpper()); solution.setDblParam(ClpObjOffset,m.objectiveOffset()); solution.dual(); // get quadratic part int * start=NULL; int * column = NULL; double * element = NULL; m.readQuadraticMps(NULL,start,column,element,2); // Load up objective solution.loadQuadraticObjective(solution.numberColumns(),start,column,element); delete [] start; delete [] column; delete [] element; solution.primal(1); solution.nonlinearSLP(50,1.0e-4); double objValue = solution.getObjValue(); CoinRelFltEq eq(1.0e-4); assert(eq(objValue,0.5)); solution.primal(); objValue = solution.getObjValue(); assert(eq(objValue,0.5)); } #endif }