Skip to content

Commit

Permalink
Add option to disable dual reductions for Clp via C Interface (#630)
Browse files Browse the repository at this point in the history
* Add option to disable dual reductions for Clp

* add missing argument in Cbc_solve initialization

* change how we pass the reduction flag

- add a method for disabling dual reductions to Cbc_Model
- Remove reduction type argument from Cbc_solve and Cbc_solveLinearProgram
- Change logic in Cbc_solveLinearProgram to depend on the value of the red_type parameter in Cbc_Model

* Change function name to Cbc_setDualReductionsType

- Add getter function

* Add simple test for LP dual reduction type
  • Loading branch information
patrickvossler18 authored Mar 17, 2024
1 parent eee5e3f commit 52a59a7
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 9 deletions.
22 changes: 21 additions & 1 deletion src/Cbc_C_Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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_;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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) {
Expand Down
36 changes: 28 additions & 8 deletions src/Cbc_C_Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* */
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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. */
Expand Down
94 changes: 94 additions & 0 deletions test/CInterfaceTest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -1115,5 +1205,9 @@ int main() {
testTSPUlysses22( 1 );
testTSPUlysses22( 0 );

printf("Dual reduction type test\n");
testDualReductionsType(LPR_Default);
testDualReductionsType(LPR_NoDualReds);

return 0;
}

0 comments on commit 52a59a7

Please sign in to comment.