/** problem reading method of reader */ static SCIP_DECL_READERREAD(readerReadFix) { /*lint --e{715}*/ assert(reader != NULL); assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); assert(result != NULL); *result = SCIP_DIDNOTRUN; if( SCIPgetStage(scip) < SCIP_STAGE_PROBLEM ) { SCIPerrorMessage("reading of fixing file is only possible after a problem was created\n"); return SCIP_READERROR; } /* free transformed problem, s.t. fixings are applied to the original problem */ SCIP_CALL( SCIPfreeTransform(scip) ); /* read (partial) solution from fixing file */ SCIP_CALL( readSol(scip, filename) ); *result = SCIP_SUCCESS; return SCIP_OKAY; }
/** transforms constraint data into data belonging to the transformed problem */ static SCIP_DECL_CONSTRANS(consTransSamediff) { /*lint --e{715}*/ SCIP_CONSDATA* sourcedata; SCIP_CONSDATA* targetdata; assert(conshdlr != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING); assert(sourcecons != NULL); assert(targetcons != NULL); sourcedata = SCIPconsGetData(sourcecons); assert(sourcedata != NULL); /* create constraint data for target constraint */ SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->itemid1, sourcedata->itemid2, sourcedata->type, sourcedata->node) ); /* create target constraint */ SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata, SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) ); return SCIP_OKAY; }
/* reads problem from file */ SCIP_RETCODE SCIPreadDec( SCIP* scip, /**< SCIP data structure */ const char* filename, /**< full path and name of file to read, or NULL if stdin should be used */ SCIP_RESULT* result /**< pointer to store the result of the file reading call */ ) { SCIP_READER* reader; DECINPUT decinput; int i; if( SCIPgetStage(scip) < SCIP_STAGE_TRANSFORMED ) SCIP_CALL( SCIPtransformProb(scip) ); reader = SCIPfindReader(scip, READER_NAME); assert(reader != NULL); /* initialize DEC input data */ decinput.file = NULL; decinput.linebuf[0] = '\0'; SCIP_CALL( SCIPallocMemoryArray(scip, &decinput.token, DEC_MAX_LINELEN) ); /*lint !e506*/ decinput.token[0] = '\0'; SCIP_CALL( SCIPallocMemoryArray(scip, &decinput.tokenbuf, DEC_MAX_LINELEN) ); /*lint !e506*/ decinput.tokenbuf[0] = '\0'; for( i = 0; i < DEC_MAX_PUSHEDTOKENS; ++ i ) { SCIP_CALL( SCIPallocMemoryArray(scip, &decinput.pushedtokens[i], DEC_MAX_LINELEN) ); /*lint !e506 !e866*/ } decinput.npushedtokens = 0; decinput.linenumber = 0; decinput.linepos = 0; decinput.section = DEC_START; decinput.presolved = FALSE; decinput.haspresolvesection = FALSE; decinput.nblocks = NOVALUE; decinput.blocknr = - 2; decinput.haserror = FALSE; /* read the file */ SCIP_CALL( readDECFile(scip, reader, &decinput, filename) ); /* free dynamically allocated memory */ SCIPfreeMemoryArray(scip, &decinput.token); SCIPfreeMemoryArray(scip, &decinput.tokenbuf); for( i = 0; i < DEC_MAX_PUSHEDTOKENS; ++ i ) { SCIPfreeMemoryArray(scip, &decinput.pushedtokens[i]); } /* evaluate the result */ if( decinput.haserror ) return SCIP_READERROR; else { *result = SCIP_SUCCESS; } return SCIP_OKAY; }
/** informs solution debugger, that the given node will be freed */ SCIP_RETCODE SCIPdebugRemoveNode( BMS_BLKMEM* blkmem, /**< block memory */ SCIP_SET* set, /**< global SCIP settings */ SCIP_NODE* node /**< node that will be freed */ ) { assert(set != NULL); assert(blkmem != NULL); assert(node != NULL); /* check if we are in the original problem and not in a sub MIP */ if( !isSolutionInMip(set) ) return SCIP_OKAY; /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */ if( debugSolIsAchieved(set) ) return SCIP_OKAY; /* check if a solution will be cutoff in tree */ if( SCIPgetStage(set->scip) != SCIP_STAGE_FREESOLVE && SCIPgetStage(set->scip) != SCIP_STAGE_PRESOLVING && SCIPnodeGetType(node) != SCIP_NODETYPE_PROBINGNODE ) { SCIP_Bool solisinnode; solisinnode = FALSE; SCIP_CALL( isSolutionInNode(blkmem, set, node, &solisinnode) ); /* wrong node will be cutoff */ if( solisinnode ) { SCIPerrorMessage("debugging solution was cut off in local node %p at depth %d\n", node, SCIPnodeGetDepth(node)); SCIPABORT(); } } /* remove node from the hash map */ if( solinnode != NULL ) { SCIP_CALL( SCIPhashmapRemove(solinnode, (void*)node) ); } return SCIP_OKAY; }
/** problem reading method of reader */ static SCIP_DECL_READERREAD(readerReadBlk) { /*lint --e{715} */ if( SCIPgetStage(scip) == SCIP_STAGE_INIT || SCIPgetNVars(scip) == 0 || SCIPgetNConss(scip) == 0 ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_DIALOG, NULL, "Please read in a problem before reading in the corresponding structure file!\n"); return SCIP_OKAY; } SCIP_CALL( SCIPreadBlk(scip, filename, result) ); return SCIP_OKAY; }
/** reads a diff file */ static SCIP_RETCODE readDiffFile( SCIP* scip, /**< SCIP data structure */ LPINPUT* lpinput, /**< LP reading data */ const char* filename /**< name of the input file */ ) { assert(lpinput != NULL); /* open file */ lpinput->file = SCIPfopen(filename, "r"); if( lpinput->file == NULL ) { SCIPerrorMessage("cannot open file <%s> for reading\n", filename); SCIPprintSysError(filename); return SCIP_NOFILE; } /* free transformed problem */ if( SCIPgetStage(scip) >= SCIP_STAGE_PROBLEM ) { SCIP_CALL( SCIPfreeTransform(scip) ); } /* parse the file */ lpinput->section = LP_START; while( lpinput->section != LP_END && !hasError(lpinput) ) { switch( lpinput->section ) { case LP_START: SCIP_CALL( readStart(scip, lpinput) ); break; case LP_OBJECTIVE: SCIP_CALL( readObjective(scip, lpinput) ); break; case LP_END: /* this is already handled in the while() loop */ default: SCIPerrorMessage("invalid Diff file section <%d>\n", lpinput->section); return SCIP_INVALIDDATA; } } /* close file */ SCIPfclose(lpinput->file); return SCIP_OKAY; }
/** dialog execution method for writing all known decompositions */ static SCIP_DECL_DIALOGEXEC(GCGdialogExecWriteAllDecompositions) { SCIP_CALL( SCIPdialoghdlrAddHistory(dialoghdlr, dialog, NULL, FALSE) ); if( SCIPgetStage(scip) >= SCIP_STAGE_PROBLEM ) { SCIP_CALL( writeAllDecompositions(scip, dialog, dialoghdlr, nextdialog) ); } else SCIPdialogMessage(scip, NULL, "no problem available\n"); *nextdialog = SCIPdialoghdlrGetRoot(dialoghdlr); return SCIP_OKAY; }
void ILPSolverSCIP::set_start_solution(const std::vector<double>& p_solution) { assert(p_solution.size() == d_cols.size()); // May not be able to set the solution after the problem has been solved or transformed. if (SCIPgetStage(d_scip) == SCIP_STAGE_SOLVED) reset_solution(); SCIP_SOL* sol; SCIP_Bool ignored{ false }; call_scip(SCIPcreateSol, d_scip, &sol, nullptr); // SCIP uses a double*, not a const double*, but ScaiILP demands a const std::vector<double>&. // Internally, SCIP calls a single-variable setter for every variable with a by-value pass of the corresponding double, // so the const_cast should not violate actual const-ness. // Sadly, it is not avoidable since SCIP is not const-correct. (SCIP 6.0) call_scip(SCIPsetSolVals, d_scip, sol, static_cast<int>(d_cols.size()), d_cols.data(), const_cast<double*>(p_solution.data())); call_scip(SCIPaddSolFree, d_scip, &sol, &ignored); }
SolutionStatus ILPSolverSCIP::get_status() const { int n = 0; // There are null-pointer accesses if called in the wrong stage, which happens if resetted. switch (SCIPgetStage(d_scip)) { case SCIP_STAGE_TRANSFORMED: [[fallthrough]]; case SCIP_STAGE_INITPRESOLVE: [[fallthrough]]; case SCIP_STAGE_PRESOLVING: [[fallthrough]]; case SCIP_STAGE_EXITPRESOLVE: [[fallthrough]]; case SCIP_STAGE_PRESOLVED: [[fallthrough]]; case SCIP_STAGE_INITSOLVE: [[fallthrough]]; case SCIP_STAGE_SOLVING: [[fallthrough]]; case SCIP_STAGE_SOLVED: [[fallthrough]]; case SCIP_STAGE_EXITSOLVE: n = static_cast<int>(SCIPgetNSolsFound(d_scip)); } SolutionStatus ret = (n > 0) ? SolutionStatus::SUBOPTIMAL : SolutionStatus::NO_SOLUTION; // Handle all possible status values. Almost all will be reduced to SUBOPTIMAL or NO_SOLUTION. switch (SCIPgetStatus(d_scip)) { case SCIP_STATUS_OPTIMAL: return SolutionStatus::PROVEN_OPTIMAL; case SCIP_STATUS_INFEASIBLE: return SolutionStatus::PROVEN_INFEASIBLE; case SCIP_STATUS_UNBOUNDED: return SolutionStatus::PROVEN_UNBOUNDED; case SCIP_STATUS_UNKNOWN: [[fallthrough]]; case SCIP_STATUS_INFORUNBD: [[fallthrough]]; case SCIP_STATUS_NODELIMIT: [[fallthrough]]; case SCIP_STATUS_TOTALNODELIMIT: [[fallthrough]]; case SCIP_STATUS_STALLNODELIMIT: [[fallthrough]]; case SCIP_STATUS_TIMELIMIT: [[fallthrough]]; case SCIP_STATUS_MEMLIMIT: [[fallthrough]]; case SCIP_STATUS_GAPLIMIT: [[fallthrough]]; case SCIP_STATUS_SOLLIMIT: [[fallthrough]]; case SCIP_STATUS_BESTSOLLIMIT: [[fallthrough]]; case SCIP_STATUS_RESTARTLIMIT: [[fallthrough]]; case SCIP_STATUS_USERINTERRUPT: [[fallthrough]]; case SCIP_STATUS_TERMINATE: [[fallthrough]]; default: return ret; } }
/** initializes the pricing problem for the given capacity */ static SCIP_RETCODE initPricing( SCIP* scip, /**< SCIP data structure */ SCIP_PRICERDATA* pricerdata, /**< pricer data */ SCIP* subscip, /**< pricing SCIP data structure */ SCIP_VAR** vars /**< variable array for the items */ ) { SCIP_CONS** conss; SCIP_Longint* vals; SCIP_CONS* cons; SCIP_VAR* var; SCIP_Longint* weights; SCIP_Longint capacity; SCIP_Real dual; int nitems; int nvars; int c; assert( SCIPgetStage(subscip) == SCIP_STAGE_PROBLEM ); assert(pricerdata != NULL); nitems = pricerdata->nitems; conss = pricerdata->conss; weights = pricerdata->weights; capacity = pricerdata->capacity; nvars = 0; SCIP_CALL( SCIPallocBufferArray(subscip, &vals, nitems) ); /* create for each order, which is not assigned yet, a variable with objective coefficient */ for( c = 0; c < nitems; ++c ) { cons = conss[c]; /* check if each constraint is setppc constraint */ assert( !strncmp( SCIPconshdlrGetName( SCIPconsGetHdlr(cons) ), "setppc", 6) ); /* constraints which are (locally) disabled/redundant are not of * interest since the corresponding job is assigned to a packing */ if( !SCIPconsIsEnabled(cons) ) continue; if( SCIPgetNFixedonesSetppc(scip, cons) == 1 ) { /* disable constraint locally */ SCIP_CALL( SCIPdelConsLocal(scip, cons) ); continue; } /* dual value in original SCIP */ dual = SCIPgetDualsolSetppc(scip, cons); SCIP_CALL( SCIPcreateVarBasic(subscip, &var, SCIPconsGetName(cons), 0.0, 1.0, dual, SCIP_VARTYPE_BINARY) ); SCIP_CALL( SCIPaddVar(subscip, var) ); vals[nvars] = weights[c]; vars[nvars] = var; nvars++; /* release variable */ SCIP_CALL( SCIPreleaseVar(subscip, &var) ); } /* create capacity constraint */ SCIP_CALL( SCIPcreateConsBasicKnapsack(subscip, &cons, "capacity", nvars, vars, vals, capacity) ); SCIP_CALL( SCIPaddCons(subscip, cons) ); SCIP_CALL( SCIPreleaseCons(subscip, &cons) ); /* add constraint of the branching decisions */ SCIP_CALL( addBranchingDecisionConss(scip, subscip, vars, pricerdata->conshdlr) ); /* avoid to generate columns which are fixed to zero */ SCIP_CALL( addFixedVarsConss(scip, subscip, vars, conss, nitems) ); SCIPfreeBufferArray(subscip, &vals); return SCIP_OKAY; }
/** perform dual presolving */ static SCIP_RETCODE performDualfix( SCIP* scip, /**< SCIP data structure */ int* nfixedvars, /**< pointer to store number of fixed variables */ SCIP_Bool* unbounded, /**< pointer to store if an unboundness was detected */ SCIP_Bool* cutoff /**< pointer to store if a cutoff was detected */ ) { SCIP_VAR** vars; int nvars; int v; /* get active problem variables */ vars = SCIPgetVars(scip); nvars = SCIPgetNVars(scip); /* look for fixable variables * loop backwards, since a variable fixing can change the current and the subsequent slots in the vars array */ for( v = nvars - 1; v >= 0; --v ) { SCIP_VAR* var; SCIP_Real bound; SCIP_Real obj; SCIP_Bool infeasible; SCIP_Bool fixed; var = vars[v]; assert(var != NULL); /* don't perform dual presolving operations on deleted variables */ if( SCIPvarIsDeleted(var) ) continue; /* ignore already fixed variables (use feasibility tolerance since this is used in SCIPfixVar() */ if( SCIPisFeasEQ(scip, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var)) ) continue; obj = SCIPvarGetObj(var); /* if the objective coefficient of the variable is 0 and it may be rounded both * up and down, then fix it to the closest feasible value to 0 */ if( SCIPisZero(scip, obj) && SCIPvarMayRoundDown(var) && SCIPvarMayRoundUp(var) ) { SCIP_Real roundbound; bound = SCIPvarGetLbGlobal(var); if( SCIPisLT(scip, bound, 0.0) ) { if( SCIPisLE(scip, 0.0, SCIPvarGetUbGlobal(var)) ) bound = 0.0; else { /* try to take an integer value, only for polishing */ roundbound = SCIPfloor(scip, SCIPvarGetUbGlobal(var)); if( roundbound < bound ) bound = SCIPvarGetUbGlobal(var); else bound = roundbound; } } else { /* try to take an integer value, only for polishing */ roundbound = SCIPceil(scip, bound); if( roundbound < SCIPvarGetUbGlobal(var) ) bound = roundbound; } SCIPdebugMessage("fixing variable <%s> with objective 0 to %g\n", SCIPvarGetName(var), bound); } else { /* if it is always possible to round variable in direction of objective value, fix it to its proper bound */ if( SCIPvarMayRoundDown(var) && !SCIPisNegative(scip, obj) ) { bound = SCIPvarGetLbGlobal(var); if ( SCIPisInfinity(scip, -bound) ) { /* variable can be fixed to -infinity */ if ( SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING ) { /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this * consistently. We thus have to ignore this (should better be handled in presolving). */ continue; } if ( SCIPisZero(scip, obj) && SCIPvarGetNLocksUp(var) == 1 ) { /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is * clever enough to set/aggregate the variable to something more useful than -infinity and do nothing * here. */ continue; } } SCIPdebugMessage("fixing variable <%s> with objective %g and %d uplocks to lower bound %g\n", SCIPvarGetName(var), SCIPvarGetObj(var), SCIPvarGetNLocksUp(var), bound); } else if( SCIPvarMayRoundUp(var) && !SCIPisPositive(scip, obj) ) { bound = SCIPvarGetUbGlobal(var); if ( SCIPisInfinity(scip, bound) ) { /* variable can be fixed to infinity */ if ( SCIPgetStage(scip) > SCIP_STAGE_PRESOLVING ) { /* Fixing variables to infinity is not allowed after presolving, since LP-solvers cannot handle this * consistently. We thus have to ignore this (should better be handled in presolving). */ continue; } if ( SCIPisZero(scip, obj) && SCIPvarGetNLocksDown(var) == 1 ) { /* Variable is only contained in one constraint: we hope that the corresponding constraint handler is * clever enough to set/aggregate the variable to something more useful than +infinity and do nothing * here */ continue; } } SCIPdebugMessage("fixing variable <%s> with objective %g and %d downlocks to upper bound %g\n", SCIPvarGetName(var), SCIPvarGetObj(var), SCIPvarGetNLocksDown(var), bound); } else continue; } if( SCIPisInfinity(scip, REALABS(bound)) && !SCIPisZero(scip, obj) ) { SCIPdebugMessage(" -> unbounded fixing\n"); SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "problem infeasible or unbounded: variable <%s> with objective %.15g can be made infinitely %s\n", SCIPvarGetName(var), SCIPvarGetObj(var), bound < 0.0 ? "small" : "large"); *unbounded = TRUE; return SCIP_OKAY; } /* apply the fixing */ SCIPdebugMessage("apply fixing of variable %s to %g\n", SCIPvarGetName(var), bound); SCIP_CALL( SCIPfixVar(scip, var, bound, &infeasible, &fixed) ); if( infeasible ) { SCIPdebugMessage(" -> infeasible fixing\n"); *cutoff = TRUE; return SCIP_OKAY; } assert(fixed || (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && SCIPisFeasEQ(scip, bound, SCIPvarGetLbLocal(var)) && SCIPisFeasEQ(scip, bound, SCIPvarGetUbLocal(var)))); (*nfixedvars)++; } return SCIP_OKAY; }
/** reduced cost propagation method for an LP solution */ static SCIP_DECL_PROPEXEC(propExecRedcost) { /*lint --e{715}*/ SCIP_PROPDATA* propdata; SCIP_COL** cols; SCIP_Real requiredredcost; SCIP_Real cutoffbound; SCIP_Real lpobjval; SCIP_Bool propbinvars; SCIP_Bool cutoff; int nchgbds; int ncols; int c; *result = SCIP_DIDNOTRUN; /* in case we have a zero objective function, we skip the reduced cost propagator */ if( SCIPgetNObjVars(scip) == 0 ) return SCIP_OKAY; /* propagator can only be applied during solving stage */ if( SCIPgetStage(scip) < SCIP_STAGE_SOLVING ) return SCIP_OKAY; /* we cannot apply reduced cost fixing, if we want to solve exactly */ /**@todo implement reduced cost fixing with interval arithmetics */ if( SCIPisExactSolve(scip) ) return SCIP_OKAY; /* only call propagator, if the current node has an LP */ if( !SCIPhasCurrentNodeLP(scip) ) return SCIP_OKAY; /* only call propagator, if an optimal LP solution is at hand */ if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL ) return SCIP_OKAY; /* only call propagator, if the current LP is a valid relaxation */ if( !SCIPisLPRelax(scip) ) return SCIP_OKAY; /* we cannot apply reduced cost strengthening, if no simplex basis is available */ if( !SCIPisLPSolBasic(scip) ) return SCIP_OKAY; /* get current cutoff bound */ cutoffbound = SCIPgetCutoffbound(scip); /* reduced cost strengthening can only be applied, if we have a finite cutoff */ if( SCIPisInfinity(scip, cutoffbound) ) return SCIP_OKAY; /* get LP columns */ cols = SCIPgetLPCols(scip); ncols = SCIPgetNLPCols(scip); /* do nothing if the LP has no columns (is empty) */ if( ncols == 0 ) return SCIP_OKAY; /* get propagator data */ propdata = SCIPpropGetData(prop); assert(propdata != NULL); /* chack if all integral variables are fixed and the continuous variables should not be propagated */ if( !propdata->continuous && SCIPgetNPseudoBranchCands(scip) == 0 ) return SCIP_OKAY; /* get LP objective value */ lpobjval = SCIPgetLPObjval(scip); /* check if binary variables should be propagated */ propbinvars = (SCIPgetDepth(scip) == 0) || (cutoffbound - lpobjval < 5 * propdata->maxredcost); /* skip the propagator if the problem has only binary variables and those should not be propagated */ if( !propbinvars && SCIPgetNVars(scip) == SCIPgetNBinVars(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; cutoff = FALSE; nchgbds = 0; /* compute the required reduced cost which are needed for a binary variable to be fixed */ requiredredcost = cutoffbound - lpobjval; SCIPdebugMessage("lpobjval <%g>, cutoffbound <%g>, max reduced <%g>, propgate binary %u, use implics %u\n", lpobjval, cutoffbound, propdata->maxredcost, propbinvars, propdata->usefullimplics); /* check reduced costs for non-basic columns */ for( c = 0; c < ncols && !cutoff; ++c ) { SCIP_VAR* var; var = SCIPcolGetVar(cols[c]); /* skip continuous variables in case the corresponding parameter is set */ if( !propdata->continuous && !SCIPvarIsIntegral(var) ) continue; if( SCIPvarIsBinary(var) ) { if( propbinvars ) { if( SCIPgetDepth(scip) == 0 ) { SCIP_CALL( propagateRootRedcostBinvar(scip, propdata, var, cols[c], cutoffbound, &nchgbds) ); } else { SCIP_CALL( propagateRedcostBinvar(scip, propdata, var, cols[c], requiredredcost, &nchgbds, &cutoff) ); } } } else { SCIP_CALL( propagateRedcostVar(scip, var, cols[c], lpobjval, cutoffbound, &nchgbds) ); } } if( cutoff ) { *result = SCIP_CUTOFF; SCIPdebugMessage("node %"SCIP_LONGINT_FORMAT": detected cutoff\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip))); } else if( nchgbds > 0 ) { *result = SCIP_REDUCEDDOM; SCIPdebugMessage("node %"SCIP_LONGINT_FORMAT": %d bound changes (max redcost <%g>)\n", SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) , nchgbds, propdata->maxredcost); } return SCIP_OKAY; }
/** reads an BLK file */ static SCIP_RETCODE readBLKFile( SCIP* scip, /**< SCIP data structure */ SCIP_READER* reader, /**< reader data structure */ BLKINPUT* blkinput, /**< BLK reading data */ const char* filename /**< name of the input file */ ) { DEC_DECOMP *decdecomp; int i; int nconss; int nblocksread; int nvars; SCIP_READERDATA* readerdata; SCIP_CONS** conss; nblocksread = FALSE; assert(scip != NULL); assert(reader != NULL); assert(blkinput != NULL); if( SCIPgetStage(scip) < SCIP_STAGE_TRANSFORMED ) SCIP_CALL( SCIPtransformProb(scip) ); readerdata = SCIPreaderGetData(reader); assert(readerdata != NULL); readerdata->nlinkingcons = SCIPgetNConss(scip); readerdata->nlinkingvars = 0; nvars = SCIPgetNVars(scip); conss = SCIPgetConss(scip); nconss = SCIPgetNConss(scip); /* alloc: var -> block mapping */ SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->varstoblock, nvars) ); for( i = 0; i < nvars; i ++ ) { readerdata->varstoblock[i] = NOVALUE; } /* alloc: linkingvar -> blocks mapping */ SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->linkingvarsblocks, nvars) ); SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nlinkingvarsblocks, nvars) ); BMSclearMemoryArray(readerdata->linkingvarsblocks, nvars); BMSclearMemoryArray(readerdata->nlinkingvarsblocks, nvars); /* cons -> block mapping */ SCIP_CALL( SCIPhashmapCreate(&readerdata->constoblock, SCIPblkmem(scip), nconss) ); for( i = 0; i < SCIPgetNConss(scip); i ++ ) { SCIP_CALL( SCIPhashmapInsert(readerdata->constoblock, conss[i], (void*)(size_t) NOVALUE) ); } /* open file */ blkinput->file = SCIPfopen(filename, "r"); if( blkinput->file == NULL ) { SCIPerrorMessage("cannot open file <%s> for reading\n", filename); SCIPprintSysError(filename); return SCIP_NOFILE; } /* parse the file */ blkinput->section = BLK_START; while( blkinput->section != BLK_END && !hasError(blkinput) ) { switch( blkinput->section ) { case BLK_START: SCIP_CALL( readStart(scip, blkinput) ); break; case BLK_PRESOLVED: SCIP_CALL( readPresolved(scip, blkinput) ); if( blkinput->presolved && SCIPgetStage(scip) < SCIP_STAGE_PRESOLVED ) { assert(blkinput->haspresolvesection); /** @bug GCG should be able to presolve the problem first */ SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "decomposition belongs to the presolved problem, please presolve the problem first.\n"); goto TERMINATE; } break; case BLK_NBLOCKS: SCIP_CALL( readNBlocks(scip, blkinput) ); if( blkinput->haspresolvesection && !blkinput->presolved && SCIPgetStage(scip) >= SCIP_STAGE_PRESOLVED ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "decomposition belongs to the unpresolved problem, please re-read the problem and read the decomposition without presolving.\n"); goto TERMINATE; } if( !blkinput->haspresolvesection ) { SCIPwarningMessage(scip, "decomposition has no presolve section at beginning. The behaviour is undefined. See the FAQ for further information.\n"); } break; case BLK_BLOCK: if( nblocksread == FALSE ) { /* alloc n vars per block */ SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nblockvars, blkinput->nblocks) ); SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->nblockcons, blkinput->nblocks) ); SCIP_CALL( SCIPallocMemoryArray(scip, &readerdata->blockcons, blkinput->nblocks) ); for( i = 0; i < blkinput->nblocks; ++i ) { readerdata->nblockvars[i] = 0; readerdata->nblockcons[i] = 0; SCIP_CALL( SCIPallocMemoryArray(scip, &(readerdata->blockcons[i]), nconss) ); /*lint !e866*/ } nblocksread = TRUE; } SCIP_CALL( readBlock(scip, blkinput, readerdata) ); break; case BLK_MASTERCONSS: SCIP_CALL( readMasterconss(scip, blkinput, readerdata) ); break; case BLK_END: /* this is already handled in the while() loop */ default: SCIPerrorMessage("invalid BLK file section <%d>\n", blkinput->section); return SCIP_INVALIDDATA; } } SCIP_CALL( DECdecompCreate(scip, &decdecomp) ); /* fill decomp */ SCIP_CALL( fillDecompStruct(scip, blkinput, decdecomp, readerdata) ); /* add decomp to cons_decomp */ SCIP_CALL( SCIPconshdlrDecompAddDecdecomp(scip, decdecomp) ); for( i = 0; i < nvars; ++i ) { assert(readerdata->linkingvarsblocks[i] != NULL || readerdata->nlinkingvarsblocks[i] == 0); if( readerdata->nlinkingvarsblocks[i] > 0 ) { SCIPfreeMemoryArray(scip, &readerdata->linkingvarsblocks[i]); } } TERMINATE: if( nblocksread ) { for( i = blkinput->nblocks - 1; i >= 0; --i ) { SCIPfreeMemoryArray(scip, &(readerdata->blockcons[i])); } SCIPfreeMemoryArray(scip, &readerdata->blockcons); SCIPfreeMemoryArray(scip, &readerdata->nblockcons); SCIPfreeMemoryArray(scip, &readerdata->nblockvars); } SCIPhashmapFree(&readerdata->constoblock); SCIPfreeMemoryArray(scip, &readerdata->nlinkingvarsblocks); SCIPfreeMemoryArray(scip, &readerdata->linkingvarsblocks); SCIPfreeMemoryArray(scip, &readerdata->varstoblock); /* close file */ SCIPfclose(blkinput->file); return SCIP_OKAY; }
/** execution method of presolver */ static SCIP_DECL_PRESOLEXEC(presolExecDualagg) { /*lint --e{715}*/ SCIPMILPMATRIX* matrix; SCIP_Bool initialized; SCIP_Bool complete; assert(result != NULL); *result = SCIP_DIDNOTRUN; if( (SCIPgetStage(scip) != SCIP_STAGE_PRESOLVING) || SCIPinProbing(scip) || SCIPisNLPEnabled(scip) ) return SCIP_OKAY; if( SCIPisStopped(scip) || SCIPgetNActivePricers(scip) > 0 ) return SCIP_OKAY; if( SCIPgetNBinVars(scip) == 0 ) return SCIP_OKAY; if( !SCIPallowDualReds(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; matrix = NULL; SCIP_CALL( SCIPmatrixCreate(scip, &matrix, &initialized, &complete) ); /* we only work on pure MIPs currently */ if( initialized && complete ) { AGGRTYPE* aggtypes; SCIP_VAR** binvars; int nvaragg; int ncols; ncols = SCIPmatrixGetNColumns(matrix); nvaragg = 0; SCIP_CALL( SCIPallocBufferArray(scip, &aggtypes, ncols) ); BMSclearMemoryArray(aggtypes, ncols); SCIP_CALL( SCIPallocBufferArray(scip, &binvars, ncols) ); SCIPdebug( BMSclearMemoryArray(binvars, ncols) ); /* search for aggregations */ SCIP_CALL( findUplockAggregations(scip, matrix, &nvaragg, aggtypes, binvars) ); SCIP_CALL( findDownlockAggregations(scip, matrix, &nvaragg, aggtypes, binvars) ); /* apply aggregations, if we found any */ if( nvaragg > 0 ) { int v; for( v = 0; v < ncols; v++ ) { if( aggtypes[v] != NOAGG ) { SCIP_Bool infeasible; SCIP_Bool redundant; SCIP_Bool aggregated; SCIP_Real ub; SCIP_Real lb; ub = SCIPmatrixGetColUb(matrix, v); lb = SCIPmatrixGetColLb(matrix, v); /* aggregate variable */ assert(binvars[v] != NULL); if( aggtypes[v] == BIN0UBOUND ) { SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix, v), binvars[v], 1.0, ub-lb, ub, &infeasible, &redundant, &aggregated) ); } else { assert(aggtypes[v] == BIN0LBOUND); SCIP_CALL( SCIPaggregateVars(scip, SCIPmatrixGetVar(matrix, v), binvars[v], 1.0, lb-ub, lb, &infeasible, &redundant, &aggregated) ); } /* infeasible aggregation */ if( infeasible ) { SCIPdebugMessage(" -> infeasible aggregation\n"); *result = SCIP_CUTOFF; return SCIP_OKAY; } if( aggregated ) (*naggrvars)++; } } /* set result pointer */ if( (*naggrvars) > 0 ) *result = SCIP_SUCCESS; } SCIPfreeBufferArray(scip, &binvars); SCIPfreeBufferArray(scip, &aggtypes); } SCIPmatrixFree(scip, &matrix); return SCIP_OKAY; }
/** execution method of primal heuristic */ static SCIP_DECL_HEUREXEC(heurExecGcgrens) { /*lint --e{715}*/ SCIP* masterprob; SCIP_HEURDATA* heurdata; /* heuristic's data */ SCIP_Longint nstallnodes; /* number of stalling nodes for the subproblem */ assert( heur != NULL ); assert( scip != NULL ); assert( result != NULL ); /* get master problem */ masterprob = GCGrelaxGetMasterprob(scip); assert( masterprob != NULL); /* get heuristic's data */ heurdata = SCIPheurGetData(heur); assert( heurdata != NULL ); *result = SCIP_DELAYED; /* do not execute the heuristic on invalid relaxation solutions * (which is the case if the node has been cut off) */ if( !SCIPisRelaxSolValid(scip) ) { SCIPdebugMessage("skipping GCG RENS: invalid relaxation solution\n"); return SCIP_OKAY; } /* only call heuristic, if an optimal LP solution is at hand */ if( SCIPgetStage(masterprob) > SCIP_STAGE_SOLVING || SCIPgetLPSolstat(masterprob) != SCIP_LPSOLSTAT_OPTIMAL ) return SCIP_OKAY; *result = SCIP_DIDNOTRUN; /* only continue with some fractional variables */ if( SCIPgetNExternBranchCands(scip) == 0 ) return SCIP_OKAY; /* calculate the maximal number of branching nodes until heuristic is aborted */ nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip)); /* reward RENS if it succeeded often */ nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0)); nstallnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-SCIP as 100 nodes */ nstallnodes += heurdata->nodesofs; /* determine the node limit for the current process */ nstallnodes -= heurdata->usednodes; nstallnodes = MIN(nstallnodes, heurdata->maxnodes); /* check whether we have enough nodes left to call subproblem solving */ if( nstallnodes < heurdata->minnodes ) { SCIPdebugMessage("skipping RENS: nstallnodes=%"SCIP_LONGINT_FORMAT", minnodes=%"SCIP_LONGINT_FORMAT"\n", nstallnodes, heurdata->minnodes); return SCIP_OKAY; } if( SCIPisStopped(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; SCIP_CALL( SCIPapplyGcgrens(scip, heur, result, heurdata->minfixingrate, heurdata->minimprove, heurdata->maxnodes, nstallnodes, heurdata->binarybounds, heurdata->uselprows) ); return SCIP_OKAY; }
/** ensure that maxindex + 1 rows can be represented in data arrays; memory gets reallocated with 10% extra space * to save some time for future allocations */ static SCIP_RETCODE heurdataEnsureArraySize( SCIP* scip, /**< SCIP data structure */ SCIP_HEURDATA* heurdata, /**< heuristic data */ int maxindex /**< row index at hand (size must be at least this large) */ ) { int newsize; int r; /* maxindex fits in current array -> nothing to do */ if( maxindex < heurdata->memsize ) return SCIP_OKAY; /* new memory size is the max index + 1 plus 10% additional space */ newsize = (int)SCIPfeasCeil(scip, (maxindex + 1) * 1.1); assert(newsize > heurdata->memsize); assert(heurdata->memsize >= 0); /* alloc memory arrays for row information */ if( heurdata->memsize == 0 ) { SCIP_VAR** vars; int v; int nvars; SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowmeans, newsize) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowvariances, newsize) ); assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING); vars = SCIPgetVars(scip); nvars = SCIPgetNVars(scip); assert(nvars > 0); /* allocate variable update event processing array storage */ SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varfilterposs, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varposs, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->updatedvars, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentubs, nvars) ); SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentlbs, nvars) ); heurdata->varpossmemsize = nvars; heurdata->nupdatedvars = 0; /* init variable event processing data */ for( v = 0; v < nvars; ++v ) { assert(SCIPvarIsActive(vars[v])); assert(SCIPvarGetProbindex(vars[v]) == v); /* set up variable events to catch bound changes */ SCIP_CALL( SCIPcatchVarEvent(scip, vars[v], EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, &(heurdata->varfilterposs[v])) ); assert(heurdata->varfilterposs[v] >= 0); heurdata->varposs[v] = -1; heurdata->updatedvars[v] = NULL; heurdata->currentlbs[v] = SCIP_INVALID; heurdata->currentubs[v] = SCIP_INVALID; } } else { SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowmeans, newsize) ); SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowvariances, newsize) ); } /* loop over extended arrays and invalidate data to trigger initialization of this row when necessary */ for( r = heurdata->memsize; r < newsize; ++r ) { heurdata->rowmeans[r] = SCIP_INVALID; heurdata->rowvariances[r] = SCIP_INVALID; heurdata->rowinfinitiesdown[r] = 0; heurdata->rowinfinitiesup[r] = 0; } /* adjust memsize */ heurdata->memsize = newsize; return SCIP_OKAY; }
SCIP_RETCODE SCIPconshdlrBenders::sepaBenders( SCIP * scip, SCIP_CONSHDLR * conshdlr, SCIP_SOL * sol, whereFrom where, SCIP_RESULT * result) { OsiCuts cs; /**< Benders cut placeholder */ SCIP_Real * vals = NULL; /**< current solution */ #if 1 if (scip_checkpriority_ < 0) { /** consider incumbent solutions only */ double primObj = SCIPgetPrimalbound(scip); double currObj = SCIPgetSolOrigObj(scip, sol); if (SCIPisLT(scip, primObj, currObj)) { DSPdebugMessage(" -> primObj %e currObj %e\n", primObj, currObj); return SCIP_OKAY; } } #endif /** allocate memory */ SCIP_CALL(SCIPallocMemoryArray(scip, &vals, nvars_)); /** get current solution */ SCIP_CALL(SCIPgetSolVals(scip, sol, nvars_, vars_, vals)); /** TODO The following filter does not work, meaning that it provides suboptimal solution. * I do not know the reason. */ #if 0 double maxviol = 1.e-10; for (int j = 0; j < nvars_ - naux_; ++j) { SCIP_VARTYPE vartype = SCIPvarGetType(vars_[j]); if (vartype == SCIP_VARTYPE_CONTINUOUS) continue; double viol = 0.5 - fabs(vals[j] - floor(vals[j]) - 0.5); if (viol > maxviol) maxviol = viol; } DSPdebugMessage("maximum violation %e\n", maxviol); if (where != from_scip_check && where != from_scip_enfolp && where != from_scip_enfops && maxviol > 1.e-7) { printf("where %d maxviol %e\n", where, maxviol); /** free memory */ SCIPfreeMemoryArray(scip, &vals); return SCIP_OKAY; } #endif #ifdef DSP_DEBUG2 double minvals = COIN_DBL_MAX; double maxvals = -COIN_DBL_MAX; double sumvals = 0.; double ssvals = 0.; //printf("nvars_ %d naux_ %d nAuxvars_ %d\n", nvars_, naux_, tss_->nAuxvars_); for (int j = 0; j < nvars_ - naux_; ++j) { // if (vals[j] < 0 || vals[j] > 1) // printf("solution %d has value %e.\n", j, vals[j]); sumvals += vals[j]; ssvals += vals[j] * vals[j]; minvals = minvals > vals[j] ? vals[j] : minvals; maxvals = maxvals < vals[j] ? vals[j] : maxvals; } DSPdebugMessage("solution: min %e max %e avg %e sum %e two-norm %e\n", minvals, maxvals, sumvals / nvars_, sumvals, sqrt(ssvals)); #endif #define SCAN_GLOBAL_CUT_POOL #ifdef SCAN_GLOBAL_CUT_POOL if (SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPgetStage(scip) == SCIP_STAGE_SOLVED || SCIPgetStage(scip) == SCIP_STAGE_EXITSOLVE) { bool addedPoolCut = false; int numPoolCuts = SCIPgetNPoolCuts(scip); int numCutsToScan = 100; SCIP_CUT ** poolcuts = SCIPgetPoolCuts(scip); for (int i = numPoolCuts - 1; i >= 0; --i) { if (i < 0) break; if (numCutsToScan == 0) break; /** retrieve row */ SCIP_ROW * poolcutrow = SCIPcutGetRow(poolcuts[i]); /** benders? */ if (strcmp(SCIProwGetName(poolcutrow), "benders") != 0) continue; /** counter */ numCutsToScan--; if (SCIPgetCutEfficacy(scip, sol, poolcutrow) > 1.e-6) { if (where == from_scip_sepalp || where == from_scip_sepasol || where == from_scip_enfolp) { /** add cut */ SCIP_Bool infeasible; SCIP_CALL(SCIPaddCut(scip, sol, poolcutrow, FALSE, /**< force cut */ &infeasible)); if (infeasible) *result = SCIP_CUTOFF; else //if (*result != SCIP_CUTOFF) *result = SCIP_SEPARATED; } else *result = SCIP_INFEASIBLE; addedPoolCut = true; break; } } if (addedPoolCut) { DSPdebugMessage("Added pool cut\n"); /** free memory */ SCIPfreeMemoryArray(scip, &vals); return SCIP_OKAY; } } #endif /** generate Benders cuts */ assert(tss_); tss_->generateCuts(nvars_, vals, &cs); /** If found Benders cuts */ for (int i = 0; i < cs.sizeCuts(); ++i) { /** get cut pointer */ OsiRowCut * rc = cs.rowCutPtr(i); if (!rc) continue; const CoinPackedVector cutrow = rc->row(); if (cutrow.getNumElements() == 0) continue; /** is optimality cut? */ bool isOptimalityCut = false; for (int j = nvars_ - naux_; j < nvars_; ++j) { if (cutrow.getMaxIndex() == j) { isOptimalityCut = true; break; } } double efficacy = rc->violated(vals) / cutrow.twoNorm(); SCIP_Bool isEfficacious = efficacy > 1.e-6; #define KK_TEST #ifdef KK_TEST if (SCIPgetStage(scip) == SCIP_STAGE_INITSOLVE || SCIPgetStage(scip) == SCIP_STAGE_SOLVING) { /** create empty row */ SCIP_ROW * row = NULL; SCIP_CALL(SCIPcreateEmptyRowCons(scip, &row, conshdlr, "benders", rc->lb(), SCIPinfinity(scip), FALSE, /**< is row local? */ FALSE, /**< is row modifiable? */ FALSE /**< is row removable? can this be TRUE? */)); /** cache the row extension and only flush them if the cut gets added */ SCIP_CALL(SCIPcacheRowExtensions(scip, row)); /** collect all non-zero coefficients */ for (int j = 0; j < cutrow.getNumElements(); ++j) SCIP_CALL(SCIPaddVarToRow(scip, row, vars_[cutrow.getIndices()[j]], cutrow.getElements()[j])); DSPdebugMessage("found Benders (%s) cut: act=%f, lhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n", isOptimalityCut ? "opti" : "feas", SCIPgetRowLPActivity(scip, row), SCIProwGetLhs(row), SCIProwGetNorm(row), SCIPgetCutEfficacy(scip, sol, row), SCIPgetRowMinCoef(scip, row), SCIPgetRowMaxCoef(scip, row), SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row)); /** flush all changes before adding cut */ SCIP_CALL(SCIPflushRowExtensions(scip, row)); DSPdebugMessage("efficacy %e isEfficatious %d\n", efficacy, isEfficacious); if (isEfficacious) { if (where == from_scip_sepalp || where == from_scip_sepasol || where == from_scip_enfolp) { /** add cut */ SCIP_Bool infeasible; SCIP_CALL(SCIPaddCut(scip, sol, row, FALSE, /**< force cut */ &infeasible)); if (infeasible) *result = SCIP_CUTOFF; else //if (*result != SCIP_CUTOFF) *result = SCIP_SEPARATED; } else *result = SCIP_INFEASIBLE; } /** add cut to global pool */ SCIP_CALL(SCIPaddPoolCut(scip, row)); DSPdebugMessage("number of cuts in global cut pool: %d\n", SCIPgetNPoolCuts(scip)); /** release the row */ SCIP_CALL(SCIPreleaseRow(scip, &row)); } else if (isEfficacious && where != from_scip_sepalp && where != from_scip_sepasol && where != from_scip_enfolp) *result = SCIP_INFEASIBLE; #else if (where == from_scip_sepalp || where == from_scip_sepasol || where == from_scip_enfolp) { /** create empty row */ SCIP_ROW * row = NULL; SCIP_CALL(SCIPcreateEmptyRowCons(scip, &row, conshdlr, "benders", rc->lb(), SCIPinfinity(scip), FALSE, /**< is row local? */ FALSE, /**< is row modifiable? */ FALSE /**< is row removable? can this be TRUE? */)); /** cache the row extension and only flush them if the cut gets added */ SCIP_CALL(SCIPcacheRowExtensions(scip, row)); /** collect all non-zero coefficients */ for (int j = 0; j < cutrow.getNumElements(); ++j) SCIP_CALL(SCIPaddVarToRow(scip, row, vars_[cutrow.getIndices()[j]], cutrow.getElements()[j])); DSPdebugMessage("found Benders (%s) cut: act=%f, lhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n", isOptimalityCut ? "opti" : "feas", SCIPgetRowLPActivity(scip, row), SCIProwGetLhs(row), SCIProwGetNorm(row), SCIPgetCutEfficacy(scip, NULL, row), SCIPgetRowMinCoef(scip, row), SCIPgetRowMaxCoef(scip, row), SCIPgetRowMaxCoef(scip, row)/SCIPgetRowMinCoef(scip, row)); /** flush all changes before adding cut */ SCIP_CALL(SCIPflushRowExtensions(scip, row)); /** is cut efficacious? */ if (isOptimalityCut) { efficacy = SCIPgetCutEfficacy(scip, sol, row); isEfficacious = SCIPisCutEfficacious(scip, sol, row); } else { efficacy = rc->violated(vals); isEfficacious = efficacy > 1.e-6; } if (isEfficacious) { /** add cut */ SCIP_Bool infeasible; SCIP_CALL(SCIPaddCut(scip, sol, row, FALSE, /**< force cut */ &infeasible)); if (infeasible) *result = SCIP_CUTOFF; else if (*result != SCIP_CUTOFF) *result = SCIP_SEPARATED; } /** add cut to global pool */ SCIP_CALL(SCIPaddPoolCut(scip, row)); /** release the row */ SCIP_CALL(SCIPreleaseRow(scip, &row)); } else { if (isOptimalityCut) { efficacy = rc->violated(vals) / cutrow.twoNorm(); isEfficacious = efficacy > 0.05; } else { efficacy = rc->violated(vals); isEfficacious = efficacy > 1.e-6; } DSPdebugMessage("%s efficacy %e\n", isOptimalityCut ? "Opti" : "Feas", efficacy); if (isEfficacious == TRUE) *result = SCIP_INFEASIBLE; } #endif } /** free memory */ SCIPfreeMemoryArray(scip, &vals); return SCIP_OKAY; }
/** propagator to force finding the debugging solution */ static SCIP_DECL_PROPEXEC(propExecDebug) { /*lint --e{715}*/ SCIP_VAR** vars; int nvars; int i; assert(scip != NULL); assert(result != NULL); *result = SCIP_DIDNOTFIND; /* check if we are in the original problem and not in a sub MIP */ if( !isSolutionInMip(scip->set) ) return SCIP_OKAY; if( SCIPgetStage(scip) != SCIP_STAGE_SOLVING ) return SCIP_OKAY; /* check if the incumbent solution is at least as good as the debug solution, so we can stop to check the debug solution */ if( debugSolIsAchieved(scip->set) ) return SCIP_OKAY; #if 1 /* solve at least one LP */ if( SCIPgetNLPIterations(scip) == 0 ) return SCIP_OKAY; #endif vars = SCIPgetOrigVars(scip); nvars = SCIPgetNOrigVars(scip); for( i = 0; i < nvars; ++i ) { SCIP_Real solval; SCIP_Real lb; SCIP_Real ub; SCIP_Bool infeasible; SCIP_Bool fixed; SCIP_CALL( getSolutionValue(scip->set, vars[i], &solval) ); if( solval == SCIP_UNKNOWN ) /*lint !e777*/ { SCIPerrorMessage("original variable without debugging solution value\n"); SCIPABORT(); } lb = SCIPvarGetLbGlobal(vars[i]); ub = SCIPvarGetUbGlobal(vars[i]); if( SCIPisLT(scip, solval, lb) || SCIPisGT(scip, solval, ub) ) { SCIPerrorMessage("solution value %.15g of <%s> outside bounds loc=[%.15g,%.15g], glb=[%.15g,%.15g]\n", solval, SCIPvarGetName(vars[i]), lb, ub, SCIPvarGetLbGlobal(vars[i]), SCIPvarGetUbGlobal(vars[i])); SCIPABORT(); } SCIP_CALL( SCIPfixVar(scip, vars[i], solval, &infeasible, &fixed) ); if( infeasible ) *result = SCIP_CUTOFF; else if( fixed ) *result = SCIP_REDUCEDDOM; } return SCIP_OKAY; }
/** problem reading method of reader * * In order to determine the type of the file, we have to open it. Thus, it has to be opened * twice. This might be removed, but is likely to not hurt the performance too much. */ static SCIP_DECL_READERREAD(readerReadSol) { /*lint --e{715}*/ SCIP_FILE* file; char buffer[SCIP_MAXSTRLEN]; char *s; assert(reader != NULL); assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0); assert(result != NULL); *result = SCIP_DIDNOTRUN; if( SCIPgetStage(scip) < SCIP_STAGE_PROBLEM ) { SCIPerrorMessage("reading of solution file is only possible after a problem was created\n"); return SCIP_READERROR; } if( SCIPgetStage(scip) == SCIP_STAGE_SOLVED ) { SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was ignored - problem is already solved to optimality\n", filename); *result = SCIP_SUCCESS; return SCIP_OKAY; } /* open input file in order to determine type */ file = SCIPfopen(filename, "r"); if( file == NULL ) { SCIPerrorMessage("cannot open file <%s> for reading\n", filename); SCIPprintSysError(filename); return SCIP_NOFILE; } /* get next line */ if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL ) { SCIPerrorMessage("cannot parse file.\n"); return SCIP_READERROR; } /* close file */ SCIPfclose(file); /* decide whether it is xml */ s = buffer; /* skip spaces */ while( isspace((unsigned char)*s) ) ++s; if( s[0] == '<' && s[1] == '?' && s[2] == 'x' && s[3] == 'm' && s[4] == 'l' ) { /* read XML solution and add it to the solution pool */ SCIP_CALL( readXMLSol(scip, filename) ); } else { /* read the solution and add it to the solution pool */ SCIP_CALL( readSol(scip, filename) ); } *result = SCIP_SUCCESS; return SCIP_OKAY; }