/** depending on the LP's solution status, calls reduced cost or Farkas pricing method of variable pricer */ SCIP_RETCODE SCIPpricerExec( SCIP_PRICER* pricer, /**< variable pricer */ SCIP_SET* set, /**< global SCIP settings */ SCIP_PROB* prob, /**< transformed problem */ SCIP_LP* lp, /**< LP data */ SCIP_PRICESTORE* pricestore, /**< pricing storage */ SCIP_Real* lowerbound, /**< local lower bound computed by the pricer */ SCIP_RESULT* result /**< result of the pricing process */ ) { assert(pricer != NULL); assert(lowerbound != NULL); assert(result != NULL); /* set lowerbound and result pointer */ *lowerbound = - SCIPsetInfinity(set); *result = SCIP_SUCCESS; /* check if pricer should be delayed */ if( pricer->delay && SCIPpricestoreGetNVars(pricestore) > 0 ) return SCIP_OKAY; if( SCIPlpGetSolstat(lp) == SCIP_LPSOLSTAT_INFEASIBLE ) { SCIP_CALL( SCIPpricerFarkas(pricer, set, prob) ); } else { *result = SCIP_DIDNOTRUN; SCIP_CALL( SCIPpricerRedcost(pricer, set, prob, lowerbound, result) ); } return SCIP_OKAY; }
/** reset primal-dual integral */ void SCIPstatResetPrimalDualIntegral( SCIP_STAT* stat, /**< problem statistics data */ SCIP_SET* set, /**< global SCIP settings */ SCIP_Bool partialreset /**< should time and integral value be kept? (in combination with no statistical * reset, integrals are added for each problem to be solved) */ ) { assert(stat != NULL); stat->previousgap = 100.0; stat->lastprimalbound = SCIP_UNKNOWN; stat->lastdualbound = SCIP_UNKNOWN; stat->lastlowerbound = -SCIPsetInfinity(set); stat->lastupperbound = SCIPsetInfinity(set); /* partial resets keep the integral value and previous evaluation time */ if( !partialreset ) { stat->previntegralevaltime = 0.0; stat->primaldualintegral = 0.0; } }
/** adds cut stored as LP row to separation storage and captures it; * if the cut should be forced to be used, an infinite score has to be used */ static SCIP_RETCODE sepastoreAddCut( SCIP_SEPASTORE* sepastore, /**< separation storage */ BMS_BLKMEM* blkmem, /**< block memory */ SCIP_SET* set, /**< global SCIP settings */ SCIP_STAT* stat, /**< problem statistics data */ SCIP_EVENTQUEUE* eventqueue, /**< event queue */ SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */ SCIP_LP* lp, /**< LP data */ SCIP_SOL* sol, /**< primal solution that was separated, or NULL for LP solution */ SCIP_ROW* cut, /**< separated cut */ SCIP_Bool forcecut, /**< should the cut be forced to enter the LP? */ SCIP_Bool root /**< are we at the root node? */ ) { SCIP_Real cutefficacy; SCIP_Real cutobjparallelism; SCIP_Real cutscore; int pos; assert(sepastore != NULL); assert(sepastore->nforcedcuts <= sepastore->ncuts); assert(set != NULL); assert(cut != NULL); assert(sol != NULL || !SCIProwIsInLP(cut)); assert(!SCIPsetIsInfinity(set, -SCIProwGetLhs(cut)) || !SCIPsetIsInfinity(set, SCIProwGetRhs(cut))); assert(eventqueue != NULL); assert(eventfilter != NULL); /* in the root node, every local cut is a global cut, and global cuts are nicer in many ways...*/ if( root && SCIProwIsLocal(cut) ) { SCIPdebugMessage("change local flag of cut <%s> to FALSE due to addition in root node\n", SCIProwGetName(cut)); SCIP_CALL( SCIProwChgLocal(cut, FALSE) ); assert(!SCIProwIsLocal(cut)); } /* check cut for redundancy * in each separation round, make sure that at least one (even redundant) cut enters the LP to avoid cycling */ if( !forcecut && sepastore->ncuts > 0 && sepastoreIsCutRedundant(sepastore, set, stat, cut) ) return SCIP_OKAY; /* if only one cut is currently present in the cut store, it could be redundant; in this case, it can now be removed * again, because now a non redundant cut enters the store */ if( sepastore->ncuts == 1 && sepastoreIsCutRedundant(sepastore, set, stat, sepastore->cuts[0]) ) { /* check, if the row deletions from separation storage events are tracked * if so, issue ROWDELETEDSEPA event */ if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 ) { SCIP_EVENT* event; SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[0]) ); SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) ); } SCIP_CALL( SCIProwRelease(&sepastore->cuts[0], blkmem, set, lp) ); sepastore->ncuts = 0; sepastore->nforcedcuts = 0; } /* a cut is forced to enter the LP if * - we construct the initial LP, or * - it has infinite score factor, or * - it is a bound change * if it is a non-forced cut and no cuts should be added, abort */ forcecut = forcecut || sepastore->initiallp || sepastore->forcecuts || (!SCIProwIsModifiable(cut) && SCIProwGetNNonz(cut) == 1); if( !forcecut && SCIPsetGetSepaMaxcuts(set, root) == 0 ) return SCIP_OKAY; /* get enough memory to store the cut */ SCIP_CALL( sepastoreEnsureCutsMem(sepastore, set, sepastore->ncuts+1) ); assert(sepastore->ncuts < sepastore->cutssize); if( forcecut ) { cutefficacy = SCIPsetInfinity(set); cutscore = SCIPsetInfinity(set); cutobjparallelism = 1.0; } else { /* initialize values to invalid (will be initialized during cut filtering) */ cutefficacy = SCIP_INVALID; cutscore = SCIP_INVALID; /* initialize parallelism to objective (constant throughout filtering) */ if( set->sepa_objparalfac > 0.0 ) cutobjparallelism = SCIProwGetObjParallelism(cut, set, lp); else cutobjparallelism = 0.0; /* no need to calculate it */ } SCIPdebugMessage("adding cut <%s> to separation storage of size %d (forcecut=%u, len=%d)\n", SCIProwGetName(cut), sepastore->ncuts, forcecut, SCIProwGetNNonz(cut)); /*SCIPdebug(SCIProwPrint(cut, NULL));*/ /* capture the cut */ SCIProwCapture(cut); /* add cut to arrays */ if( forcecut ) { /* make room at the beginning of the array for forced cut */ pos = sepastore->nforcedcuts; sepastore->cuts[sepastore->ncuts] = sepastore->cuts[pos]; sepastore->efficacies[sepastore->ncuts] = sepastore->efficacies[pos]; sepastore->objparallelisms[sepastore->ncuts] = sepastore->objparallelisms[pos]; sepastore->orthogonalities[sepastore->ncuts] = sepastore->orthogonalities[pos]; sepastore->scores[sepastore->ncuts] = sepastore->scores[pos]; sepastore->nforcedcuts++; } else pos = sepastore->ncuts; sepastore->cuts[pos] = cut; sepastore->efficacies[pos] = cutefficacy; sepastore->objparallelisms[pos] = cutobjparallelism; sepastore->orthogonalities[pos] = 1.0; sepastore->scores[pos] = cutscore; sepastore->ncuts++; /* check, if the row addition to separation storage events are tracked * if so, issue ROWADDEDSEPA event */ if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDSEPA) != 0 ) { SCIP_EVENT* event; SCIP_CALL( SCIPeventCreateRowAddedSepa(&event, blkmem, cut) ); SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) ); } return SCIP_OKAY; }