All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cons_and.c
Go to the documentation of this file.
17 * @brief Constraint handler for "and" constraints, \f$r = x_1 \wedge x_2 \wedge \dots \wedge x_n\f$
28 * where \f$x_i\f$ is a binary variable for all \f$i\f$. Hence, \f$r\f$ is also of binary type. The variable \f$r\f$ is
32 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
52 #define CONSHDLR_ENFOPRIORITY -850100 /**< priority of the constraint handler for constraint enforcing */
53 #define CONSHDLR_CHECKPRIORITY -850100 /**< priority of the constraint handler for checking feasibility */
54 #define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
55 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
56 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
58 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
59 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
60 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
61 #define CONSHDLR_DELAYPRESOL FALSE /**< should presolving method be delayed, if other presolvers found reductions? */
62 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
69 #define DEFAULT_PRESOLPAIRWISE TRUE /**< should pairwise constraint comparison be performed in presolving? */
73 #define DEFAULT_UPGRRESULTANT TRUE /**< should all binary resultant variables be upgraded to implicit binary variables */
77 #define DEFAULT_PRESOLUSEHASHING TRUE /**< should hash table be used for detecting redundant constraints in advance */
79 #define MINGAINPERNMINCOMPARISONS 1e-06 /**< minimal gain per minimal pairwise presolving comparisons to repeat pairwise comparison round */
80 #define EXPRGRAPHREFORM_PRIORITY 100000 /**< priority of expression graph node reformulation method */
82 /* @todo maybe use event SCIP_EVENTTYPE_VARUNLOCKED to decide for another dual-presolving run on a constraint */
105 unsigned int opimpladded:1; /**< was the implication for 2 operands with fixed resultant added? */
109 unsigned int checkwhenupgr:1; /**< if and constraint is upgraded to an logicor constraint or the and-
112 unsigned int notremovablewhenupgr:1;/**< if and constraint is upgraded to an logicor constraint or the and-
121 SCIP_Bool presolpairwise; /**< should pairwise constraint comparison be performed in presolving? */
122 SCIP_Bool presolusehashing; /**< should hash table be used for detecting redundant constraints in advance */
126 SCIP_Bool upgrresultant; /**< upgrade binary resultant variable to an implicit binary variable */
240 /* catch tightening events for lower bound and relaxed events for upper bounds on watched variable */
241 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[pos], SCIP_EVENTTYPE_LBTIGHTENED | SCIP_EVENTTYPE_UBRELAXED,
264 /* drop tightening events for lower bound and relaxed events for upper bounds on watched variable */
265 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], SCIP_EVENTTYPE_LBTIGHTENED | SCIP_EVENTTYPE_UBRELAXED,
271 /** catches needed events on all variables of constraint, except the special ones for watched variables */
287 /* catch tightening events for upper bound and relaxed events for lower bounds on operator variables */
290 SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[i], SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED,
297 /** drops events on all variables of constraint, except the special ones for watched variables */
313 /* drop tightening events for upper bound and relaxed events for lower bounds on operator variables */
316 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[i], SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED,
358 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar1, consdata->filterpos1) );
363 SCIP_CALL( consdataDropWatchedEvents(scip, consdata, eventhdlr, consdata->watchedvar2, consdata->filterpos2) );
369 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar1, &consdata->filterpos1) );
373 SCIP_CALL( consdataCatchWatchedEvents(scip, consdata, eventhdlr, watchedvar2, &consdata->filterpos2) );
416 SCIP_Bool checkwhenupgr, /**< should an upgraded constraint be checked despite the fact that this
455 SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nvars, (*consdata)->vars, (*consdata)->vars) );
631 SCIPerrorMessage("cannot add coefficients to and constraint after LP relaxation was created\n");
662 SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], SCIP_EVENTTYPE_UBTIGHTENED | SCIP_EVENTTYPE_LBRELAXED,
746 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var1, consdata->nvars, &pos);
757 found = SCIPsortedvecFindPtr((void**)consdata->vars, SCIPvarComp, (void*)var2, consdata->nvars, &pos);
911 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[0], SCIPconsGetHdlr(cons), rowname, -consdata->nvars + 1.0, SCIPinfinity(scip),
920 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->rows[i+1], SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 0.0,
964 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &consdata->aggrrow, SCIPconsGetHdlr(cons), rowname, -SCIPinfinity(scip), 0.0,
966 SCIP_CALL( SCIPaddVarToRow(scip, consdata->aggrrow, consdata->resvar, (SCIP_Real) consdata->nvars) );
967 SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, consdata->aggrrow, consdata->nvars, consdata->vars, -1.0) );
974 assert(!infeasible); /* this function is only called by initlp() -> the cuts should be feasible */
981 assert( ! infeasible ); /* this function is only called by initlp() -> the cuts should be feasible */
987 /** checks and constraint for feasibility of given solution: returns TRUE iff constraint is feasible */
1009 /* check, if we can skip this feasibility check, because all rows are in the LP and doesn't have to be checked */
1030 /* increase age of constraint; age is reset to zero, if a violation was found only in case we are in
1043 /* @todo if upgraded resultants to varstatus implicit is fully allowed, than the following assert does not hold
1044 * anymore, therefor we need to stop the check and return with the status not violated, because the
1048 * SCIP_SEPARATED if the origin was the CONSENFOPS or the CONSENFOLP callback or SCIP_INFEASIBLE if the
1057 /* if all operator variables are TRUE, the resultant has to be TRUE, otherwise, the resultant has to be FALSE;
1058 * in case of an implicit integer resultant variable, we need to ensure the integrality of the solution value
1061 assert(SCIPvarGetType(consdata->resvar) == SCIP_VARTYPE_IMPLINT || SCIPisFeasIntegral(scip, solval));
1080 SCIPinfoMessage(scip, NULL, " resultant variable <%s> has fractional solution value %"SCIP_REAL_FORMAT"\n",
1149 /** analyzes conflicting TRUE assignment to resultant of given constraint, and adds conflict constraint to problem */
1160 if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) )
1169 /* initialize conflict analysis, and add resultant and single operand variable to conflict candidate queue */
1180 /** analyzes conflicting FALSE assignment to resultant of given constraint, and adds conflict constraint to problem */
1193 if( (SCIPgetStage(scip) != SCIP_STAGE_SOLVING && !SCIPinProbing(scip)) || !SCIPisConflictAnalysisApplicable(scip) )
1200 /* initialize conflict analysis, and add all variables of infeasible constraint to conflict candidate queue */
1232 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, FALSE, cons, (int)PROPRULE_1, &infeasible, &tightened) );
1274 SCIP_CALL( SCIPinferBinvarCons(scip, vars[v], TRUE, cons, (int)PROPRULE_2, &infeasible, &tightened) );
1298 /** linearize AND constraint due to a globally to zero fixed resultant; that is, creates, adds, and releases a logicor
1301 * Since the resultant is fixed to zero the AND constraint collapses to linear constraint of the form:
1336 /* if we only have two variables, we prefer a set packing constraint instead of a logicor constraint */
1348 /* if one of the two operators is globally fixed to one it follows that the other has to be zero */
1373 SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons),
1374 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
1393 SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons), SCIPconsIsModifiable(cons), SCIPconsIsDynamic(cons),
1394 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
1418 /** the resultant is fixed to zero; in case all except one operator are fixed to TRUE the last operator has to fixed to FALSE */
1419 /** @note consdata->watchedvars might not be the same to the watchedvar parameters, because the update was not yet done */
1454 SCIPdebugMessage("constraint <%s>: resultant <%s> fixed to 0.0, only one unfixed operand -> fix operand <%s> to 0.0\n",
1455 SCIPconsGetName(cons), SCIPvarGetName(consdata->resvar), SCIPvarGetName(consdata->vars[watchedvar1]));
1457 SCIP_CALL( SCIPinferBinvarCons(scip, consdata->vars[watchedvar1], FALSE, cons, (int)PROPRULE_4, &infeasible, &tightened) );
1486 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
1546 assert(SCIPvarIsActive(var) || (SCIPvarIsNegated(var) && SCIPvarIsActive(SCIPvarGetNegatedVar(var))));
1554 /* check variable type, either pure binary or an integer/implicit integer variable with 0/1 bounds */
1557 ((probidx >= nbinvars && probidx < nbinvars + nintvars && SCIPvarGetType(probvar) == SCIP_VARTYPE_INTEGER) ||
1565 /* search for multiple variables; scan from back to front because deletion doesn't affect the order of the front
1567 * @note don't reorder variables because we would loose the watched variables and filter position inforamtion
1573 assert(SCIPvarIsActive(var) || (SCIPvarIsNegated(var) && SCIPvarIsActive(SCIPvarGetNegatedVar(var))));
1587 else if( ((*entries)[probidx] == 1 && SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && !SCIPvarIsActive(var)) )
1598 assert(((*entries)[probidx] == 1 && !SCIPvarIsActive(var)) || ((*entries)[probidx] == 2 && SCIPvarIsActive(var)));
1600 SCIPdebugMessage("and constraint <%s> is redundant: variable <%s> and its negation are present -> fix resultant <%s> = 0\n",
1634 * additional if the resultant is fixed to zero during presolving or in the root node (globally), then the "and"
1668 /* don't process the constraint, if none of the operator variables was fixed to FALSE, and if the watched variables
1678 /* increase age of constraint; age is reset to zero, if a conflict or a propagation was found */
1698 /* if one of the operator variables was fixed to FALSE, the resultant can be fixed to FALSE (rule (1)) */
1701 for( i = 0; i < nvars && SCIPvarGetUbLocal(vars[i]) > 0.5; ++i ) /* search for operator fixed to zero */
1729 * that means, we only have to watch (i.e. capture events) of two variables, and switch to other variables
1785 SCIPdebugMessage("constraint <%s>: all operator vars fixed to 1.0 -> fix resultant <%s> to 1.0\n",
1787 SCIP_CALL( SCIPinferBinvarCons(scip, resvar, TRUE, cons, (int)PROPRULE_3, &infeasible, &tightened) );
1809 /* if resultant is fixed to FALSE, and only one operator variable is not fixed to TRUE, this operator variable
1824 /* mark the constraint propagated if we have an unfixed resultant or are not in probing, it is necessary that a fixed
1825 * resulting in probing mode does not lead to a propagated constraint, because the constraint upgrade needs to be performed
1827 consdata->propagated = (!SCIPinProbing(scip) || (SCIPvarGetLbLocal(consdata->resvar) < 0.5 && SCIPvarGetUbLocal(consdata->resvar) > 0.5));
1832 /** resolves a conflict on the given variable by supplying the variables needed for applying the corresponding
1845 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1846 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1900 /* the operand variable was infered to FALSE, because the resultant was FALSE and all other operands were TRUE */
1917 SCIPerrorMessage("invalid inference information %d in and constraint <%s>\n", proprule, SCIPconsGetName(cons));
1931 unsigned char** entries, /**< array to store whether two positions in constraints represent the same variable */
1998 SCIP_CALL( mergeMultiples(scip, cons, eventhdlr, entries, nentries, nfixedvars, nchgcoefs, ndelconss) );
2017 /* a fixed resultant needs to be removed, otherwise we might fix operands to a wrong value later on */
2048 /* add up all positive objective values of operands which have exactly one lock in both directions */
2074 /* if all variables are only locked by this constraint and the resultants contribution more then compensates
2079 SCIPdebugMessage("dual-fixing all variables in constraint <%s> to 1\n", SCIPconsGetName(cons));
2097 SCIPdebugMessage("deleting constraint <%s> because all variables are fixed to one\n", SCIPconsGetName(cons));
2109 SCIPdebugMessage("dual-fixing all variables in constraint <%s> with positive contribution (when together exceeding the negative contribution of the resultant) to 0 and with negative contribution to 1\n", SCIPconsGetName(cons));
2150 SCIPdebugMessage("dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(impoperands[v]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2156 /* did we aggregate the resultant, then we can decide the value to fix it on the (aggregated) objective
2176 SCIPdebugMessage("constraint <%s> we can fix the resultant <%s> to %g, because the and constraint will alwys be fulfilled\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), fixval);
2206 /* if the smallest possible contribution is negative, but does not compensate the positive contribution of
2213 SCIPdebugMessage("dual-fixing variable <%s> in constraint <%s> to %g, because the contribution is%s enough to nullify/exceed the contribution of the resultant \n", SCIPvarGetName(impoperands[maxpos]), SCIPconsGetName(cons), fixval, (fixval < 0.5) ? " not" : "");
2223 SCIPdebugMessage("dual-fixing all variables, except the variable with the highest contribution to the objective, in constraint <%s> with positive contribution to 0 and with negative contribution to 1\n", SCIPconsGetName(cons));
2248 /* iff we have fixed all variables, all variables needed to be stored in the impoperands array */
2253 SCIPdebugMessage("all operands are fixed in constraint <%s> => fix resultant <%s> to %g\n", SCIPconsGetName(cons), SCIPvarGetName(resvar), (zerofix ? 0.0 : 1.0));
2261 SCIPdebugMessage("deleting constraint <%s> because all variables are fixed\n", SCIPconsGetName(cons));
2268 /* resultant is lock by another constraint (handler), check for operands with only one down- and uplock */
2289 /* we can only aggregate when the objective contribution of the resultant is less or equal to 0 */
2303 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
2324 SCIPdebugMessage("dual aggregating operand <%s> with 1 up- and downlock to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(var), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2335 /* if we aggregated an operands with the resultant we can also fix "good" independant operands to 1, since
2336 * the correctness of "resultant = 0 => at least one operand = 0" in enforced by that aggregation
2337 * without an aggregation we cannot fix these variables since it might lead to infeasibility, e.g.
2360 SCIPdebugMessage("dual-fixing variable <%s> in constraint <%s> to 1, because the contribution is negative\n", SCIPvarGetName(var), SCIPconsGetName(cons));
2373 /* if the downlocks of the resultant are only from this constraint and the objective contribution is positive,
2400 /* all operands which are only locked by this constraint, the objective contribution is greater or equal
2401 * to 0, and the absolute value of the contribution of the resultant exceeds can be eliminated and
2404 if( SCIPvarGetNLocksUp(var) == 1 && SCIPvarGetNLocksDown(var) == 1 && SCIPisGE(scip, obj, 0.0) )
2406 SCIPdebugMessage("dualfix operand <%s> in constraint <%s> to 0\n", SCIPvarGetName(var), SCIPconsGetName(cons));
2419 /* if constraint is still active and all operands are only lock by this constraint, we check if we can fix
2425 /* objective contribution needs to be negative, otherwise, the variable should already be fixed to 0 */
2428 SCIPdebugMessage("dualfix operand <%s> with worst contribution in constraint <%s> to 0\n", SCIPvarGetName(vars[maxpos]), SCIPconsGetName(cons));
2442 SCIPdebugMessage("fix resultant <%s> in constraint <%s> to 0\n", SCIPvarGetName(resvar), SCIPconsGetName(cons));
2450 SCIPdebugMessage("deleting constraint <%s> because at least one operand and the resultant is fixed to zero\n", SCIPconsGetName(cons));
2457 /* we have to linearize the constraint, otherwise we might get wrong propagations, since due to aggregations a
2458 * resultant fixed to zero is already fulfilling the constraint, and we must not ensure that some remaining
2480 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, consvars, vals, -SCIPinfinity(scip), 0.0,
2492 SCIPdebugMessage("deleting constraint <%s> because it was linearized\n", SCIPconsGetName(cons));
2500 SCIPdebugMessage("aggregating last operand <%s> to the resultant <%s> in constraint <%s>\n", SCIPvarGetName(consdata->vars[0]), SCIPvarGetName(resvar), SCIPconsGetName(cons));
2511 SCIPdebugMessage("deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
2520 SCIPdebugMessage("deleting constraint <%s> because all variables are removed\n", SCIPconsGetName(cons));
2533 /** 1. check if at least two operands or one operand and the resultant are in one clique, if so, we can fix the
2534 * resultant to zero and in the former case we can also delete this constraint but we need to extract the clique
2542 * - if the resultant is equal to an operand, we will linearize this constraint by adding all necessary
2548 * 2. check if one operand is in a clique with the negation of all other operands, this means we can aggregate this
2555 * r == AND(x,y) and clique(r, ~x,~y) => upgrade the constraint to a set-partitioning constraint r + ~x + ~y = 1
2557 * @note We removed also fixed variables and propagate them, and if only one operand is remaining due to removal, we
2620 SCIPdebugMessage("In constraint <%s> the operand <%s> is fixed to 1 so remove it from the constraint\n",
2633 SCIPdebugMessage("constraint <%s> redundant: because operand <%s> is fixed to zero so we can fix the resultant <%s> to 0\n",
2653 /* all operands fixed to one were removed, so if no operand is left this means we can fix the resultant to 1
2658 SCIPdebugMessage("All operand in constraint <%s> were deleted, so the resultant needs to be fixed to 1\n",
2695 /* @todo when cliques are improved, we only need to collect all clique-ids for all variables and check for doubled
2734 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
2735 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better
2747 SCIPdebugMessage("constraint <%s> redundant: because variable <%s> and variable <%s> are in a clique, the resultant <%s> can be fixed to 0\n",
2748 SCIPconsGetName(cons), SCIPvarGetName(var1), SCIPvarGetName(var2), SCIPvarGetName(consdata->resvar));
2775 consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
2777 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
2805 SCIPdebugMessage("In constraint <%s> the resultant <%s> is fixed to 1 so fix all operands to 1\n",
2825 /* the upgrade to a linear constraint because of the to 0 fixed resultant we do in propagateCons() */
2855 /* if both variables are negated of each other or the same, this will be handled in applyFixings();
2856 * @note if both variables are the same, then SCIPvarsHaveCommonClique() will return TRUE, so we better continue
2863 SCIPdebugMessage("In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
2874 /* x1 == AND(x1, x2 ...) => delete constraint and create all set-packing constraints x1 + ~x2 <= 1, x1 + ~... <= 1 */
2891 /* if the active representations of the resultant and an operand are different then we need to extract
2894 * if the active representations of the resultant and an operand are equal then the clique constraint
2897 * if the active representations of the resultant and an operand are negated of each other then the
2898 * clique constraint would look like x1 + x1 <= 1, which will lead to a fixation of the resultant later
2905 SCIPdebugMessage("In constraint <%s> the resultant <%s> can be fixed to 0 because the negation of it is an operand.\n",
2928 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
2945 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to handle
2951 /* due to SCIPvarsHaveCommonClique() returns on two negated variables that they are not in a clique, we need to
2954 if( (var1 == var2 && value1 != value2) || SCIPvarsHaveCommonClique(var1, value1, var2, value2, TRUE) )
2956 SCIPdebugMessage("in constraint <%s> the resultant <%s> can be fixed to 0 because it is in a clique with operand <%s>\n",
3001 /* exactly one operands has no negated variable, so only this variable can be in a clique with all other negations */
3007 /* at least two operands have no negated variable, so there is no possible clique with negated variables */
3054 /* due to SCIPvarsHaveCommonClique() returns on two same variables that they are in a clique, we need to handle
3059 SCIPdebugMessage("in constraint <%s> the resultant <%s> can be fixed to 0 because two operands are negated of each other\n",
3070 /* due to SCIPvarsHaveCommonClique() returns on two negated variables that they are not in a clique, we need to
3085 SCIPdebugMessage("In constraint <%s> the operand <%s> is in a negated clique with all other operands, so we can aggregated this operand to the resultant <%s>.\n",
3100 /* check if the resultant and the negations of the operands are in a clique, then we can upgrade this constraint to a
3138 /* the resultant is in a clique with the negations of all operands, due to this and-constraint */
3187 consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3189 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3190 SCIPdebugMessage(" -> upgrading and-constraint <%s> with use of clique information to a set-partitioning constraint: \n", SCIPconsGetName(cons));
3216 /** returns TRUE iff both keys are equal; two constraints are equal if they have the same variables */
3287 /** compares each constraint with all other constraints for possible redundancy and removes or changes constraint
3354 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3382 consdata1->notremovablewhenupgr = consdata1->notremovablewhenupgr || consdata0->notremovablewhenupgr;
3491 * - if one operand list is a subset of the other, add implication r0 = 1 -> r1 = 1, or r1 = 1 -> r0 = 1
3544 SCIPdebugMessage("equivalent and constraints <%s> and <%s>: aggregate resultants <%s> == <%s>\n",
3561 /* update flags of constraint which caused the redundancy s.t. nonredundant information doesn't get lost */
3566 consdata0->notremovablewhenupgr = consdata1->notremovablewhenupgr || consdata0->notremovablewhenupgr;
3581 SCIPdebugMessage("and constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
3586 SCIP_CALL( SCIPaddVarImplication(scip, consdata0->resvar, TRUE, consdata1->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
3597 SCIPdebugMessage("and constraint <%s> is superset of <%s>: add implication <%s> = 1 -> <%s> = 1\n",
3602 SCIP_CALL( SCIPaddVarImplication(scip, consdata1->resvar, TRUE, consdata0->resvar, SCIP_BOUNDTYPE_LOWER, 1.0,
3614 /** tries to reformulate an expression graph node that is a product of binary variables via introducing an and constraint */
3636 (SCIPexprgraphGetNodeOperator(node) != SCIP_EXPR_POLYNOMIAL || SCIPexprgraphGetNodePolynomialNMonomials(node) > 1)
3642 /* for a polynomial with only one monomial, all children should appear as factors in the monomial
3643 * since we assume that the factors have been merged, this means that the number of factors in the monomial should equal the number of children of the node
3645 assert(SCIPexprgraphGetNodeOperator(node) != SCIP_EXPR_POLYNOMIAL || SCIPexprGetMonomialNFactors(SCIPexprgraphGetNodePolynomialMonomials(node)[0]) == nchildren);
3647 /* check only products with at least 3 variables (2 variables are taken of by cons_quadratic) */
3664 /* node corresponds to product of binary variables (maybe with coefficient and constant, if polynomial) */
3676 * cons_and wants to add implications for resultant, which is only possible for binary variables currently
3714 /* if we have coefficient and constant, then replace reformnode by linear expression in reformnode */
3755 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
3773 /** presolving initialization method of constraint handler (called when presolving is about to begin) */
3831 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, 2, vars, vals, -SCIPinfinity(scip), 0.0,
3833 consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3835 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3863 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -SCIPinfinity(scip), 0.0,
3865 consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3867 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3879 SCIP_CALL( SCIPcreateConsLinear(scip, &newcons, consname, nvars + 1, vars, vals, -nvars + 1.0, SCIPinfinity(scip),
3881 consdata->checkwhenupgr || SCIPconsIsChecked(cons), SCIPconsIsPropagated(cons), SCIPconsIsLocal(cons),
3883 !(consdata->notremovablewhenupgr) && SCIPconsIsRemovable(cons), SCIPconsIsStickingAtNode(cons)) );
3906 /** presolving deinitialization method of constraint handler (called after presolving has been finished) */
3942 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, &nimplvars, &ncontvars) );
3956 SCIP_CALL( SCIPhashmapCreate(&hashmap, SCIPblkmem(scip), SCIPcalcHashtableSize(HASHTABLESIZE_FACTOR * nvars)) );
4055 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
4111 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
4114 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
4120 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
4225 * e.g. the resultant, which has a negative objective value, is in the lp solution on its upper bound
4226 * (variables with status loose are in an lp solution on it's best bound), but already creating a row, and
4227 * thereby creating the column, changes the solution value (variable than has status column, and the
4228 * initialization sets the lp solution value) to 0.0, and this already could lead to no violation of the
4232 assert(consseparated); /* because the solution is integral, the separation always finds a cut */
4318 SCIP_CALL( propagateCons(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, &nfixedvars, &nupgdconss) );
4386 SCIP_CALL( propagateCons(scip, cons, conshdlrdata->eventhdlr, &cutoff, nfixedvars, nupgdconss) );
4396 SCIP_CALL( mergeMultiples(scip, cons, conshdlrdata->eventhdlr, &entries, &nentries, nfixedvars, nchgcoefs, ndelconss) );
4409 SCIPdebugMessage("and constraint <%s> has only one variable not fixed to 1.0\n", SCIPconsGetName(cons));
4466 SCIP_CALL( dualPresolve(scip, conss, nconss, conshdlrdata->eventhdlr, &entries, &nentries, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, nupgdconss, naddconss) );
4477 SCIP_CALL( cliquePresolve(scip, conss[c], conshdlrdata->eventhdlr, &cutoff, nfixedvars, naggrvars, nchgcoefs, ndelconss, naddconss) );
4484 /* process pairs of constraints: check them for equal operands in order to aggregate resultants;
4485 * only apply this expensive procedure, if the single constraint preprocessing did not find any reductions
4494 /* detect redundant constraints; fast version with hash table instead of pairwise comparison */
4495 SCIP_CALL( detectRedundantConstraints(scip, SCIPblkmem(scip), conss, nconss, &firstchange, &cutoff, naggrvars, ndelconss) );
4515 npaircomparisons += ((SCIPconsGetData(conss[c])->changed) ? (SCIP_Longint) c : ((SCIP_Longint) c - (SCIP_Longint) firstchange));
4522 if( ((*ndelconss - oldndelconss) + (*naggrvars - oldnaggrvars) + (*nchgbds - oldnchgbds)/2.0) / ((SCIP_Real) npaircomparisons) < MINGAINPERNMINCOMPARISONS )
4575 SCIP_CALL( SCIPaddVarLocks(scip, consdata->resvar, nlockspos + nlocksneg, nlockspos + nlocksneg) );
4580 SCIP_CALL( SCIPaddVarLocks(scip, consdata->vars[i], nlockspos + nlocksneg, nlockspos + nlocksneg) );
4619 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourceresvar, &resvar, varmap, consmap, global, valid) );
4635 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &vars[v], varmap, consmap, global, valid) );
4650 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4721 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4733 SCIP_CALL( SCIPparseVarsList(scip, strcopy, vars, &nvars, varssize, &requiredsize, &endptr, ',', success) );
4741 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4758 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
4788 /** constraint method of constraint handler which returns the number of variable (if possible) */
4873 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolAnd, CONSHDLR_MAXPREROUNDS, CONSHDLR_DELAYPRESOL) );
4875 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropAnd, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
4878 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpAnd, consSepasolAnd, CONSHDLR_SEPAFREQ,
4915 SCIP_CALL( SCIPincludeNonlinconsUpgrade(scip, NULL, exprgraphnodeReformAnd, EXPRGRAPHREFORM_PRIORITY, TRUE, CONSHDLR_NAME) );
4923 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
4950 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
4952 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
4975 #if 1 /* todo delete following hack, because upgraded variables might have implications, which still only work with
4976 * SCIP_VARTYPE_BINARY variables and removing branching candidates also asserts to have only such variables
4977 * the following avoids upgrading not artificial variables, for example and-resultants which are genarated
4980 && strlen(SCIPvarGetName(resvar)) > strlen(ARTIFICIALVARNAMEPREFIX) && strncmp(SCIPvarGetName(resvar), ARTIFICIALVARNAMEPREFIX, strlen(ARTIFICIALVARNAMEPREFIX)) == 0 )
4990 SCIP_CALL( consdataCreate(scip, &consdata, conshdlrdata->eventhdlr, nvars, vars, resvar, FALSE, FALSE) );
4993 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
5000 * in its most basic version, i. e., all constraint flags are set to their basic value as explained for the
5005 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
5148 /** when 'upgrading' the given and-constraint, should the check flag for the upgraded constraint be set to TRUE, even if
|