/** initialization method of event handler (called after problem was transformed) */ static SCIP_DECL_EVENTINIT(eventInitBoundwriting) { /*lint --e{715}*/ SCIP_EVENTHDLRDATA* eventhdlrdata; assert(scip != NULL); assert(eventhdlr != NULL); assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0); /* notify SCIP that your event handler wants to react on the event type best solution found */ SCIP_CALL( SCIPcatchEvent(scip, SCIP_EVENTTYPE_NODESOLVED, eventhdlr, NULL, NULL) ); eventhdlrdata = SCIPeventhdlrGetData(eventhdlr); assert(eventhdlrdata != NULL); eventhdlrdata->lastpb = SCIPinfinity(scip) * (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ? 1.0 : -1.0); return SCIP_OKAY; }
/** returns whether the debug solution is worse as the best known solution or if the debug solution was found */ static SCIP_Bool debugSolIsAchieved( SCIP_SET* set /**< global SCIP settings */ ) { SCIP_SOL* bestsol; SCIP* scip; if( solisachieved ) return TRUE; assert(set != NULL); scip = set->scip; assert(scip != NULL); bestsol = SCIPgetBestSol(scip); if( bestsol != NULL ) { SCIP_Real solvalue; /* don't check solution while in problem creation stage */ if( SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM ) return TRUE; solvalue = SCIPgetSolOrigObj(scip, bestsol); /* make sure a debug solution has been read, so we do not compare against the initial debugsolval == 0 */ SCIP_CALL( readSolution(set) ); if( (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE && SCIPsetIsLE(set, solvalue, debugsolval)) || (SCIPgetObjsense(scip) == SCIP_OBJSENSE_MAXIMIZE && SCIPsetIsGE(set, solvalue, debugsolval)) ) solisachieved = TRUE; } return solisachieved; }
/** creates the objective value inequality and the objective value variable, if not yet existing */ static SCIP_RETCODE createObjRow( SCIP* scip, /**< SCIP data structure */ SCIP_SEPA* sepa, /**< separator */ SCIP_SEPADATA* sepadata /**< separator data */ ) { assert(sepadata != NULL); if( sepadata->objrow == NULL ) { SCIP_VAR** vars; SCIP_Real obj; SCIP_Real intobjval; int nvars; int v; SCIP_Bool attendobjvarbound; attendobjvarbound = FALSE; /* create and add objective value variable */ if( sepadata->objvar == NULL ) { SCIP_CALL( SCIPcreateVar(scip, &sepadata->objvar, "objvar", -SCIPinfinity(scip), SCIPinfinity(scip), 0.0, SCIP_VARTYPE_IMPLINT, FALSE, TRUE, NULL, NULL, NULL, NULL, NULL) ); SCIP_CALL( SCIPaddVar(scip, sepadata->objvar) ); SCIP_CALL( SCIPaddVarLocks(scip, sepadata->objvar, +1, +1) ); } else attendobjvarbound = TRUE; /* get problem variables */ vars = SCIPgetOrigVars(scip); nvars = SCIPgetNOrigVars(scip); /* create objective value inequality */ if( SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ) { if( attendobjvarbound ) intobjval = SCIPceil(scip, SCIPgetDualbound(scip)) - SCIPvarGetLbGlobal(sepadata->objvar); else intobjval = SCIPceil(scip, SCIPgetDualbound(scip)); SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &sepadata->objrow, sepa, "objrow", intobjval, SCIPinfinity(scip), FALSE, !SCIPallVarsInProb(scip), TRUE) ); sepadata->setoff = intobjval; } else { if( attendobjvarbound ) intobjval = SCIPceil(scip, SCIPgetDualbound(scip)) - SCIPvarGetUbGlobal(sepadata->objvar); else intobjval = SCIPfloor(scip, SCIPgetDualbound(scip)); SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &sepadata->objrow, sepa, "objrow", -SCIPinfinity(scip), intobjval, FALSE, !SCIPallVarsInProb(scip), TRUE) ); sepadata->setoff = intobjval; } SCIP_CALL( SCIPcacheRowExtensions(scip, sepadata->objrow) ); for( v = 0; v < nvars; ++v ) { obj = SCIPvarGetObj(vars[v]); if( !SCIPisZero(scip, obj) ) { SCIP_CALL( SCIPaddVarToRow(scip, sepadata->objrow, vars[v], obj) ); } } SCIP_CALL( SCIPaddVarToRow(scip, sepadata->objrow, sepadata->objvar, -1.0) ); SCIP_CALL( SCIPflushRowExtensions(scip, sepadata->objrow) ); SCIPdebugMessage("created objective value row: "); SCIPdebug( SCIP_CALL( SCIPprintRow(scip, sepadata->objrow, NULL) ) ); } return SCIP_OKAY; }
/** searches and adds integral objective cuts that separate the given primal solution */ static SCIP_RETCODE separateCuts( SCIP* scip, /**< SCIP data structure */ SCIP_SEPA* sepa, /**< the intobj separator */ SCIP_SOL* sol, /**< the solution that should be separated, or NULL for LP solution */ SCIP_RESULT* result /**< pointer to store the result */ ) { SCIP_SEPADATA* sepadata; SCIP_Real objval; SCIP_Real intbound; SCIP_Bool infeasible; SCIP_Bool tightened; assert(result != NULL); assert(*result == SCIP_DIDNOTRUN); /* if the objective value may be fractional, we cannot do anything */ if( !SCIPisObjIntegral(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; /* if the current objective value is integral, there is no integral objective value cut */ if( sol == NULL ) objval = SCIPretransformObj(scip, SCIPgetLPObjval(scip)); else objval = SCIPgetSolOrigObj(scip, sol); if( SCIPisFeasIntegral(scip, objval) ) return SCIP_OKAY; sepadata = SCIPsepaGetData(sepa); assert(sepadata != NULL); /* the objective value is fractional: create the objective value inequality, if not yet existing */ SCIP_CALL( createObjRow(scip, sepa, sepadata) ); /* adjust the bounds of the objective value variable */ if( SCIPgetObjsense(scip) == SCIP_OBJSENSE_MINIMIZE ) { intbound = SCIPceil(scip, objval) - sepadata->setoff; SCIP_CALL( SCIPtightenVarLb(scip, sepadata->objvar, intbound, FALSE, &infeasible, &tightened) ); SCIPdebugMessage("new objective variable lower bound: <%s>[%g,%g]\n", SCIPvarGetName(sepadata->objvar), SCIPvarGetLbLocal(sepadata->objvar), SCIPvarGetUbLocal(sepadata->objvar)); } else { intbound = SCIPfloor(scip, objval) - sepadata->setoff; SCIP_CALL( SCIPtightenVarUb(scip, sepadata->objvar, intbound, FALSE, &infeasible, &tightened) ); SCIPdebugMessage("new objective variable upper bound: <%s>[%g,%g]\n", SCIPvarGetName(sepadata->objvar), SCIPvarGetLbLocal(sepadata->objvar), SCIPvarGetUbLocal(sepadata->objvar)); } /* add the objective value inequality as a cut to the LP */ if( infeasible ) *result = SCIP_CUTOFF; else { if( !SCIProwIsInLP(sepadata->objrow) ) { SCIP_CALL( SCIPaddCut(scip, sol, sepadata->objrow, FALSE, &infeasible) ); } if ( infeasible ) *result = SCIP_CUTOFF; else if ( tightened ) *result = SCIP_REDUCEDDOM; else *result = SCIP_SEPARATED; } return SCIP_OKAY; }