/** tries to upgrade a linear constraint into a xyz constraint */ static SCIP_DECL_LINCONSUPGD(linconsUpgdXyz) { /*lint --e{715}*/ SCIP_Bool upgrade; assert(upgdcons != NULL); /* check, if linear constraint can be upgraded to xyz constraint */ upgrade = FALSE; /* TODO: put the constraint's properties here, in terms of the statistics given by nposbin, nnegbin, ... */ if( upgrade ) { SCIPdebugMessage("upgrading constraint <%s> to xyz constraint\n", SCIPconsGetName(cons)); /* create the bin Xyz constraint (an automatically upgraded constraint is always unmodifiable) */ assert(!SCIPconsIsModifiable(cons)); SCIP_CALL( SCIPcreateConsXyz(scip, upgdcons, SCIPconsGetName(cons), nvars, vars, vals, lhs, rhs, SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) ); } return SCIP_OKAY; }
/** presolving method of constraint handler */ static SCIP_DECL_CONSPRESOL(consPresolConjunction) { /*lint --e{715}*/ SCIP_CONSDATA* consdata; int c; int i; assert(result != NULL); *result = SCIP_DIDNOTFIND; /* all constraints in a conjunction constraint of the global problem can be added directly to the problem and * removed from the conjunction constraint; * an unmodifiable conjunction constraint can be deleted */ for( c = 0; c < nconss; ++c ) { consdata = SCIPconsGetData(conss[c]); assert(consdata != NULL); /* add all inactive constraints to the global problem */ for( i = 0; i < consdata->nconss; ++i ) { /* update check flag for sub constraints when upgrade takes place */ if( SCIPconsIsChecked(conss[c]) ) { /* make sure, the constraint is checked for feasibility */ SCIP_CALL( SCIPsetConsChecked(scip, consdata->conss[i], TRUE) ); } /* add constraint, if it is not active yet */ if( !SCIPconsIsActive(consdata->conss[i]) ) { SCIPdebugMessage("adding constraint <%s> from add conjunction <%s>\n", SCIPconsGetName(consdata->conss[i]), SCIPconsGetName(conss[c])); SCIP_CALL( SCIPaddCons(scip, consdata->conss[i]) ); *result = SCIP_SUCCESS; } /* release constraint because it will be removed from the conjunction constraint */ SCIP_CALL( SCIPreleaseCons(scip, &(consdata->conss[i])) ); } /* all constraints where removed, so we need to clear the array */ consdata->nconss = 0; /* delete conjunction constraint, if it is unmodifiable */ if( !SCIPconsIsModifiable(conss[c]) ) { SCIP_CALL( SCIPdelCons(scip, conss[c]) ); } } return SCIP_OKAY; }
/** constraint display method of constraint handler */ static SCIP_DECL_CONSPRINT(consPrintDisjunction) { /*lint --e{715}*/ SCIP_CONSDATA* consdata; int i; assert(scip != NULL); assert(conshdlr != NULL); assert(cons != NULL); consdata = SCIPconsGetData(cons); assert(consdata != NULL); SCIPinfoMessage(scip, file, "disjunction("); for( i = 0; i < consdata->nconss; ++i ) { if( i > 0 ) SCIPinfoMessage(scip, file, ", "); SCIPinfoMessage(scip, file, "<%s>", SCIPconsGetName(consdata->conss[i])); } SCIPinfoMessage(scip, file, ")"); 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; }
/** constraint activation notification method of constraint handler */ static SCIP_DECL_CONSACTIVE(consActiveSamediff) { /*lint --e{715}*/ SCIP_CONSDATA* consdata; assert(scip != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(cons != NULL); consdata = SCIPconsGetData(cons); assert(consdata != NULL); assert(consdata->npropagatedvars <= SCIPprobdataGetNVars(SCIPgetProbData(scip))); SCIPdebugMessage("activate constraint <%s> at node <%"SCIP_LONGINT_FORMAT"> in depth <%d>: ", SCIPconsGetName(cons), SCIPnodeGetNumber(consdata->node), SCIPnodeGetDepth(consdata->node)); SCIPdebug( consdataPrint(scip, consdata, NULL) ); if( consdata->npropagatedvars != SCIPprobdataGetNVars(SCIPgetProbData(scip)) ) { SCIPdebugMessage("-> mark constraint to be repropagated\n"); consdata->propagated = FALSE; SCIP_CALL( SCIPrepropagateNode(scip, consdata->node) ); } return SCIP_OKAY; }
/** constraint deactivation notification method of constraint handler */ static SCIP_DECL_CONSDEACTIVE(consDeactiveOrigbranch) { /*lint --e{715}*/ SCIP_CONSHDLRDATA* conshdlrData; assert(scip != NULL); assert(conshdlr != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(cons != NULL); conshdlrData = SCIPconshdlrGetData(conshdlr); assert(conshdlrData != NULL); assert(conshdlrData->stack != NULL || conshdlrData->nstack <= 1); assert(conshdlrData->nstack <= 1 || cons == conshdlrData->stack[conshdlrData->nstack-1]); assert(SCIPconsGetData(cons) != NULL); SCIPdebugMessage("Deactivating branch orig constraint: <%s> [stack size: %d].\n", SCIPconsGetName(cons), conshdlrData->nstack-1); /* remove constraint from the stack */ if( conshdlrData->nstack > 0 ) --(conshdlrData->nstack); return SCIP_OKAY; }
/** constraint deactivation notification method of constraint handler */ static SCIP_DECL_CONSDEACTIVE(consDeactiveSamediff) { /*lint --e{715}*/ SCIP_CONSDATA* consdata; SCIP_PROBDATA* probdata; assert(scip != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(cons != NULL); consdata = SCIPconsGetData(cons); assert(consdata != NULL); assert(consdata->propagated || SCIPgetNChildren(scip) == 0); probdata = SCIPgetProbData(scip); assert(probdata != NULL); /* check if all variables which are not fixed locally to zero are valid for this constraint/node */ assert( consdataCheck(scip, probdata, consdata) ); SCIPdebugMessage("deactivate constraint <%s> at node <%"SCIP_LONGINT_FORMAT"> in depth <%d>: ", SCIPconsGetName(cons), SCIPnodeGetNumber(consdata->node), SCIPnodeGetDepth(consdata->node)); SCIPdebug( consdataPrint(scip, consdata, NULL) ); /* set the number of propagated variables to current number of variables is SCIP */ consdata->npropagatedvars = SCIPprobdataGetNVars(probdata); /* check if all variables are valid for this constraint */ assert( consdataCheck(scip, probdata, consdata) ); return SCIP_OKAY; }
/** adds all constraints in conjunction constraints to the problem; disables unmodifiable conjunction constraints */ static SCIP_RETCODE addAllConss( SCIP* scip, /**< SCIP data structure */ SCIP_CONS** conss, /**< active conjunction constraints */ int nconss, /**< number of active conjunction constraints */ SCIP_RESULT* result /**< pointer to store the result */ ) { SCIP_CONSDATA* consdata; int c; int i; assert(result != NULL); for( c = 0; c < nconss; ++c ) { consdata = SCIPconsGetData(conss[c]); assert(consdata != NULL); /* add all inactive constraints to local subproblem */ for( i = 0; i < consdata->nconss; ++i ) { /* update check flag for sub constraints when upgrade takes place */ if( SCIPconsIsChecked(conss[c]) ) { /* make sure, the constraint is checked for feasibility */ SCIP_CALL( SCIPsetConsChecked(scip, consdata->conss[i], TRUE) ); } if( !SCIPconsIsActive(consdata->conss[i]) ) { SCIPdebugMessage("adding constraint <%s> from add conjunction <%s>\n", SCIPconsGetName(consdata->conss[i]), SCIPconsGetName(conss[c])); SCIP_CALL( SCIPaddConsLocal(scip, consdata->conss[i], NULL) ); *result = SCIP_CONSADDED; } } /* disable conjunction constraint, if it is unmodifiable */ if( !SCIPconsIsModifiable(conss[c]) ) { SCIP_CALL( SCIPdelConsLocal(scip, conss[c]) ); } } return SCIP_OKAY; }
/** fills the whole Decomp struct after the dec file has been read */ static SCIP_RETCODE fillDecompStruct( SCIP* scip, /**< SCIP data structure */ DECINPUT* decinput, /**< DEC reading data */ DEC_DECOMP* decomp, /**< DEC_DECOMP structure to fill */ SCIP_READERDATA* readerdata /**< reader data*/ ) { SCIP_HASHMAP* constoblock; SCIP_CONS** allcons; int i; int j; int nblockconss; int nconss; int nblocks; SCIP_Bool valid; assert(scip != NULL); assert(decinput != NULL); assert(decomp != NULL); assert(readerdata != NULL); valid = FALSE; allcons = SCIPgetConss(scip); nconss = SCIPgetNConss(scip); nblocks = decinput->nblocks; DECdecompSetPresolved(decomp, decinput->presolved); DECdecompSetNBlocks(decomp, nblocks); DECdecompSetDetector(decomp, NULL); DECdecompSetType(decomp, DEC_DECTYPE_ARROWHEAD, &valid); assert(valid); /* hashmaps */ SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(scip), nconss) ); for( i = 0; i < nconss; i ++ ) { SCIP_CALL( SCIPhashmapInsert(constoblock, allcons[i], (void*) (size_t) (nblocks+1)) ); } for( i = 0; i < nblocks; i ++ ) { nblockconss = readerdata->nblockconss[i]; for( j = 0; j < nblockconss; j ++ ) { /* hashmap */ SCIPdebugMessage("cons %s is in block %d\n", SCIPconsGetName(readerdata->blockconss[i][j]), i); SCIP_CALL( SCIPhashmapSetImage(constoblock, readerdata->blockconss[i][j], (void*) (size_t) (i+1)) ); } } SCIP_CALL( DECfilloutDecdecompFromConstoblock(scip, decomp, constoblock, nblocks, SCIPgetVars(scip), SCIPgetNVars(scip), SCIPgetConss(scip), SCIPgetNConss(scip), FALSE) ); return SCIP_OKAY; }
/** constraint copying method of constraint handler */ static SCIP_DECL_CONSCOPY(consCopyConjuction) { /*lint --e{715}*/ SCIP_CONSDATA* sourcedata; SCIP_CONS** sourceconss; SCIP_CONS** conss; int nconss; int c; sourcedata = SCIPconsGetData(sourcecons); assert(sourcedata != NULL); nconss = sourcedata->nconss; if( nconss == 0 && !SCIPconsIsModifiable(sourcecons) ) { *valid = TRUE; return SCIP_OKAY; } SCIP_CALL( SCIPallocBufferArray(scip, &conss, nconss) ); sourceconss = sourcedata->conss; /* copy each constraint one by one */ for( c = 0; c < nconss && (*valid); ++c ) { SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceconss[c], &conss[c], sourceconshdlr, varmap, consmap, SCIPconsGetName(sourceconss[c]), SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]), SCIPconsIsEnforced(sourceconss[c]), SCIPconsIsChecked(sourceconss[c]), SCIPconsIsPropagated(sourceconss[c]), SCIPconsIsLocal(sourceconss[c]), SCIPconsIsModifiable(sourceconss[c]), SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), SCIPconsIsStickingAtNode(sourceconss[c]), global, valid) ); assert(!(*valid) || conss[c] != NULL); } if( *valid ) { SCIP_CALL( SCIPcreateConsDisjunction(scip, cons, name, nconss, conss, initial, enforce, check, local, modifiable, dynamic) ); } SCIPfreeBufferArray(scip, &conss); return SCIP_OKAY; }
/** adds a bound change on an original variable found by propagation in the original problem * to the given origbranch constraint so that it will be transferred to the master problem */ SCIP_RETCODE GCGconsOrigbranchAddPropBoundChg( SCIP* scip, /**< SCIP data structure */ SCIP_CONS* cons, /**< origbranch constraint to which the bound change is added */ SCIP_VAR* var, /**< variable on which the bound change was performed */ SCIP_BOUNDTYPE boundtype, /**< bound type of the bound change */ SCIP_Real newbound /**< new bound of the variable after the bound change */ ) { SCIP_CONSDATA* consdata; assert(scip != NULL); assert(cons != NULL); assert(var != NULL); consdata = SCIPconsGetData(cons); assert(consdata != NULL); /* realloc the arrays, if needed */ if( consdata->npropbounds >= consdata->maxpropbounds ) { consdata->maxpropbounds = consdata->npropbounds+5; SCIP_CALL( SCIPreallocMemoryArray(scip, &(consdata->propvars), consdata->maxpropbounds) ); SCIP_CALL( SCIPreallocMemoryArray(scip, &(consdata->propboundtypes), consdata->maxpropbounds) ); SCIP_CALL( SCIPreallocMemoryArray(scip, &(consdata->propbounds), consdata->maxpropbounds) ); } SCIPdebugMessage("Bound change stored at branch orig constraint: <%s>.\n", SCIPconsGetName(cons)); /* store the new bound change */ consdata->propvars[consdata->npropbounds] = var; consdata->propboundtypes[consdata->npropbounds] = boundtype; consdata->propbounds[consdata->npropbounds] = newbound; consdata->npropbounds++; /* mark the corresponding master node to be repropagated */ if( consdata->mastercons != NULL ) { SCIP_CALL( SCIPrepropagateNode(GCGrelaxGetMasterprob(scip), GCGconsMasterbranchGetNode(consdata->mastercons)) ); } return SCIP_OKAY; }
/** transforms constraint data into data belonging to the transformed problem */ static SCIP_DECL_CONSTRANS(consTransDisjunction) { /*lint --e{715}*/ SCIP_CONSDATA* sourcedata; SCIP_CONSDATA* targetdata; /* get constraint data of source constraint */ sourcedata = SCIPconsGetData(sourcecons); assert(sourcedata != NULL); SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->conss, sourcedata->nconss) ); /* 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; }
/** constraint copying method of constraint handler */ static SCIP_DECL_CONSCOPY(consCopyStp) { /*lint --e{715}*/ const char* consname; SCIP_PROBDATA* probdata; GRAPH* graph; probdata = SCIPgetProbData(scip); assert(probdata != NULL); graph = SCIPprobdataGetGraph(probdata); assert(graph != NULL); consname = SCIPconsGetName(sourcecons); /* creates and captures a and constraint */ SCIP_CALL( SCIPcreateConsStp(scip, cons, consname, graph) ); *valid = TRUE; return SCIP_OKAY; }
/** transforms constraint data into data belonging to the transformed problem */ static SCIP_DECL_CONSTRANS(consTransConjunction) { /*lint --e{715}*/ SCIP_CONSDATA* sourcedata; SCIP_CONSDATA* targetdata; int c; /* create constraint data for target constraint */ SCIP_CALL( SCIPallocBlockMemory(scip, &targetdata) ); /* get constraint data of source constraint */ sourcedata = SCIPconsGetData(sourcecons); if( sourcedata->nconss > 0 ) { targetdata->consssize = sourcedata->nconss; targetdata->nconss = sourcedata->nconss; SCIP_CALL( SCIPallocBlockMemoryArray(scip, &targetdata->conss, targetdata->consssize) ); for( c = 0; c < sourcedata->nconss; ++c ) { SCIP_CALL( SCIPtransformCons(scip, sourcedata->conss[c], &targetdata->conss[c]) ); } } else { targetdata->conss = NULL; targetdata->consssize = 0; targetdata->nconss = 0; } /* 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; }
/** constraint activation notification method of constraint handler */ static SCIP_DECL_CONSACTIVE(consActiveOrigbranch) { /*lint --e{715}*/ SCIP_CONSHDLRDATA* conshdlrData; assert(scip != NULL); assert(conshdlr != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(cons != NULL); conshdlrData = SCIPconshdlrGetData(conshdlr); assert(conshdlrData != NULL); assert(conshdlrData->stack != NULL); assert(SCIPconsGetData(cons) != NULL); if( SCIPconsGetData(cons)->node == NULL ) SCIPconsGetData(cons)->node = SCIPgetRootNode(scip); SCIPdebugMessage("Activating branch orig constraint: <%s>[stack size: %d].\n", SCIPconsGetName(cons), conshdlrData->nstack+1); /* put constraint on the stack */ if( conshdlrData->nstack >= conshdlrData->maxstacksize ) { SCIP_CALL( SCIPreallocMemoryArray(scip, &(conshdlrData->stack), 2*(conshdlrData->maxstacksize)) ); conshdlrData->maxstacksize = 2*(conshdlrData->maxstacksize); SCIPdebugMessage("reallocating Memory for stack! %d --> %d\n", conshdlrData->maxstacksize/2, conshdlrData->maxstacksize); } /* put constraint on the stack */ assert(conshdlrData->stack != NULL); conshdlrData->stack[conshdlrData->nstack] = cons; ++(conshdlrData->nstack); return SCIP_OKAY; }
/** write the data optionally using the decomposition data */ static SCIP_RETCODE writeData( SCIP* scip, /**< SCIP data structure */ FILE* file, /**< File pointer to write to */ DEC_DECOMP* decdecomp /**< Decomposition pointer */ ) { SCIP_CONS*** subscipconss; SCIP_CONS** linkingconss; int* nsubscipconss; int nlinkingconss; int nblocks; SCIP_Bool presolved; int i; int j; assert(scip != NULL); assert(decdecomp != NULL); assert(DECdecompGetType(decdecomp) == DEC_DECTYPE_ARROWHEAD || DECdecompGetType(decdecomp) == DEC_DECTYPE_BORDERED || DECdecompGetType(decdecomp) == DEC_DECTYPE_DIAGONAL || DECdecompGetType(decdecomp) == DEC_DECTYPE_UNKNOWN || DECdecompGetType(decdecomp) == DEC_DECTYPE_STAIRCASE); SCIPdebugMessage("DEC_DECOMP Type: %s\n", DECgetStrType(DECdecompGetType(decdecomp))); /* if we don't have staicase, but something else, go through the blocks and create the indices */ /* subscip conss */ subscipconss = DECdecompGetSubscipconss(decdecomp); nsubscipconss = DECdecompGetNSubscipconss(decdecomp); assert(subscipconss != NULL); assert(nsubscipconss != NULL); /* linking cons */ linkingconss = DECdecompGetLinkingconss(decdecomp); nlinkingconss = DECdecompGetNLinkingconss(decdecomp); assert(nlinkingconss >= 0 && nlinkingconss < SCIPgetNConss(scip)); assert(linkingconss != NULL || nlinkingconss == 0 ); presolved = DECdecompGetPresolved(decdecomp); SCIPinfoMessage(scip, file, "PRESOLVED\n"); SCIPinfoMessage(scip, file, "%d\n", presolved ? 1 : 0); nblocks = DECdecompGetNBlocks(decdecomp); SCIPinfoMessage(scip, file, "NBLOCKS\n"); SCIPinfoMessage(scip, file, "%d\n", nblocks); for( i = 0; i < nblocks; i ++ ) { SCIPinfoMessage(scip, file, "BLOCK %d\n", i + 1); for( j = 0; j < nsubscipconss[i]; j ++ ) { SCIPinfoMessage(scip, file, "%s\n", SCIPconsGetName(subscipconss[i][j])); } } if( nlinkingconss > 0 ) { assert(linkingconss != NULL); /* for flexelint */ SCIPinfoMessage(scip, file, "MASTERCONSS\n"); for( i = 0; i < nlinkingconss; i ++ ) { SCIPinfoMessage(scip, file, "%s\n", SCIPconsGetName(linkingconss[i])); } } return SCIP_OKAY; }
/** reads the masterconss section */ static SCIP_RETCODE readMasterconss( SCIP* scip, /**< SCIP data structure */ DECINPUT* decinput, /**< DEC reading data */ SCIP_READERDATA* readerdata /**< reader data */ ) { assert(scip != NULL); assert(decinput != NULL); assert(readerdata != NULL); while( getNextToken(decinput) ) { SCIP_CONS* cons; /* check if we reached a new section */ if( isNewSection(scip, decinput) ) break; /* the token must be the name of an existing constraint */ cons = SCIPfindCons(scip, decinput->token); if( cons == NULL ) { syntaxError(scip, decinput, "unknown constraint in masterconss section"); break; } else { if( !SCIPhashmapExists( readerdata->constoblock, cons) ) { SCIPwarningMessage(scip, "Cons <%s> has been deleted by presolving, skipping.\n", SCIPconsGetName(cons)); continue; } assert(SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*)(size_t) LINKINGVALUE); SCIPdebugMessage("cons %s is linking constraint\n", decinput->token); } } return SCIP_OKAY; }
/** domain propagation method of constraint handler */ static SCIP_DECL_CONSPROP(consPropSamediff) { /*lint --e{715}*/ SCIP_PROBDATA* probdata; SCIP_CONSDATA* consdata; SCIP_VAR** vars; int nvars; int c; assert(scip != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); SCIPdebugMessage("propagation constraints of constraint handler <"CONSHDLR_NAME">\n"); probdata = SCIPgetProbData(scip); assert(probdata != NULL); vars = SCIPprobdataGetVars(probdata); nvars = SCIPprobdataGetNVars(probdata); *result = SCIP_DIDNOTFIND; for( c = 0; c < nconss; ++c ) { consdata = SCIPconsGetData(conss[c]); #ifndef NDEBUG { /* check if there are no equal consdatas */ SCIP_CONSDATA* consdata2; int i; for( i = c+1; i < nconss; ++i ) { consdata2 = SCIPconsGetData(conss[i]); assert( !(consdata->itemid1 == consdata2->itemid1 && consdata->itemid2 == consdata2->itemid2 && consdata->type == consdata2->type) ); assert( !(consdata->itemid1 == consdata2->itemid2 && consdata->itemid2 == consdata2->itemid1 && consdata->type == consdata2->type) ); } } #endif if( !consdata->propagated ) { SCIPdebugMessage("propagate constraint <%s> ", SCIPconsGetName(conss[c])); SCIPdebug( consdataPrint(scip, consdata, NULL) ); SCIP_CALL( consdataFixVariables(scip, consdata, vars, nvars, result) ); consdata->npropagations++; if( *result != SCIP_CUTOFF ) { consdata->propagated = TRUE; consdata->npropagatedvars = nvars; } else break; } /* check if constraint is completely propagated */ assert( consdataCheck(scip, probdata, consdata) ); } return SCIP_OKAY; }
/** constraint copying method of constraint handler */ static SCIP_DECL_CONSCOPY(consCopyConjunction) { /*lint --e{715}*/ SCIP_CONSDATA* sourcedata; SCIP_CONS** sourceconss; SCIP_CONS** conss; int nconss; int c; *valid = TRUE; sourcedata = SCIPconsGetData(sourcecons); assert(sourcedata != NULL); sourceconss = sourcedata->conss; nconss = sourcedata->nconss; if( nconss > 0 ) { assert(sourceconss != NULL); SCIP_CALL( SCIPallocBufferArray(scip, &conss, nconss) ); /* copy each constraint one by one */ for( c = 0; c < nconss && (*valid); ++c ) { SCIP_CALL( SCIPgetConsCopy(sourcescip, scip, sourceconss[c], &conss[c], SCIPconsGetHdlr(sourceconss[c]), varmap, consmap, SCIPconsGetName(sourceconss[c]), SCIPconsIsInitial(sourceconss[c]), SCIPconsIsSeparated(sourceconss[c]), SCIPconsIsEnforced(sourceconss[c]), SCIPconsIsChecked(sourceconss[c]), SCIPconsIsPropagated(sourceconss[c]), SCIPconsIsLocal(sourceconss[c]), SCIPconsIsModifiable(sourceconss[c]), SCIPconsIsDynamic(sourceconss[c]), SCIPconsIsRemovable(sourceconss[c]), SCIPconsIsStickingAtNode(sourceconss[c]), global, valid) ); assert(!(*valid) || conss[c] != NULL); } if( *valid ) { if( name == NULL ) { SCIP_CALL( SCIPcreateConsConjunction(scip, cons, SCIPconsGetName(sourcecons), nconss, conss, enforce, check, local, modifiable, dynamic) ); } else { SCIP_CALL( SCIPcreateConsConjunction(scip, cons, name, nconss, conss, enforce, check, local, modifiable, dynamic) ); } } /* release the copied constraints */ for( c = (*valid ? c - 1 : c - 2); c >= 0; --c ) { assert(conss[c] != NULL); SCIP_CALL( SCIPreleaseCons(scip, &conss[c]) ); } SCIPfreeBufferArray(scip, &conss); } return SCIP_OKAY; }
/** checks all constraints in conjunction constraints for feasibility */ static SCIP_RETCODE checkAllConss( SCIP* scip, /**< SCIP data structure */ SCIP_CONS** conss, /**< active conjunction constraints */ int nconss, /**< number of active conjunction constraints */ SCIP_SOL* sol, /**< solution to check */ SCIP_Bool checkintegrality, /**< has integrality to be checked? */ SCIP_Bool checklprows, /**< have current LP rows to be checked? */ SCIP_Bool printreason, /**< should the reason for the violation be printed? */ SCIP_RESULT* result /**< pointer to store the result */ ) { SCIP_CONSDATA* consdata; int c; int i; assert(result != NULL); for( c = 0; c < nconss && *result == SCIP_FEASIBLE; ++c ) { consdata = SCIPconsGetData(conss[c]); assert(consdata != NULL); /* check all constraints */ for( i = 0; i < consdata->nconss && *result == SCIP_FEASIBLE; ++i ) { SCIP_CALL( SCIPcheckCons(scip, consdata->conss[i], sol, checkintegrality, checklprows, printreason, result) ); assert(*result == SCIP_FEASIBLE || *result == SCIP_INFEASIBLE); } if( printreason && *result == SCIP_INFEASIBLE ) { SCIPinfoMessage(scip, NULL, "conjunction constraint %s is violated, at least the sub-constraint %s is violated by this given solution\n", SCIPconsGetName(conss[c]), SCIPconsGetName(consdata->conss[i-1])); SCIPdebug( SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) ) ); } } return SCIP_OKAY; }
/** LP solution separation method of separator */ static SCIP_DECL_SEPAEXECLP(sepaExeclpRapidlearning) {/*lint --e{715}*/ SCIP* subscip; /* the subproblem created by rapid learning */ SCIP_SEPADATA* sepadata; /* separator's private data */ SCIP_VAR** vars; /* original problem's variables */ SCIP_VAR** subvars; /* subproblem's variables */ SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */ SCIP_HASHMAP* varmapbw; /* mapping of sub-SCIP variables to SCIP variables */ SCIP_CONSHDLR** conshdlrs; /* array of constraint handler's that might that might obtain conflicts */ int* oldnconss; /* number of constraints without rapid learning conflicts */ SCIP_Longint nodelimit; /* node limit for the subproblem */ SCIP_Real timelimit; /* time limit for the subproblem */ SCIP_Real memorylimit; /* memory limit for the subproblem */ int nconshdlrs; /* size of conshdlr and oldnconss array */ int nfixedvars; /* number of variables that could be fixed by rapid learning */ int nvars; /* number of variables */ int restartnum; /* maximal number of conflicts that should be created */ int i; /* counter */ SCIP_Bool success; /* was problem creation / copying constraint successful? */ SCIP_RETCODE retcode; /* used for catching sub-SCIP errors in debug mode */ int nconflicts; /* statistic: number of conflicts applied */ int nbdchgs; /* statistic: number of bound changes applied */ int n1startinfers; /* statistic: number of one side infer values */ int n2startinfers; /* statistic: number of both side infer values */ SCIP_Bool soladded; /* statistic: was a new incumbent found? */ SCIP_Bool dualboundchg; /* statistic: was a new dual bound found? */ SCIP_Bool disabledualreductions; /* TRUE, if dual reductions in sub-SCIP are not valid for original SCIP, * e.g., because a constraint could not be copied or a primal solution * could not be copied back */ int ndiscvars; soladded = FALSE; assert(sepa != NULL); assert(scip != NULL); assert(result != NULL); *result = SCIP_DIDNOTRUN; ndiscvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)+SCIPgetNImplVars(scip); /* only run when still not fixed binary variables exists */ if( ndiscvars == 0 ) return SCIP_OKAY; /* get separator's data */ sepadata = SCIPsepaGetData(sepa); assert(sepadata != NULL); /* only run for integer programs */ if( !sepadata->contvars && ndiscvars != SCIPgetNVars(scip) ) return SCIP_OKAY; /* only run if there are few enough continuous variables */ if( sepadata->contvars && SCIPgetNContVars(scip) > sepadata->contvarsquot * SCIPgetNVars(scip) ) return SCIP_OKAY; /* do not run if pricers are present */ if( SCIPgetNActivePricers(scip) > 0 ) return SCIP_OKAY; /* if the separator should be exclusive to the root node, this prevents multiple calls due to restarts */ if( SCIPsepaGetFreq(sepa) == 0 && SCIPsepaGetNCalls(sepa) > 0) return SCIP_OKAY; /* call separator at most once per node */ if( SCIPsepaGetNCallsAtNode(sepa) > 0 ) return SCIP_OKAY; /* do not call rapid learning, if the problem is too big */ if( SCIPgetNVars(scip) > sepadata->maxnvars || SCIPgetNConss(scip) > sepadata->maxnconss ) return SCIP_OKAY; if( SCIPisStopped(scip) ) return SCIP_OKAY; *result = SCIP_DIDNOTFIND; SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) ); /* initializing the subproblem */ SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) ); SCIP_CALL( SCIPcreate(&subscip) ); SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) ); success = FALSE; /* copy the subproblem */ SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "rapid", FALSE, FALSE, &success) ); if( sepadata->copycuts ) { /** copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */ SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, FALSE) ); } for( i = 0; i < nvars; i++ ) subvars[i] = (SCIP_VAR*) (size_t) SCIPhashmapGetImage(varmapfw, vars[i]); SCIPhashmapFree(&varmapfw); /* this avoids dual presolving */ if( !success ) { for( i = 0; i < nvars; i++ ) { SCIP_CALL( SCIPaddVarLocks(subscip, subvars[i], 1, 1 ) ); } } SCIPdebugMessage("Copying SCIP was%s successful.\n", success ? "" : " not"); /* mimic an FD solver: DFS, no LP solving, 1-FUIP instead of all-FUIP */ SCIP_CALL( SCIPsetIntParam(subscip, "lp/solvefreq", -1) ); SCIP_CALL( SCIPsetIntParam(subscip, "conflict/fuiplevels", 1) ); SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/dfs/stdpriority", INT_MAX/4) ); SCIP_CALL( SCIPsetBoolParam(subscip, "constraints/disableenfops", TRUE) ); SCIP_CALL( SCIPsetIntParam(subscip, "propagating/pseudoobj/freq", -1) ); /* use inference branching */ SCIP_CALL( SCIPsetBoolParam(subscip, "branching/inference/useweightedsum", FALSE) ); /* only create short conflicts */ SCIP_CALL( SCIPsetRealParam(subscip, "conflict/maxvarsfac", 0.05) ); /* set limits for the subproblem */ nodelimit = SCIPgetNLPIterations(scip); nodelimit = MAX(sepadata->minnodes, nodelimit); nodelimit = MIN(sepadata->maxnodes, nodelimit); restartnum = 1000; /* check whether there is enough time and memory left */ SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) ); if( !SCIPisInfinity(scip, timelimit) ) timelimit -= SCIPgetSolvingTime(scip); SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) ); if( !SCIPisInfinity(scip, memorylimit) ) memorylimit -= SCIPgetMemUsed(scip)/1048576.0; if( timelimit <= 0.0 || memorylimit <= 0.0 ) goto TERMINATE; SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit/5) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) ); SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) ); SCIP_CALL( SCIPsetIntParam(subscip, "limits/restarts", 0) ); SCIP_CALL( SCIPsetIntParam(subscip, "conflict/restartnum", restartnum) ); /* forbid recursive call of heuristics and separators solving subMIPs */ SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) ); /* disable cutting plane separation */ SCIP_CALL( SCIPsetSeparating(subscip, SCIP_PARAMSETTING_OFF, TRUE) ); /* disable expensive presolving */ SCIP_CALL( SCIPsetPresolving(subscip, SCIP_PARAMSETTING_FAST, TRUE) ); /* do not abort subproblem on CTRL-C */ SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) ); #ifndef SCIP_DEBUG /* disable output to console */ SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) ); #endif /* add an objective cutoff */ SCIP_CALL( SCIPsetObjlimit(subscip, SCIPgetUpperbound(scip)) ); /* create the variable mapping hash map */ SCIP_CALL( SCIPhashmapCreate(&varmapbw, SCIPblkmem(scip), SCIPcalcHashtableSize(5 * nvars)) ); /* store reversing mapping of variables */ SCIP_CALL( SCIPtransformProb(subscip) ); for( i = 0; i < nvars; ++i) { SCIP_CALL( SCIPhashmapInsert(varmapbw, SCIPvarGetTransVar(subvars[i]), vars[i]) ); } /** allocate memory for constraints storage. Each constraint that will be created from now on will be a conflict. * Therefore, we need to remember oldnconss to get the conflicts from the FD search. */ nconshdlrs = 4; SCIP_CALL( SCIPallocBufferArray(scip, &conshdlrs, nconshdlrs) ); SCIP_CALL( SCIPallocBufferArray(scip, &oldnconss, nconshdlrs) ); /* store number of constraints before rapid learning search */ conshdlrs[0] = SCIPfindConshdlr(subscip, "bounddisjunction"); conshdlrs[1] = SCIPfindConshdlr(subscip, "setppc"); conshdlrs[2] = SCIPfindConshdlr(subscip, "linear"); conshdlrs[3] = SCIPfindConshdlr(subscip, "logicor"); /* redundant constraints might be eliminated in presolving */ SCIP_CALL( SCIPpresolve(subscip)); for( i = 0; i < nconshdlrs; ++i) { if( conshdlrs[i] != NULL ) oldnconss[i] = SCIPconshdlrGetNConss(conshdlrs[i]); } nfixedvars = SCIPgetNFixedVars(scip); /* solve the subproblem */ retcode = SCIPsolve(subscip); /* Errors in solving the subproblem should not kill the overall solving process * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */ if( retcode != SCIP_OKAY ) { #ifndef NDEBUG SCIP_CALL( retcode ); #endif SCIPwarningMessage("Error while solving subproblem in rapid learning separator; sub-SCIP terminated with code <%d>\n",retcode); } /* abort solving, if limit of applied conflicts is reached */ if( SCIPgetNConflictConssApplied(subscip) >= restartnum ) { SCIPdebugMessage("finish after %lld successful conflict calls.\n", SCIPgetNConflictConssApplied(subscip)); } /* if the first 20% of the solution process were successful, proceed */ else if( (sepadata->applyprimalsol && SCIPgetNSols(subscip) > 0 && SCIPisFeasLT(scip, SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip) ) ) || (sepadata->applybdchgs && SCIPgetNFixedVars(subscip) > nfixedvars) || (sepadata->applyconflicts && SCIPgetNConflictConssApplied(subscip) > 0) ) { SCIPdebugMessage("proceed solving after the first 20%% of the solution process, since:\n"); if( SCIPgetNSols(subscip) > 0 && SCIPisFeasLE(scip, SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip) ) ) { SCIPdebugMessage(" - there was a better solution (%f < %f)\n",SCIPgetUpperbound(subscip), SCIPgetUpperbound(scip)); } if( SCIPgetNFixedVars(subscip) > nfixedvars ) { SCIPdebugMessage(" - there were %d variables fixed\n", SCIPgetNFixedVars(scip)-nfixedvars ); } if( SCIPgetNConflictConssFound(subscip) > 0 ) { SCIPdebugMessage(" - there were %lld conflict constraints created\n", SCIPgetNConflictConssApplied(subscip)); } /* set node limit to 100% */ SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nodelimit) ); /* solve the subproblem */ retcode = SCIPsolve(subscip); /* Errors in solving the subproblem should not kill the overall solving process * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */ if( retcode != SCIP_OKAY ) { #ifndef NDEBUG SCIP_CALL( retcode ); #endif SCIPwarningMessage("Error while solving subproblem in rapid learning separator; sub-SCIP terminated with code <%d>\n",retcode); } } else { SCIPdebugMessage("do not proceed solving after the first 20%% of the solution process.\n"); } #ifdef SCIP_DEBUG SCIP_CALL( SCIPprintStatistics(subscip, NULL) ); #endif disabledualreductions = FALSE; /* check, whether a solution was found */ if( sepadata->applyprimalsol && SCIPgetNSols(subscip) > 0 && SCIPfindHeur(scip, "trysol") != NULL ) { SCIP_HEUR* heurtrysol; SCIP_SOL** subsols; int nsubsols; /* check, whether a solution was found; * due to numerics, it might happen that not all solutions are feasible -> try all solutions until was declared to be feasible */ nsubsols = SCIPgetNSols(subscip); subsols = SCIPgetSols(subscip); soladded = FALSE; heurtrysol = SCIPfindHeur(scip, "trysol"); /* sequentially add solutions to trysol heuristic */ for( i = 0; i < nsubsols && !soladded; ++i ) { SCIPdebugMessage("Try to create new solution by copying subscip solution.\n"); SCIP_CALL( createNewSol(scip, subscip, subvars, heurtrysol, subsols[i], &soladded) ); } if( !soladded || !SCIPisEQ(scip, SCIPgetSolOrigObj(subscip, subsols[i-1]), SCIPgetSolOrigObj(subscip, subsols[0])) ) disabledualreductions = TRUE; } /* if the sub problem was solved completely, we update the dual bound */ dualboundchg = FALSE; if( sepadata->applysolved && !disabledualreductions && (SCIPgetStatus(subscip) == SCIP_STATUS_OPTIMAL || SCIPgetStatus(subscip) == SCIP_STATUS_INFEASIBLE) ) { /* we need to multiply the dualbound with the scaling factor and add the offset, * because this information has been disregarded in the sub-SCIP */ SCIPdebugMessage("Update old dualbound %g to new dualbound %g.\n", SCIPgetDualbound(scip), SCIPgetTransObjscale(scip) * SCIPgetDualbound(subscip) + SCIPgetTransObjoffset(scip)); SCIP_CALL( SCIPupdateLocalDualbound(scip, SCIPgetDualbound(subscip) * SCIPgetTransObjscale(scip) + SCIPgetTransObjoffset(scip)) ); dualboundchg = TRUE; } /* check, whether conflicts were created */ nconflicts = 0; if( sepadata->applyconflicts && !disabledualreductions && SCIPgetNConflictConssApplied(subscip) > 0 ) { SCIP_HASHMAP* consmap; int hashtablesize; assert(SCIPgetNConflictConssApplied(subscip) < (SCIP_Longint) INT_MAX); hashtablesize = (int) SCIPgetNConflictConssApplied(subscip); assert(hashtablesize < INT_MAX/5); hashtablesize *= 5; /* create the variable mapping hash map */ SCIP_CALL( SCIPhashmapCreate(&consmap, SCIPblkmem(scip), SCIPcalcHashtableSize(hashtablesize)) ); /* loop over all constraint handlers that might contain conflict constraints */ for( i = 0; i < nconshdlrs; ++i) { /* copy constraints that have been created in FD run */ if( conshdlrs[i] != NULL && SCIPconshdlrGetNConss(conshdlrs[i]) > oldnconss[i] ) { SCIP_CONS** conss; int c; int nconss; nconss = SCIPconshdlrGetNConss(conshdlrs[i]); conss = SCIPconshdlrGetConss(conshdlrs[i]); /* loop over all constraints that have been added in sub-SCIP run, these are the conflicts */ for( c = oldnconss[i]; c < nconss; ++c) { SCIP_CONS* cons; SCIP_CONS* conscopy; cons = conss[c]; assert(cons != NULL); success = FALSE; SCIP_CALL( SCIPgetConsCopy(subscip, scip, cons, &conscopy, conshdlrs[i], varmapbw, consmap, NULL, SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), TRUE, FALSE, SCIPconsIsDynamic(cons), SCIPconsIsRemovable(cons), FALSE, TRUE, &success) ); if( success ) { nconflicts++; SCIP_CALL( SCIPaddCons(scip, conscopy) ); SCIP_CALL( SCIPreleaseCons(scip, &conscopy) ); } else { SCIPdebugMessage("failed to copy conflict constraint %s back to original SCIP\n", SCIPconsGetName(cons)); } } } } SCIPhashmapFree(&consmap); } /* check, whether tighter global bounds were detected */ nbdchgs = 0; if( sepadata->applybdchgs && !disabledualreductions ) for( i = 0; i < nvars; ++i ) { SCIP_Bool infeasible; SCIP_Bool tightened; assert(SCIPisLE(scip, SCIPvarGetLbGlobal(vars[i]), SCIPvarGetLbGlobal(subvars[i]))); assert(SCIPisLE(scip, SCIPvarGetLbGlobal(subvars[i]), SCIPvarGetUbGlobal(subvars[i]))); assert(SCIPisLE(scip, SCIPvarGetUbGlobal(subvars[i]), SCIPvarGetUbGlobal(vars[i]))); /* update the bounds of the original SCIP, if a better bound was proven in the sub-SCIP */ SCIP_CALL( SCIPtightenVarUb(scip, vars[i], SCIPvarGetUbGlobal(subvars[i]), FALSE, &infeasible, &tightened) ); if( tightened ) nbdchgs++; SCIP_CALL( SCIPtightenVarLb(scip, vars[i], SCIPvarGetLbGlobal(subvars[i]), FALSE, &infeasible, &tightened) ); if( tightened ) nbdchgs++; } n1startinfers = 0; n2startinfers = 0; /* install start values for inference branching */ if( sepadata->applyinfervals && (!sepadata->reducedinfer || soladded || nbdchgs+nconflicts > 0) ) { for( i = 0; i < nvars; ++i ) { SCIP_Real downinfer; SCIP_Real upinfer; SCIP_Real downvsids; SCIP_Real upvsids; SCIP_Real downconflen; SCIP_Real upconflen; /* copy downwards branching statistics */ downvsids = SCIPgetVarVSIDS(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS); downconflen = SCIPgetVarAvgConflictlength(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS); downinfer = SCIPgetVarAvgInferences(subscip, subvars[i], SCIP_BRANCHDIR_DOWNWARDS); /* copy upwards branching statistics */ upvsids = SCIPgetVarVSIDS(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS); upconflen = SCIPgetVarAvgConflictlength(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS); upinfer = SCIPgetVarAvgInferences(subscip, subvars[i], SCIP_BRANCHDIR_UPWARDS); /* memorize statistics */ if( downinfer+downconflen+downvsids > 0.0 || upinfer+upconflen+upvsids != 0 ) n1startinfers++; if( downinfer+downconflen+downvsids > 0.0 && upinfer+upconflen+upvsids != 0 ) n2startinfers++; SCIP_CALL( SCIPinitVarBranchStats(scip, vars[i], 0.0, 0.0, downvsids, upvsids, downconflen, upconflen, downinfer, upinfer, 0.0, 0.0) ); } } SCIPdebugPrintf("XXX Rapidlearning added %d conflicts, changed %d bounds, %s primal solution, %s dual bound improvement.\n", nconflicts, nbdchgs, soladded ? "found" : "no", dualboundchg ? "found" : "no"); SCIPdebugPrintf("YYY Infervalues initialized on one side: %5.2f %% of variables, %5.2f %% on both sides\n", 100.0 * n1startinfers/(SCIP_Real)nvars, 100.0 * n2startinfers/(SCIP_Real)nvars); /* change result pointer */ if( nconflicts > 0 || dualboundchg ) *result = SCIP_CONSADDED; else if( nbdchgs > 0 ) *result = SCIP_REDUCEDDOM; /* free local data */ SCIPfreeBufferArray(scip, &oldnconss); SCIPfreeBufferArray(scip, &conshdlrs); SCIPhashmapFree(&varmapbw); TERMINATE: /* free subproblem */ SCIPfreeBufferArray(scip, &subvars); SCIP_CALL( SCIPfree(&subscip) ); return SCIP_OKAY; }
/** writes problem data to file with given reader or returns SCIP_DIDNOTRUN */ SCIP_RETCODE SCIPreaderWrite( SCIP_READER* reader, /**< reader */ SCIP_PROB* prob, /**< problem data */ SCIP_SET* set, /**< global SCIP settings */ FILE* file, /**< output file (or NULL for standard output) */ const char* extension, /**< file format */ SCIP_Bool genericnames, /**< using generic variable and constraint names? */ SCIP_RESULT* result /**< pointer to store the result of the callback method */ ) { SCIP_RETCODE retcode; assert(reader != NULL); assert(set != NULL); assert(extension != NULL); assert(result != NULL); /* check, if reader is applicable on the given file */ if( readerIsApplicable(reader, extension) && reader->readerwrite != NULL ) { SCIP_VAR** vars; int nvars; SCIP_VAR** fixedvars; int nfixedvars; SCIP_CONS** conss; int nconss; int i; SCIP_CONS* cons; char* name; const char* consname; const char** varnames; const char** fixedvarnames; const char** consnames; varnames = NULL; fixedvarnames = NULL; consnames = NULL; vars = prob->vars; nvars = prob->nvars; fixedvars = prob->fixedvars; nfixedvars = prob->nfixedvars; /* case of the transformed problem, we want to write currently valid problem */ if( prob->transformed ) { SCIP_CONSHDLR** conshdlrs; int nconshdlrs; conshdlrs = set->conshdlrs; nconshdlrs = set->nconshdlrs; /* collect number of constraints which have to be enforced; these are the constraints which currency (locally) * enabled; these also includes the local constraints */ nconss = 0; for( i = 0; i < nconshdlrs; ++i ) { /* check if all constraints of the constraint handler should be written */ if( set->write_allconss ) nconss += SCIPconshdlrGetNConss(conshdlrs[i]); else nconss += SCIPconshdlrGetNEnfoConss(conshdlrs[i]); } SCIPdebugMessage("Writing %d constraints.\n", nconss); SCIP_ALLOC( BMSallocMemoryArray(&conss, nconss) ); /* copy the constraints */ nconss = 0; for( i = 0; i < nconshdlrs; ++i ) { SCIP_CONS** conshdlrconss; int nconshdlrconss; int c; /* check if all constraints of the constraint handler should be written */ if( set->write_allconss ) { conshdlrconss = SCIPconshdlrGetConss(conshdlrs[i]); nconshdlrconss = SCIPconshdlrGetNConss(conshdlrs[i]); } else { conshdlrconss = SCIPconshdlrGetEnfoConss(conshdlrs[i]); nconshdlrconss = SCIPconshdlrGetNEnfoConss(conshdlrs[i]); } SCIPdebugMessage("Conshdlr <%s> has %d constraints to write from all in all %d constraints.\n", SCIPconshdlrGetName(conshdlrs[i]), nconshdlrconss, SCIPconshdlrGetNConss(conshdlrs[i])); for( c = 0; c < nconshdlrconss; ++c ) { conss[nconss] = conshdlrconss[c]; nconss++; } } } else { conss = prob->conss; nconss = prob->nconss; } if( genericnames ) { SCIP_VAR* var; int size; /* save variable and constraint names and replace these names by generic names */ /* allocate memory for saving the original variable and constraint names */ SCIP_ALLOC( BMSallocMemoryArray(&varnames, nvars) ); SCIP_ALLOC( BMSallocMemoryArray(&fixedvarnames, nfixedvars) ); SCIP_ALLOC( BMSallocMemoryArray(&consnames, nconss) ); /* compute length of the generic variable names: * - nvars + 1 to avoid log of zero * - +3 (zero at end + 'x' + 1 because we round down) * Example: 10 -> need 4 chars ("x10\0") */ size = (int) log10(nvars+1.0) + 3; for( i = 0; i < nvars; ++i ) { var = vars[i]; varnames[i] = SCIPvarGetName(var); SCIP_ALLOC( BMSallocMemoryArray(&name, size) ); (void) SCIPsnprintf(name, size, "x%d", i + set->write_genoffset); SCIPvarSetNamePointer(var, name); } /* compute length of the generic variable names */ size = (int) log10(nfixedvars+1.0) + 3; for( i = 0; i < nfixedvars; ++i ) { var = fixedvars[i]; fixedvarnames[i] = SCIPvarGetName(var); SCIP_ALLOC( BMSallocMemoryArray(&name, size) ); (void) SCIPsnprintf(name, size, "y%d", i); SCIPvarSetNamePointer(var, name); } /* compute length of the generic constraint names */ size = (int) log10(nconss+1.0) + 3; for( i = 0; i < nconss; ++i ) { cons = conss[i]; consnames[i] = SCIPconsGetName(cons); SCIP_ALLOC( BMSallocMemoryArray(&name, size) ); (void) SCIPsnprintf(name, size, "c%d", i); SCIPconsSetNamePointer(cons, name); } } /* call reader to write problem */ retcode = reader->readerwrite(set->scip, reader, file, prob->name, prob->probdata, prob->transformed, prob->transformed ? SCIP_OBJSENSE_MINIMIZE : prob->objsense, prob->objscale, prob->objoffset, vars, nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars, fixedvars, nfixedvars, prob->startnvars, conss, nconss, prob->maxnconss, prob->startnconss, genericnames, result); /* reset variable and constraint names to original names */ if( genericnames ) { assert(varnames != NULL); assert(fixedvarnames != NULL); assert(consnames != NULL); for( i = 0; i < nvars; ++i ) resetVarname(vars[i], varnames[i]); for( i = 0; i < nfixedvars; ++i ) resetVarname(fixedvars[i], fixedvarnames[i]); for( i = 0; i < nconss; ++i ) { cons = conss[i]; /* get pointer to temporary generic name and free the memory */ consname = SCIPconsGetName(cons); BMSfreeMemory(&consname); /* reset name */ SCIPconsSetNamePointer(cons, consnames[i]); } /* free memory */ BMSfreeMemoryArray(&varnames); BMSfreeMemoryArray(&fixedvarnames); BMSfreeMemoryArray(&consnames); } if( prob->transformed ) { /* free memory */ BMSfreeMemoryArray(&conss); } } else { *result = SCIP_DIDNOTRUN; retcode = SCIP_OKAY; } /* check for reader errors */ if( retcode == SCIP_WRITEERROR ) return retcode; SCIP_CALL( retcode ); return SCIP_OKAY; }
/** fills the whole Decomp struct after the blk file has been read */ static SCIP_RETCODE fillDecompStruct( SCIP* scip, /**< SCIP data structure */ BLKINPUT* blkinput, /**< blk reading data */ DEC_DECOMP* decomp, /**< DEC_DECOMP structure to fill */ SCIP_READERDATA* readerdata /**< reader data*/ ) { SCIP_HASHMAP* constoblock; SCIP_CONS** allcons; SCIP_VAR** consvars; int i; int j; int nvars; int blocknr; int nconss; int nblocks; SCIP_Bool valid; assert(scip != NULL); assert(blkinput != NULL); assert(readerdata != NULL); allcons = SCIPgetConss(scip); nvars = SCIPgetNVars(scip); nconss = SCIPgetNConss(scip); nblocks = blkinput->nblocks; DECdecompSetPresolved(decomp, blkinput->presolved); DECdecompSetNBlocks(decomp, nblocks); DECdecompSetDetector(decomp, NULL); DECdecompSetType(decomp, DEC_DECTYPE_ARROWHEAD, &valid); assert(valid); /* hashmaps */ SCIP_CALL( SCIPhashmapCreate(&constoblock, SCIPblkmem(scip), nconss) ); SCIP_CALL( SCIPallocMemoryArray(scip, &consvars, nvars) ); /* assign constraints to blocks or declare them linking */ for( i = 0; i < nconss; i ++ ) { SCIP_CONS* cons; cons = allcons[i]; if( SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*) (size_t) LINKINGVALUE ) { SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (nblocks+1)) ); SCIPdebugMessage("cons %s is linking\n", SCIPconsGetName(cons)); } /* check whether all variables in the constraint belong to one block */ else { int nconsvars; nconsvars = SCIPgetNVarsXXX(scip, cons); assert(nconsvars < nvars); SCIP_CALL( SCIPgetVarsXXX(scip, cons, consvars, nvars) ); blocknr = -1; /* find the first unique assignment of a contained variable to a block */ for( j = 0; j < nconsvars; ++j ) { /* if a contained variables is directly transferred to the master, the constraint is a linking constraint */ if( readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])] == NOVALUE ) { blocknr = -1; break; } /* assign the constraint temporarily to the block of the variable, if it is unique */ if( blocknr == -1 && readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])] != LINKINGVALUE ) { blocknr = readerdata->varstoblock[SCIPvarGetProbindex(consvars[j])]; } } if( blocknr != -1 ) { int varidx; int varblock; /* check whether all contained variables are copied into the assigned block; * if not, the constraint is treated as a linking constraint */ for( j = 0; j < nconsvars; ++j ) { varidx = SCIPvarGetProbindex(consvars[j]); varblock = readerdata->varstoblock[varidx]; assert(varblock != NOVALUE); if( varblock != LINKINGVALUE && varblock != blocknr ) { blocknr = -1; break; } else if( varblock == LINKINGVALUE ) { int k; for( k = 0; k < readerdata->nlinkingvarsblocks[varidx]; ++k ) { if( readerdata->linkingvarsblocks[varidx][k] == blocknr ) break; } /* we did not break, so the variable is not assigned to the block */ if( k == readerdata->nlinkingvarsblocks[varidx] ) { blocknr = -1; break; } } } } if( blocknr == -1 ) { SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (nblocks+1)) ); SCIPdebugMessage("constraint <%s> is a linking constraint\n", SCIPconsGetName(cons)); } else { SCIP_CALL( SCIPhashmapInsert(constoblock, cons, (void*) (size_t) (blocknr+1)) ); SCIPdebugMessage("constraint <%s> is assigned to block %d\n", SCIPconsGetName(cons), blocknr); } } } SCIP_CALL( DECfilloutDecdecompFromConstoblock(scip, decomp, constoblock, nblocks, SCIPgetVars(scip), SCIPgetNVars(scip), SCIPgetConss(scip), SCIPgetNConss(scip), FALSE) ); SCIPfreeMemoryArray(scip, &consvars); return SCIP_OKAY; }
/** 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; }
/** add branching decisions constraints to the sub SCIP */ static SCIP_RETCODE addBranchingDecisionConss( SCIP* scip, /**< SCIP data structure */ SCIP* subscip, /**< pricing SCIP data structure */ SCIP_VAR** vars, /**< variable array of the subscuip oder variables */ SCIP_CONSHDLR* conshdlr /**< constraint handler for branching data */ ) { SCIP_CONS** conss; SCIP_CONS* cons; int nconss; int id1; int id2; CONSTYPE type; SCIP_Real vbdcoef; SCIP_Real lhs; SCIP_Real rhs; int c; assert( scip != NULL ); assert( subscip != NULL ); assert( conshdlr != NULL ); /* collect all branching decision constraints */ conss = SCIPconshdlrGetConss(conshdlr); nconss = SCIPconshdlrGetNConss(conshdlr); /* loop over all branching decision constraints and apply the branching decision if the corresponding constraint is * active */ for( c = 0; c < nconss; ++c ) { cons = conss[c]; /* ignore constraints which are not active since these are not laying on the current active path of the search * tree */ if( !SCIPconsIsActive(cons) ) continue; /* collect the two item ids and the branching type (SAME or DIFFER) on which the constraint branched */ id1 = SCIPgetItemid1Samediff(scip, cons); id2 = SCIPgetItemid2Samediff(scip, cons); type = SCIPgetTypeSamediff(scip, cons); SCIPdebugMessage("create varbound for %s(%d,%d)\n", type == SAME ? "same" : "diff", SCIPprobdataGetIds(SCIPgetProbData(scip))[id1], SCIPprobdataGetIds(SCIPgetProbData(scip))[id2]); /* depending on the branching type select the correct left and right hand side for the linear constraint which * enforces this branching decision in the pricing problem MIP */ if( type == SAME ) { lhs = 0.0; rhs = 0.0; vbdcoef = -1.0; } else if( type == DIFFER ) { lhs = -SCIPinfinity(scip); rhs = 1.0; vbdcoef = 1.0; } else { SCIPerrorMessage("unknow constraint type <%d>\n, type"); return SCIP_INVALIDDATA; } /* add linear (in that case a variable bound) constraint to pricing MIP depending on the branching type: * * - branching type SAME: x1 = x2 <=> x1 - x2 = 0 <=> 0 <= x1 - x2 <= 0 * * - branching type DIFFER: x1 - x2 <= 1 <=> -inf <= x1 - x2 <= 1 * */ SCIP_CALL( SCIPcreateConsBasicVarbound(subscip, &cons, SCIPconsGetName(conss[c]), vars[id1], vars[id2], vbdcoef, lhs, rhs) ); SCIPdebug( SCIPprintCons(subscip, cons, NULL) ); SCIP_CALL( SCIPaddCons(subscip, cons) ); SCIP_CALL( SCIPreleaseCons(subscip, &cons) ); } return SCIP_OKAY; }
/** reads the blocks section */ static SCIP_RETCODE readBlock( SCIP* scip, /**< SCIP data structure */ DECINPUT* decinput, /**< DEC reading data */ SCIP_READERDATA* readerdata /**< reader data */ ) { int oldblock; int varidx; int consindex; int i; int blockid; int nvars; SCIP_CONS* cons; SCIP_VAR** vars; SCIP_Bool conshasvar; assert(decinput != NULL); assert(readerdata != NULL); while( getNextToken(decinput) ) { /* check if we reached a new section */ if( isNewSection(scip, decinput) ) break; /* the token must be the name of an existing cons */ cons = SCIPfindCons(scip, decinput->token); if( cons == NULL ) { syntaxError(scip, decinput, "unknown constraint in block section"); break; } conshasvar = FALSE; /* get all vars for the specific constraint */ nvars = SCIPgetNVarsXXX(scip, cons); vars = NULL; if( nvars > 0 ) { SCIP_CALL( SCIPallocMemoryArray(scip, &vars, nvars) ); SCIP_CALL( SCIPgetVarsXXX(scip, cons, vars, nvars) ); } blockid = decinput->blocknr; for( i = 0; i < nvars; i ++ ) { SCIP_VAR* var; assert(vars != NULL); /* for flexelint */ if( decinput->presolved ) { var = SCIPvarGetProbvar(vars[i]); if( !SCIPisVarRelevant(var) ) continue; } else var = vars[i]; conshasvar = TRUE; /* store for each var whether it is in none, one or more blocks */ varidx = SCIPvarGetProbindex(var); assert(varidx >= 0 && varidx < SCIPgetNVars(scip)); oldblock = readerdata->varstoblock[varidx]; assert(oldblock == NOVALUE || oldblock == LINKINGVALUE || (oldblock >= 0 && oldblock < decinput->nblocks)); /* variable was assigned to no block before, just assign it to the new block */ if( oldblock == NOVALUE ) { SCIPdebugMessage("\tVar %s temporary in block %d.\n", SCIPvarGetName(vars[i]), blockid); readerdata->varstoblock[varidx] = blockid; ++(readerdata->nblockvars[blockid]); } /* variable was assigned to another (non-linking) block before, so it becomes a linking variable, now */ else if( (oldblock != LINKINGVALUE) && oldblock != blockid ) { SCIPdebugMessage("\tVar %s is linking (old %d != %d new).\n", SCIPvarGetName(vars[i]), oldblock, blockid); assert(oldblock != blockid); readerdata->varstoblock[varidx] = LINKINGVALUE; /* decrease the value again if it is a linking var */ --(readerdata->nblockvars[oldblock]); ++(readerdata->nlinkingvars); } } SCIPfreeMemoryArrayNull(scip, &vars); if( !conshasvar ) { assert(!SCIPhashmapExists(readerdata->constoblock, cons)); SCIPwarningMessage(scip, "Cons <%s> has been deleted by presolving, skipping.\n", SCIPconsGetName(cons)); continue; } /* * saving block <-> constraint */ /** @todo check if linking constraints are not in the subscipcons */ consindex = readerdata->nblockconss[blockid]; readerdata->blockconss[blockid][consindex] = cons; ++(readerdata->nblockconss[blockid]); assert(SCIPhashmapGetImage(readerdata->constoblock, cons) == (void*)(size_t) LINKINGVALUE); SCIPdebugMessage("cons %s is in block %d\n", SCIPconsGetName(cons), blockid); SCIP_CALL( SCIPhashmapSetImage(readerdata->constoblock, cons, (void*) ((size_t) blockid)) ); --(readerdata->nlinkingconss); } return SCIP_OKAY; }
/** frees specific constraint data */ static SCIP_DECL_CONSDELETE(consDeleteOrigbranch) { /*lint --e{715}*/ SCIP_CONSDATA* parentdata; assert(scip != NULL); assert(conshdlr != NULL); assert(cons != NULL); assert(consdata != NULL); assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0); assert(*consdata != NULL); SCIPdebugMessage("Deleting branch orig constraint: <%s>.\n", SCIPconsGetName(cons)); /* set the origcons pointer of the corresponding mastercons to NULL */ if( (*consdata)->mastercons != NULL ) GCGconsMasterbranchSetOrigcons((*consdata)->mastercons, NULL); /* set the pointer in the parent constraint to NULL */ if( (*consdata)->parentcons != NULL ) { parentdata = SCIPconsGetData((*consdata)->parentcons); if( parentdata->child1cons == cons ) parentdata->child1cons = NULL; else if( parentdata->probingtmpcons == cons ) { assert(SCIPinProbing(scip)); parentdata->probingtmpcons = NULL; } else { assert(parentdata->child2cons == cons); parentdata->child2cons = NULL; if( SCIPinProbing(scip) ) { parentdata->child2cons = parentdata->probingtmpcons; parentdata->probingtmpcons = NULL; } } } /* no child nodes may exist */ assert((*consdata)->child1cons == NULL); assert((*consdata)->child2cons == NULL); /* delete branchdata, if no mastercons is linked, which would still need the branchdata * otherwise, the mastercons deletes the branchdata when it is deleted itself */ if( (*consdata)->mastercons == NULL && (*consdata)->branchdata != NULL ) { SCIP_CALL( GCGrelaxBranchDataDelete(scip, (*consdata)->branchrule, &(*consdata)->branchdata) ); } /* free propagation domain changes arrays */ if( (*consdata)->maxpropbounds > 0 ) { SCIPfreeMemoryArray(scip, &((*consdata)->propvars)); SCIPfreeMemoryArray(scip, &((*consdata)->propboundtypes)); SCIPfreeMemoryArray(scip, &((*consdata)->propbounds)); } /* free constraint data */ SCIPfreeBlockMemory(scip, consdata); return SCIP_OKAY; }