int CPXPUBLIC CPX_CutCallback(CPXCENVptr xenv, void *cbdata, int wherefrom, void *cbhandle, int *useraction_p) { // cout << "Entering CPX Callback\n" << flush; CPXLPptr nodelp; CPXgetcallbacknodelp(xenv, cbdata, wherefrom, &nodelp); CoinCallbacks* ccc = (CoinCallbacks*)cbhandle; int length = CPXgetnumcols(xenv,nodelp) - 1; //hey, don't ask me! some VERY WIERD PHENOMENON... crap double objVal; double* solution = new double[length]; CPXgetcallbacknodeobjval(xenv, cbdata, wherefrom, &objVal); CPXgetcallbacknodex(xenv, cbdata, wherefrom, solution, 0, length-1); OsiCuts* cuts = new OsiCuts(); CoinCallbacks::CutReturn ret = ccc->cutCallback(objVal, solution, cuts); if(ret == CoinCallbacks::CR_AddCuts) { for(int i = cuts->sizeRowCuts(); i-->0;) { const OsiRowCut& c = cuts->rowCut(i); const CoinPackedVector& vec = c.row(); if(c.globallyValid()) /* Old Cplex-Versions did NOT have the last parameter (now set to "false"). * If you compile agains an older CPLEX version, simple *REMOVE* * ", false" * from the calls to CPXcutscallbackadd */ CPXcutcallbackadd(xenv, cbdata, wherefrom, vec.getNumElements(), c.rhs(), c.sense(), vec.getIndices(), vec.getElements(), false); //default to non-purgable cuts else CPXcutcallbackaddlocal(xenv, cbdata, wherefrom, vec.getNumElements(), c.rhs(), c.sense(), vec.getIndices(), vec.getElements()); cuts->eraseRowCut(i); } if(cuts->sizeColCuts() > 0) { cerr << "ColCuts currently not supported...\n"; OGDF_THROW_PARAM(LibraryNotSupportedException, lnscFunctionNotImplemented); } } *useraction_p = ( ret == CoinCallbacks::CR_Error) ? CPX_CALLBACK_FAIL : ( ret == CoinCallbacks::CR_AddCuts ) ? CPX_CALLBACK_SET : CPX_CALLBACK_DEFAULT; delete cuts; delete[] solution; // cout << "Leaving CPX Callback\n" << flush; return 0; // success }
static int CPXPUBLIC usersetbranch (CPXCENVptr env, void *cbdata, int wherefrom, void *userinfo, int brtype, int sos, int nodecnt, int bdcnt, const int *nodebeg, const int *idx, const char *lu, const double *bd, const double *nodeest, int *useraction_p) { int status = 0; int isfeas; int i, j, k, l; int besti = -1; int bestj = -1; int bestk = -1; int cols; int sossize, numsos; double maxfrac = 0.0; double xj_frac; double objval; double epint; double *x = NULL; int bdsz; int *varind = NULL; char *varlu = NULL; double *varbd = NULL; int seqnum; CPXCLPptr lp; /* Initialize useraction to indicate no user action taken */ *useraction_p = CPX_CALLBACK_DEFAULT; /* If CPLEX is choosing an ordinary branch, take it */ if ( sos < 0 ) goto TERMINATE; /* Get pointer to the problem */ status = CPXgetcallbacklp (env, cbdata, wherefrom, &lp); if ( status ) { fprintf (stdout, "Can't get LP pointer.\n"); goto TERMINATE; } cols = CPXgetnumcols (env, lp); if ( cols <= 0 ) { fprintf (stdout, "Can't number of columns.\n"); status = CPXERR_CALLBACK; goto TERMINATE; } /* Get solution values and objective coefficients */ x = (double *) malloc (cols * sizeof (double)); if ( x == NULL ) { fprintf (stdout, "Out of memory."); goto TERMINATE; } status = CPXgetcallbacknodex (env, cbdata, wherefrom, x, 0, cols-1); if ( status ) { fprintf (stdout, "Can't get node solution."); goto TERMINATE; } status = CPXgetcallbacknodeobjval (env, cbdata, wherefrom, &objval); if ( status ) { fprintf (stdout, "Can't get node objective value."); goto TERMINATE; } status = CPXgetcallbacksosinfo (env, cbdata, wherefrom, 0, 0, CPX_CALLBACK_INFO_SOS_NUM, &numsos); if ( status ) goto TERMINATE; /* Branch on the set that has the variable closest to 1 */ status = CPXgetdblparam (env, CPXPARAM_MIP_Tolerances_Integrality, &epint); for (i = 0; i < numsos; i++) { /* Check if the set is feasible */ status = CPXgetcallbacksosinfo (env, cbdata, wherefrom, i, 0, CPX_CALLBACK_INFO_SOS_IS_FEASIBLE, &isfeas); if ( status ) goto TERMINATE; /* Find variable with largest fraction in each infeasible set. Select a set with largest largest fraction for branching */ if ( !isfeas ) { status = CPXgetcallbacksosinfo (env, cbdata, wherefrom, i, 0, CPX_CALLBACK_INFO_SOS_SIZE, &sossize); if ( status ) goto TERMINATE; for (k = 0; k < sossize; k++) { status = CPXgetcallbacksosinfo (env, cbdata, wherefrom, i, k, CPX_CALLBACK_INFO_SOS_MEMBER_INDEX, &j); if ( status ) goto TERMINATE; xj_frac = x[j] - floor (x[j] + epint); if ( xj_frac > maxfrac ) { bestj = j; bestk = k; besti = i; maxfrac = xj_frac; } } } } if ( bestj < 0 ) { status = CPX_CALLBACK_DEFAULT; goto TERMINATE; } /* Now set up node descriptions */ /* Check that arrays are big enough; if not, return, requesting more space */ status = CPXgetcallbacksosinfo (env, cbdata, wherefrom, besti, 0, CPX_CALLBACK_INFO_SOS_SIZE, &sossize); if ( status ) goto TERMINATE; bdsz = sossize + 1; varind = (int *) malloc (bdsz*sizeof(int)); varlu = (char *) malloc (bdsz*sizeof(char)); varbd = (double *) malloc (bdsz*sizeof(double)); if ( varind == NULL || varlu == NULL || varbd == NULL ) { status = CPXERR_NO_MEMORY; goto TERMINATE; } /* Create two nodes, one setting all but the selected variable to 0 and the selected variable to 1, the other setting the selected variable to 0 */ /* First node */ for (k = 0, l = 0; k < sossize; k++) { status = CPXgetcallbacksosinfo (env, cbdata, wherefrom, besti, k, CPX_CALLBACK_INFO_SOS_MEMBER_INDEX, &j); if ( status ) goto TERMINATE; if ( k != bestk ) { varind[l] = j; varlu[l] = 'U'; varbd[l] = 0.; l++; } else { varind[l] = j; varlu[l] = 'L'; varbd[l] = 1.; l++; } } status = CPXbranchcallbackbranchbds (env, cbdata, wherefrom, l, varind, varlu, varbd, objval, NULL, &seqnum); if ( status ) goto TERMINATE; /* Second node */ varind[0] = bestj; varlu[0] = 'U'; varbd[0] = 0.; status = CPXbranchcallbackbranchbds (env, cbdata, wherefrom, 1, varind, varlu, varbd, objval, NULL, &seqnum); if ( status ) goto TERMINATE; *useraction_p = CPX_CALLBACK_SET; TERMINATE: free_and_null ((char **) &x); free_and_null ((char **) &varind); free_and_null ((char **) &varlu); free_and_null ((char **) &varbd); return (status); } /* END usersetbranch */
static int CPXPUBLIC usersetbranch (CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle, int brtype, int sos, int nodecnt, int bdcnt, const int *nodebeg, const int *indices, const char *lu, const double *bd, const double *nodeest, int *useraction_p) { int status = 0; int j, bestj = -1; int cols; double maxobj = -CPX_INFBOUND; double maxinf = -CPX_INFBOUND; double xj_inf; double xj_lo; double objval; double *x = NULL; double *obj = NULL; int *feas = NULL; char varlu[1]; double varbd[1]; int seqnum1, seqnum2; CPXCLPptr lp; /* Initialize useraction to indicate no user action taken */ *useraction_p = CPX_CALLBACK_DEFAULT; /* If CPLEX is choosing an SOS branch, take it */ if ( sos >= 0 ) return (status); /* Get pointer to the problem */ status = CPXgetcallbacklp (env, cbdata, wherefrom, &lp); if ( status ) { fprintf (stdout, "Can't get LP pointer.\n"); goto TERMINATE; } cols = CPXgetnumcols (env, lp); if ( cols <= 0 ) { fprintf (stdout, "Can't get number of columns.\n"); status = CPXERR_CALLBACK; goto TERMINATE; } /* Get solution values and objective coefficients */ x = (double *) malloc (cols * sizeof (double)); obj = (double *) malloc (cols * sizeof (double)); feas = (int *) malloc (cols * sizeof (int)); if ( x == NULL || obj == NULL || feas == NULL ) { fprintf (stdout, "Out of memory."); status = CPXERR_CALLBACK; goto TERMINATE; } status = CPXgetcallbacknodex (env, cbdata, wherefrom, x, 0, cols-1); if ( status ) { fprintf (stdout, "Can't get node solution."); goto TERMINATE; } status = CPXgetcallbacknodeobjval (env, cbdata, wherefrom, &objval); if ( status ) { fprintf (stdout, "Can't get node objective value."); goto TERMINATE; } status = CPXgetobj (env, lp, obj, 0, cols-1); if ( status ) { fprintf (stdout, "Can't get obj."); goto TERMINATE; } status = CPXgetcallbacknodeintfeas (env, cbdata, wherefrom, feas, 0, cols-1); if ( status ) { fprintf (stdout, "Can't get variable feasible status for node."); goto TERMINATE; } /* Branch on var with largest objective coefficient among those with largest infeasibility */ for (j = 0; j < cols; j++) { if ( feas[j] == CPX_INTEGER_INFEASIBLE ) { xj_inf = x[j] - floor (x[j]); if ( xj_inf > 0.5 ) xj_inf = 1.0 - xj_inf; if ( xj_inf >= maxinf && (xj_inf > maxinf || fabs (obj[j]) >= maxobj) ) { bestj = j; maxinf = xj_inf; maxobj = fabs (obj[j]); } } } /* If there weren't any eligible variables, take default branch */ if ( bestj < 0 ) { goto TERMINATE; } /* Now set up node descriptions */ xj_lo = floor (x[bestj]); /* Up node */ varlu[0] = 'L'; varbd[0] = xj_lo + 1; status = CPXbranchcallbackbranchbds (env, cbdata, wherefrom, 1, &bestj, varlu, varbd, objval, NULL, &seqnum1); if ( status ) goto TERMINATE; /* Down node */ varlu[0] = 'U'; varbd[0] = xj_lo; status = CPXbranchcallbackbranchbds (env, cbdata, wherefrom, 1, &bestj, varlu, varbd, objval, NULL, &seqnum2); if ( status ) goto TERMINATE; /* Set useraction to indicate a user-specified branch */ *useraction_p = CPX_CALLBACK_SET; TERMINATE: free_and_null ((char **) &x); free_and_null ((char **) &obj); free_and_null ((char **) &feas); return (status); } /* END usersetbranch */