All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cons_linking.c
Go to the documentation of this file.
21 * The constraints handler stores linking constraints between an integer variable and an array of binary variables. Such
26 * with the additional side condition that exactly one binary variable has to be one (set partitioning condition).
28 * This constraint can be created only with the integer variable. In this case the binary variables are only created on
29 * demand. That is, whenever someone asks for the binary variables. Therefore, such constraints can be used to get a
30 * "binary representation" of the domain of the integer variable which will be dynamically created.
33 * @todo add pairwise comparison of constraints in presolving (fast hash table version and complete pairwise comparison)
34 * @todo in case the integer variable is set to lower or upper bound it follows that only the corresponding binary
38 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
50 #define CONSHDLR_DESC "linking constraint x = sum_{i=1}^{n} c_i*y_i, y1+...+yn = 1, x integer, y's binary"
56 #define CONSHDLR_ENFOPRIORITY -2050000 /**< priority of the constraint handler for constraint enforcing */
57 #define CONSHDLR_CHECKPRIORITY -750000 /**< priority of the constraint handler for checking feasibility */
58 #define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
59 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
60 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation, propagation and enforcement, -1 for no eager evaluations, 0 for first only */
61 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
62 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
63 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
64 #define CONSHDLR_DELAYPRESOL FALSE /**< should presolving method be delayed, if other presolvers found reductions? */
65 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
70 #define HASHSIZE_BINVARSCONS 131101 /**< minimal size of hash table in linking constraint handler */
71 #define DEFAULT_LINEARIZE FALSE /**< should the linking constraint be linearize after the binary variable are created */
92 unsigned int sorted:1; /**< are the coefficients of the binary variables are sorted in non-decreasing order */
100 SCIP_Bool linearize; /**< should the linking constraint be linearize after the binary variable are created */
270 SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
301 SCIP_CALL( SCIPdropVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
360 /** linearize the given linking constraint into a set partitioning constraint for the binary variables and a linear
375 SCIP_CALL( SCIPcreateConsSetpart(scip, &lincons, SCIPconsGetName(cons), consdata->nbinvars, consdata->binvars,
376 SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
377 SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons),
382 /* create linear constraint for the linking between the binary variables and the integer variable */
384 SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
385 SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons),
390 SCIP_CALL( SCIPaddCoefLinear(scip, lincons, consdata->binvars[b], (SCIP_Real)consdata->vals[b]) );
423 SCIPdebugMessage("create binary variables for integer variable <%s>\n", SCIPvarGetName(consdata->intvar));
551 SCIP_CALL( SCIPgetTransformedVars(scip, nbinvars, (*consdata)->binvars, (*consdata)->binvars) );
624 /** analyzes conflicting assignment on given constraint where reason comes from the integer variable lower or upper
640 if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) )
643 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
724 /** checks constraint for violation from the local bound of the integer variable, applies fixings to the binary
733 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
757 /* ensure that the binary variables are sorted in non-decreasing order w.r.t. their coefficients */
762 /* in case there is only at most one binary variables, the constraints should already be disabled */
765 /* if more than one binary variable is fixed to one or at least nbinvars minus one variable are fixed to zero */
798 SCIPdebugMessage("fix variable <%s> to zero due to the lower bound of the integer variable <%s> [%g,%g]\n",
799 SCIPvarGetName(var), SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar));
831 SCIPdebugMessage("fix variable <%s> to zero due to the upper bound of the integer variable <%s> [%g,%g]\n",
832 SCIPvarGetName(var), SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar));
861 /* if integer variables is fixed, create for the binary variables which have a coefficient equal to the fixed vale a
873 SCIPvarGetName(var), SCIPvarGetName(intvar), SCIPvarGetLbLocal(intvar), SCIPvarGetUbLocal(intvar));
903 SCIPconsIsInitial(cons), SCIPconsIsSeparated(cons), SCIPconsIsEnforced(cons), SCIPconsIsChecked(cons),
904 SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons),
1041 /* if more than one binary variable is fixed to one or at least nbinvars minus one variable are fixed to zero return */
1073 SCIP_CALL( SCIPinferVarLbCons(scip, intvar, (SCIP_Real)vals[b], cons, -4, TRUE, &infeasible, &tightened) );
1079 if( (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) && SCIPisConflictAnalysisApplicable(scip) )
1081 SCIPdebugMessage("conflict at <%s> due to bounds and fixed binvars: [lb,ub] = [%g,%g]; b= %d; coef = %d \n",
1086 /* ??????????? use resolve method and only add binvars which are needed to exceed the upper bound */
1122 SCIP_CALL( SCIPinferVarUbCons(scip, intvar, (SCIP_Real)vals[b], cons, -5, TRUE, &infeasible, &tightened) );
1126 /* conflict analysis can only be applied in solving stage and if conflict analysis is turned on */
1127 if( (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) && SCIPisConflictAnalysisApplicable(scip) )
1129 SCIPdebugMessage("conflict at <%s> due to bounds and fixed binvars: [lb,ub] = [%g,%g]; b = %d; coef = %d,\n",
1134 /* ??????????? use resolve method and only add binvars which are needed to fall below the lower bound */
1158 /** checks constraint for violation only looking at the fixed binary variables, applies further fixings if possible */
1166 SCIP_Bool* mustcheck /**< pointer to store whether this constraint must be checked for feasibility */
1187 /* ensure that the binary variables are sorted in non-decreasing order w.r.t. their coefficients */
1190 /* in case there is only at most one binary variables, the constraints should already be disabled */
1213 SCIPdebugMessage(" -> fixing all other variables to zero due to the set partitioning condition <%s>\n",
1217 * this could result in additional variables fixed to one due to aggregations; in this case, the
1247 /* the fixed to one variable must have been found, and at least one variable must have been fixed */
1269 SCIPdebugMessage(" -> conflict on "CONSHDLR_NAME" constraint <%s> due to the set partitioning condition\n", SCIPconsGetName(cons));
1274 if( (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) && SCIPisConflictAnalysisApplicable(scip) )
1284 /* initialize conflict analysis, and add the two variables assigned to one to conflict candidate queue */
1313 SCIPdebugMessage(" -> "CONSHDLR_NAME" constraint <%s> is infeasible due to the set partitioning condition\n",
1322 if( (SCIPgetStage(scip) == SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) && SCIPisConflictAnalysisApplicable(scip) )
1331 /* initialize conflict analysis, add all variables of infeasible constraint to conflict candidate queue */
1368 assert(SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(var), 1.0));
1372 SCIPdebugMessage(" -> fixing remaining binary variable <%s> to one in "CONSHDLR_NAME" constraint <%s>\n",
1425 SCIPdebugMessage("checking linking constraint <%s> for feasibility of solution %p\n", SCIPconsGetName(cons), (void*)sol);
1431 /* in case there is only at most one binary variables, the constraints should already be disabled */
1443 for( b = 0; b < nbinvars && setpartsum < setpartsumbound; ++b ) /* if sum >= sumbound, the feasibility is clearly decided */
1455 return SCIPisFeasEQ(scip, linksum, SCIPgetSolVal(scip, sol, consdata->intvar)) && SCIPisFeasEQ(scip, setpartsum, 1.0);
1537 SCIP_CALL( SCIPaggregateVars(scip, binvars[b-offset], aggrbinvars[b+shift-aggroffset], 1.0, -1.0, 0.0,
1584 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row1, SCIPconsGetHdlr(cons), rowname, 0.0, 0.0,
1595 SCIP_CALL( SCIPaddVarToRow(scip, consdata->row1, consdata->binvars[b], (SCIP_Real)consdata->vals[b]) );
1602 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->row2, SCIPconsGetHdlr(cons), rowname, 1.0, 1.0,
1605 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->row2, consdata->nbinvars, consdata->binvars, 1.0) );
1628 /* in case there is only at most one binary variables, the constraints should already be disabled */
1644 SCIPdebugMessage("adding linking row of constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1651 SCIPdebugMessage("adding set partitioning row of constraint <%s> as cut to the LP\n", SCIPconsGetName(cons));
1684 /* in case there is only at most one binary variables, the constraints should already be disabled */
1693 /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
1779 /* check constraint for violation only looking at the fixed variables, apply further fixings if possible */
1832 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
1852 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
1889 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
1971 SCIPdebugMessage("transform linking constraint for variable <%s>\n", SCIPvarGetName(sourcedata->intvar));
1979 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1982 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1986 SCIP_CALL( SCIPhashmapInsert(conshdlrdata->varmap, getHashmapKey(targetdata->intvar), *targetcons) );
1991 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
2214 if( consdata->nbinvars > 1 && (checklprows || consdata->row1 == NULL || !SCIProwIsInLP(consdata->row1)) )
2261 else if( !SCIPisFeasEQ(scip, (SCIP_Real) (consdata->vals[pos]), SCIPgetSolVal(scip, sol, consdata->intvar)) )
2380 /* in case there is only at most one binary variables, the constraints should already be disabled */
2383 /*SCIPdebugMessage("presolving set partitioning / packing / covering constraint <%s>\n", SCIPconsGetName(cons));*/
2404 SCIPdebugMessage(""CONSHDLR_NAME" constraint <%s> has a binary variable fixed to 1.0\n", SCIPconsGetName(cons));
2429 SCIP_CALL( SCIPfixVar(scip, consdata->intvar, (SCIP_Real)(consdata->vals[v]), &infeasible, &fixed) );
2461 SCIPdebugMessage("linking constraint <%s> is infeasible due to set partitioning condition\n", SCIPconsGetName(cons));
2480 SCIPdebugMessage(""CONSHDLR_NAME" constraint <%s> has only one binary variable not fixed to zero\n",
2506 SCIP_CALL( SCIPfixVar(scip, consdata->intvar, (SCIP_Real)(consdata->vals[v]), &infeasible, &fixed) );
2556 SCIP_CALL( SCIPaggregateVars(scip, var1, var2, 1.0, 1.0, 1.0, &infeasible, &redundant, &aggregated) );
2621 SCIP_CALL( SCIPaddClique(scip, consdata->binvars, NULL, consdata->nbinvars, &infeasible, &ncliquebdchgs) );
2637 SCIP_CALL( aggregateVariables(scip, conshdlrdata->varmap, conss, nconss, naggrvars, &cutoff) );
2642 else if( oldndelconss < *ndelconss || oldnfixedvars < *nfixedvars || oldnchgbds < *nchgbds || oldnaggrvars < *naggrvars)
2670 /* we have to resolve a fixing of a binary variable which was done due to fixed binary variables */
2672 assert(SCIPisFeasEQ(scip, SCIPvarGetUbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetUbAtIndex(intvar, bdchgidx, FALSE)));
2673 assert(SCIPisFeasEQ(scip, SCIPvarGetLbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetLbAtIndex(intvar, bdchgidx, FALSE)));
2677 /* we fixed the binary variable to zero since one of the other binary variable was fixed to one (set
2711 /* we have to resolve a fixing of a binary variable which was done due to the integer variable lower bound */
2716 assert( SCIPisFeasEQ(scip, SCIPvarGetUbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetUbAtIndex(intvar, bdchgidx, FALSE)) );
2717 assert( SCIPisFeasEQ(scip, SCIPvarGetLbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetLbAtIndex(intvar, bdchgidx, FALSE)) );
2724 /* we have to resolve a fixing of a binary variable which was done due to the integer variable upper bound */
2729 assert( SCIPisFeasEQ(scip, SCIPvarGetUbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetUbAtIndex(intvar, bdchgidx, FALSE)) );
2730 assert( SCIPisFeasEQ(scip, SCIPvarGetLbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetLbAtIndex(intvar, bdchgidx, FALSE)) );
2742 /* we tightened the lower bound of the integer variable due the fixing of the corresponding binary variable to zero */
2770 /* we tightened the upper bound of the integer variable due the fixing of the corresponding binary variable two zero */
2797 assert( SCIPisFeasEQ(scip, SCIPvarGetUbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetUbAtIndex(intvar, bdchgidx, FALSE)) );
2798 assert( SCIPisFeasEQ(scip, SCIPvarGetLbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetUbAtIndex(intvar, bdchgidx, FALSE)) );
2799 assert( SCIPisFeasEQ(scip, SCIPvarGetUbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetLbAtIndex(intvar, bdchgidx, FALSE)) );
2800 assert( SCIPisFeasEQ(scip, SCIPvarGetLbAtIndex(intvar, bdchgidx, TRUE), SCIPvarGetLbAtIndex(intvar, bdchgidx, FALSE)) );
2802 assert( !SCIPisFeasEQ(scip, SCIPvarGetLbAtIndex(infervar, bdchgidx, TRUE), SCIPvarGetLbAtIndex(infervar, bdchgidx, FALSE)) );
2809 /* we fixed the integer variable to (vals[inferinfo]) since the corresponding binary variable was fixed to one */
2813 assert(consdata->vals[inferinfo] == (int)(SCIPvarGetUbAtIndex(consdata->intvar, bdchgidx, TRUE) + 0.5)
2814 || consdata->vals[inferinfo] == (int)(SCIPvarGetLbAtIndex(consdata->intvar, bdchgidx, TRUE) + 0.5));
2836 SCIP_CALL( SCIPaddVarLocks(scip, consdata->intvar, nlockspos + nlocksneg, nlockspos + nlocksneg) );
2841 SCIP_CALL( SCIPaddVarLocks(scip, consdata->binvars[b], nlockspos + nlocksneg, nlockspos + nlocksneg) );
2933 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, binvars[v], &binvars[v], varmap, consmap, global, valid) );
2940 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, intvar, &intvar, varmap, consmap, global, valid) );
2953 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3022 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, binvars, vals, &nbinvars, varssize, &requsize, &endptr, success) );
3032 SCIP_CALL( SCIPparseVarsLinearsum(scip, str, binvars, vals, &nbinvars, varssize, &requsize, &endptr, success) );
3033 assert(!*success || requsize <= varssize); /* if successful, then should have had enough space now */
3060 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3092 /** constraint method of constraint handler which returns the number of variables (if possible) */
3197 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolLinking, CONSHDLR_MAXPREROUNDS, CONSHDLR_DELAYPRESOL) );
3199 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLinking, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
3202 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLinking, consSepasolLinking, CONSHDLR_SEPAFREQ,
3207 /* include the linear constraint to linking constraint upgrade in the linear constraint handler */
3208 /* SCIP_CALL( SCIPincludeLinconsUpgrade(scip, linconsUpgdLinking, LINCONSUPGD_PRIORITY, CONSHDLR_NAME) ); */
3212 "constraints/"CONSHDLR_NAME"/linearize", "this constraint will not propagate or separate, linear and setppc are used?",
3220 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3248 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
3250 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
3271 SCIPdebugMessage("create linking constraint for variable <%s> with %d binary variable (SCIP stage %d)\n",
3288 SCIP_CALL( consdataCreate(scip, conshdlrdata->eventhdlr, &consdata, intvar, binvars, vals, nbinvars) );
3291 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
3301 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
3302 * method SCIPcreateConsLinking(); all flags can be set via SCIPsetCons<Flagname>-methods in scip.h
3306 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
3341 return (conshdlrdata->varmap != NULL) && SCIPhashmapExists(conshdlrdata->varmap, getHashmapKey(intvar));
3344 /** returns the linking constraint belonging to the given integer variable or NULL if it does not exist yet */
3418 SCIP_CALL( consdataCreateBinvars(scip, cons, consdata, conshdlrdata->eventhdlr, conshdlrdata->linearize) );
|