diff --git a/src/Cbc_C_Interface.cpp b/src/Cbc_C_Interface.cpp index 77dd90f4e..cdaec46d7 100644 --- a/src/Cbc_C_Interface.cpp +++ b/src/Cbc_C_Interface.cpp @@ -261,6 +261,7 @@ struct Cbc_Model { // parameters enum LPMethod lp_method; enum DualPivot dualp; + enum LPReductions red_type = LPR_Default; // lazy constraints CglStored *lazyConstrs; @@ -1763,7 +1764,7 @@ static void Cbc_addAllSOS( Cbc_Model *model, CbcModel &cbcModel ); static void Cbc_addMS( Cbc_Model *model, CbcModel &cbcModel ); int CBC_LINKAGE -Cbc_solveLinearProgram(Cbc_Model *model) +Cbc_solveLinearProgram(Cbc_Model *model) { Cbc_flush( model ); OsiClpSolverInterface *solver = model->solver_; @@ -1909,6 +1910,10 @@ Cbc_solveLinearProgram(Cbc_Model *model) /* for integer or linear optimization starting with LP relaxation */ ClpSolve clpOptions; + if (model->red_type == LPR_NoDualReds){ + // set special option in Clp to disable dual reductions + clpOptions.setSpecialOption(5, 1); + } char methodName[256] = ""; switch (model->lp_method) { case LPM_Auto: @@ -4745,6 +4750,21 @@ Cbc_setLPmethod(Cbc_Model *model, enum LPMethod lpm ) { model->lp_method = lpm; } +/** gets the dual reductions to be used when solving the LP + */ +double CBC_LINKAGE +Cbc_getDualReductionsType(Cbc_Model *model){ + return model->red_type; +} + +/** sets the dual reductions to be used when solving the LP + */ + +void CBC_LINKAGE +Cbc_setDualReductionsType(Cbc_Model *model, enum LPReductions red) { + model->red_type = red; +} + void * CBC_LINKAGE Cbc_getSolverPtr(Cbc_Model *model) { diff --git a/src/Cbc_C_Interface.h b/src/Cbc_C_Interface.h index 67cf5744c..f3c8afd11 100644 --- a/src/Cbc_C_Interface.h +++ b/src/Cbc_C_Interface.h @@ -53,6 +53,13 @@ enum LPMethod { LPM_BarrierNoCross = 4 /*! Barrier algorithm, not to be followed by crossover */ }; +/*! Whether specific presolve reductions should be disabled + * */ +enum LPReductions { + LPR_Default = 0, /*! Solver will use default presolve transformations */ + LPR_NoDualReds = 1 /*! Dual reduction transformation will be disabled */ +}; + /*! Selects the pivot selection strategy to be used * in the dual simplex algorithm. * */ @@ -1079,6 +1086,18 @@ Cbc_setCutoff(Cbc_Model *model, double cutoff); CBCLIB_EXPORT void CBC_LINKAGE Cbc_setLPmethod(Cbc_Model *model, enum LPMethod lpm ); +/** + * gets type of dual reductions to use when solving the LP +*/ +CBCLIB_EXPORT double CBC_LINKAGE +Cbc_getDualReductionsType(Cbc_Model *model); + +/** + * sets whether not to use dual reductions when solving the LP +*/ +CBCLIB_EXPORT void CBC_LINKAGE +Cbc_setDualReductionsType(Cbc_Model *model, enum LPReductions red); + /** Returns a pointer to the OsiClpSolverInterface object * containing the problem */ @@ -1153,18 +1172,19 @@ CBCLIB_EXPORT int CBC_LINKAGE Cbc_solve(Cbc_Model *model); /** @brief Solves only the linear programming relaxation - * - * @param model problem object - * @return execution status - * 0 optimal - * 1 incomplete search (stopped on time, iterations) - * 2 infeasible - * 3 unbounded - **/ + * + * @param model problem object + * @return execution status + * 0 optimal + * 1 incomplete search (stopped on time, iterations) + * 2 infeasible + * 3 unbounded + **/ CBCLIB_EXPORT int CBC_LINKAGE Cbc_solveLinearProgram(Cbc_Model *model); + /** @brief This is a pre-processing that tries to * strengthen set packing constraints. Dominated constraints are * removed. */ diff --git a/test/CInterfaceTest.c b/test/CInterfaceTest.c index ad3006d58..c6e1556ce 100644 --- a/test/CInterfaceTest.c +++ b/test/CInterfaceTest.c @@ -1083,6 +1083,96 @@ void testTSPUlysses22( char lazy ) { Cbc_deleteModel(m); } +void testDualReductionsType( enum LPReductions red ){ + Cbc_Model *model = Cbc_newModel(); + + /* Simple knapsack problem + Maximize 5x[1] + 3x[2] + 2x[3] + 7x[4] + 4x[5] + s.t. 2x[1] + 8x[2] + 4x[3] + 2x[4] + 5x[5] <= 10 + All x binary + */ + + CoinBigIndex start[] = {0, 1, 2, 3, 4, 5, 6}; + int rowindex[] = {0, 0, 0, 0, 0}; + double value[] = {2, 8, 4, 2, 5}; + double collb[] = {0,0,0,0,0}; + double colub[] = {1,1,1,1,1}; + double obj[] = {5, 3, 2, 7, 4}; + double feasible[] = {1,1,0,0,0}; + double rowlb[] = {-INFINITY}; + double rowub[] = {10}; + const double *sol; + const char* setname = "test model"; + char *getname = malloc(20); + int i; + + printf("Interface reports Cbc version %s\n", Cbc_getVersion()); + + Cbc_loadProblem(model, 5, 1, start, rowindex, value, collb, colub, obj, rowlb, rowub); + + Cbc_setColName(model, 2, "var2"); + Cbc_setRowName(model, 0, "constr0"); + + + assert(Cbc_getNumCols(model) == 5); + assert(Cbc_getNumRows(model) == 1); + + for (i = 0; i < 5; i++) { + Cbc_setInteger(model, i); + assert(Cbc_isInteger(model,i)); + } + + Cbc_setObjSense(model, -1); + assert(Cbc_getObjSense(model) == -1); + + Cbc_setProblemName(model, setname); + + Cbc_registerCallBack(model, test_callback); + + Cbc_setInitialSolution(model, feasible); + + Cbc_setDualReductionsType(model, red); + + assert(Cbc_getDualReductionsType(model) == red); + + Cbc_solve(model); + + assert(Cbc_isProvenOptimal(model)); + assert(!Cbc_isAbandoned(model)); + assert(!Cbc_isProvenInfeasible(model)); + assert(!Cbc_isContinuousUnbounded(model)); + assert(!Cbc_isNodeLimitReached(model)); + assert(!Cbc_isSecondsLimitReached(model)); + assert(!Cbc_isSolutionLimitReached(model)); + assert(fabs(Cbc_getObjValue(model)- (16.0)) < 1e-6); + assert(fabs(Cbc_getBestPossibleObjValue(model)- 16.0) < 1e-6); + + assert(callback_called == 1); + + sol = Cbc_getColSolution(model); + + assert(fabs(sol[0] - 1.0) < 1e-6); + assert(fabs(sol[1] - 0.0) < 1e-6); + assert(fabs(sol[2] - 0.0) < 1e-6); + assert(fabs(sol[3] - 1.0) < 1e-6); + assert(fabs(sol[4] - 1.0) < 1e-6); + + Cbc_problemName(model, 20, getname); + i = strcmp(getname,setname); + assert( (i == 0) ); + + Cbc_getColName(model, 2, getname, 20); + i = strcmp(getname, "var2"); + assert( (i == 0) ); + Cbc_getRowName(model, 0, getname, 20); + i = strcmp(getname, "constr0"); + assert( (i == 0) ); + assert( Cbc_maxNameLength(model) >= 7 ); + + Cbc_deleteModel(model); + free(getname); +} + int main() { printf("\nStarting C Interface test.\n\n"); char buildInfo[1024]; @@ -1115,5 +1205,9 @@ int main() { testTSPUlysses22( 1 ); testTSPUlysses22( 0 ); + printf("Dual reduction type test\n"); + testDualReductionsType(LPR_Default); + testDualReductionsType(LPR_NoDualReds); + return 0; }