Scippy

SCIP

Solving Constraint Integer Programs

cons_sos2.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_sos2.c
17  * @brief constraint handler for SOS type 2 constraints
18  * @author Marc Pfetsch
19  *
20  * A specially ordered set of type 2 (SOS2) is a sequence of variables such that at most two
21  * variables are nonzero and if two variables are nonzero they must be adjacent in the specified
22  * sequence. Note that it is in principle allowed that a variable appears twice, but it then can be
23  * fixed to 0 if it is at least two apart in the sequence.
24  *
25  * This constraint is useful when considering a piecewise affine approximation of a univariate
26  * (nonlinear) function \f$: [a,b] \rightarrow R\f$: Let \f$x_1 < \ldots < x_n\f$ be points in
27  * \f$[a,b]\f$ and introduce variables \f$\lambda_1, \ldots, \lambda_n\f$. To evaluate \f$f(x')\f$
28  * at some point \f$x' \in [a,b]\f$ one can use the following constraints:
29  * \f[
30  * \lambda_1 + \cdots + \lambda_n = 1,\quad x' = x_1 \lambda_1 + \cdots + x_n \lambda_n.
31  * \f]
32  * The value of \f$f(x')\f$ can the be approximated as
33  * \f[
34  * f(x_1) \lambda_1 + \cdots + f(x_n) \lambda_n.
35  * \f]
36  * To get a valid piecewise affine approximation, \f$\lambda_1, \ldots, \lambda_n\f$ have to obey an
37  * SOS constraint of type 2.
38  *
39  * This implementation of this constraint handler is based on classical ideas, see e.g.@n
40  * "Special Facilities in General Mathematical Programming System for
41  * Non-Convex Problems Using Ordered Sets of Variables"@n
42  * E. Beale and J. Tomlin, Proc. 5th IFORS Conference, 447-454 (1970)
43  *
44  * The order of the variables is determined as follows:
45  *
46  * - If the constraint is created with SCIPcreateConsSOS2() and weights are given, the weights
47  * determine the order (decreasing weights). Additional variables can be added with
48  * SCIPaddVarSOS2(), which adds a variable with given weight.
49  *
50  * - If an empty constraint is created and then variables are added with SCIPaddVarSOS2(), weights
51  * are needed and stored.
52  *
53  * - All other calls ignore the weights, i.e., if a nonempty constraint is created or variables are
54  * added with SCIPappendVarSOS2().
55  *
56  * @todo Allow to adapt the order of the constraints, e.g. by priorities. This for instance
57  * determines the branching order.
58  * @todo Separate the following cuts for each pair of variables x, y of at least distance 2 in the
59  * SOS2 constraint: \f$ \min \{l_x, l_y\} \leq x + y \leq \max \{u_x, u_y\}\f$, where \f$l_x, u_x,
60  * l_y, u_y\f$ are the lower and upper bounds of x and y, respectively.
61  * @todo Possibly allow to generate local cuts via strengthened local cuts (would affect lhs/rhs of rows)
62  */
63 
64 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
65 
66 #include <assert.h>
67 
68 #include "scip/cons_sos2.h"
69 #include "scip/cons_linear.h"
70 #include "scip/pub_misc.h"
71 #include <string.h>
72 #include <ctype.h>
73 
74 
75 /* constraint handler properties */
76 #define CONSHDLR_NAME "SOS2"
77 #define CONSHDLR_DESC "SOS2 constraint handler"
78 #define CONSHDLR_SEPAPRIORITY 10 /**< priority of the constraint handler for separation */
79 #define CONSHDLR_ENFOPRIORITY 100 /**< priority of the constraint handler for constraint enforcing */
80 #define CONSHDLR_CHECKPRIORITY -10 /**< priority of the constraint handler for checking feasibility */
81 #define CONSHDLR_SEPAFREQ 0 /**< frequency for separating cuts; zero means to separate only in the root node */
82 #define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
83 #define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
84  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
85 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
86 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
87 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
88 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
89 
90 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
91 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_FAST
92 
93 /* event handler properties */
94 #define EVENTHDLR_NAME "SOS2"
95 #define EVENTHDLR_DESC "bound change event handler for SOS2 constraints"
96 
97 
98 /** constraint data for SOS2 constraints */
99 struct SCIP_ConsData
100 {
101  int nvars; /**< number of variables in the constraint */
102  int maxvars; /**< maximal number of variables (= size of storage) */
103  int nfixednonzeros; /**< number of variables fixed to be nonzero */
104  SCIP_VAR** vars; /**< variables in constraint */
105  SCIP_ROW* row; /**< row corresponding to upper and lower bound inequalities, or NULL if not yet created */
106  SCIP_Real* weights; /**< weights determining the order (ascending), or NULL if not used */
107 };
108 
109 /** SOS2 constraint handler data */
110 struct SCIP_ConshdlrData
111 {
112  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
113 };
114 
115 
116 /** fix variable in given node to 0 or add constraint if variable is multi-aggregated */
117 static
119  SCIP* scip, /**< SCIP pointer */
120  SCIP_VAR* var, /**< variable to be fixed to 0*/
121  SCIP_NODE* node, /**< node */
122  SCIP_Bool* infeasible /**< if fixing is infeasible */
123  )
124 {
125  /* if variable cannot be nonzero */
126  *infeasible = FALSE;
128  {
129  *infeasible = TRUE;
130  return SCIP_OKAY;
131  }
132 
133  /* if variable is multi-aggregated */
135  {
136  SCIP_CONS* cons;
137  SCIP_Real val;
138 
139  val = 1.0;
140 
141  if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) || ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
142  {
143  SCIPdebugMessage("creating constraint to force multi-aggregated variable <%s> to 0.\n", SCIPvarGetName(var));
144  /* we have to insert a local constraint var = 0 */
145  SCIP_CALL( SCIPcreateConsLinear(scip, &cons, "branch", 1, &var, &val, 0.0, 0.0, TRUE, TRUE, TRUE, TRUE, TRUE,
146  TRUE, FALSE, FALSE, FALSE, FALSE) );
147  SCIP_CALL( SCIPaddConsNode(scip, node, cons, NULL) );
148  SCIP_CALL( SCIPreleaseCons(scip, &cons) );
149  }
150  }
151  else
152  {
153  if ( ! SCIPisFeasZero(scip, SCIPvarGetLbLocal(var)) )
154  SCIP_CALL( SCIPchgVarLbNode(scip, node, var, 0.0) );
155  if ( ! SCIPisFeasZero(scip, SCIPvarGetUbLocal(var)) )
156  SCIP_CALL( SCIPchgVarUbNode(scip, node, var, 0.0) );
157  }
158 
159  return SCIP_OKAY;
160 }
161 
162 
163 /** fix variable in local node to 0, and return whether the operation was feasible
164  *
165  * @note We do not add a linear constraint if the variable is multi-aggregated as in
166  * fixVariableZeroNode(), since this would be too time consuming.
167  */
168 static
170  SCIP* scip, /**< SCIP pointer */
171  SCIP_VAR* var, /**< variable to be fixed to 0*/
172  SCIP_CONS* cons, /**< constraint */
173  int inferinfo, /**< info for reverse prop. */
174  SCIP_Bool* infeasible, /**< if fixing is infeasible */
175  SCIP_Bool* tightened, /**< if fixing was performed */
176  SCIP_Bool* success /**< whether fixing was successful, i.e., variable is not multi-aggregated */
177  )
178 {
179  *infeasible = FALSE;
180  *tightened = FALSE;
181  *success = FALSE;
182 
183  /* if variable cannot be nonzero */
185  {
186  *infeasible = TRUE;
187  return SCIP_OKAY;
188  }
189 
190  /* directly fix variable if it is not multi-aggregated, do nothing otherwise */
192  {
193  SCIP_Bool tighten;
194 
195  /* fix lower bound */
196  SCIP_CALL( SCIPinferVarLbCons(scip, var, 0.0, cons, inferinfo, FALSE, infeasible, &tighten) );
197  *tightened = *tightened || tighten;
198 
199  /* fix upper bound */
200  SCIP_CALL( SCIPinferVarUbCons(scip, var, 0.0, cons, inferinfo, FALSE, infeasible, &tighten) );
201  *tightened = *tightened || tighten;
202 
203  *success = TRUE;
204  }
205 
206  return SCIP_OKAY;
207 }
208 
209 
210 /** add lock on variable */
211 static
213  SCIP* scip, /**< SCIP data structure */
214  SCIP_CONS* cons, /**< constraint */
215  SCIP_VAR* var /**< variable */
216  )
217 {
218  assert( scip != NULL );
219  assert( cons != NULL );
220  assert( var != NULL );
221 
222  /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
224 
225  return SCIP_OKAY;
226 }
227 
228 
229 /* remove lock on variable */
230 static
232  SCIP* scip, /**< SCIP data structure */
233  SCIP_CONS* cons, /**< constraint */
234  SCIP_VAR* var /**< variable */
235  )
236 {
237  assert( scip != NULL );
238  assert( cons != NULL );
239  assert( var != NULL );
240 
241  /* rounding down == bad if lb < 0, rounding up == bad if ub > 0 */
243 
244  return SCIP_OKAY;
245 }
246 
247 
248 /** ensures that the vars and weights array can store at least num entries */
249 static
251  SCIP* scip, /**< SCIP data structure */
252  SCIP_CONSDATA* consdata, /**< constraint data */
253  int num, /**< minimum number of entries to store */
254  SCIP_Bool reserveWeights /**< whether the weights array is handled */
255  )
256 {
257  assert( consdata != NULL );
258  assert( consdata->nvars <= consdata->maxvars );
259 
260  if ( num > consdata->maxvars )
261  {
262  int newsize;
263 
264  newsize = SCIPcalcMemGrowSize(scip, num);
265  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->vars, consdata->maxvars, newsize) );
266  if ( reserveWeights )
267  SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &consdata->weights, consdata->maxvars, newsize) );
268  consdata->maxvars = newsize;
269  }
270  assert( num <= consdata->maxvars );
271 
272  return SCIP_OKAY;
273 }
274 
275 
276 /** handle new variable */
277 static
279  SCIP* scip, /**< SCIP data structure */
280  SCIP_CONS* cons, /**< constraint */
281  SCIP_CONSDATA* consdata, /**< constraint data */
282  SCIP_VAR* var, /**< variable */
283  SCIP_Bool transformed /**< whether original variable was transformed */
284  )
285 {
286  assert( scip != NULL );
287  assert( cons != NULL );
288  assert( consdata != NULL );
289  assert( var != NULL );
290 
291  /* if we are in transformed problem, catch the variable's events */
292  if ( transformed )
293  {
294  SCIP_CONSHDLR* conshdlr;
295  SCIP_CONSHDLRDATA* conshdlrdata;
296 
297  /* get event handler */
298  conshdlr = SCIPconsGetHdlr(cons);
299  conshdlrdata = SCIPconshdlrGetData(conshdlr);
300  assert( conshdlrdata != NULL );
301  assert( conshdlrdata->eventhdlr != NULL );
302 
303  /* catch bound change events of variable */
304  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlr,
305  (SCIP_EVENTDATA*)consdata, NULL) );
306 
307  /* if the variable if fixed to nonzero */
308  assert( consdata->nfixednonzeros >= 0 );
310  ++consdata->nfixednonzeros;
311  }
312 
313  /* install the rounding locks for the new variable */
314  SCIP_CALL( lockVariableSOS2(scip, cons, var) );
315 
316  /* add the new coefficient to the LP row, if necessary */
317  if ( consdata->row != NULL )
318  {
319  /* this is currently dead code, since the constraint is not modifiable */
320  SCIP_CALL( SCIPaddVarToRow(scip, consdata->row, var, 1.0) );
321 
322  /* update lhs and rhs if necessary */
323  if ( SCIPisFeasGT(scip, SCIPvarGetUbLocal(var), SCIProwGetRhs(consdata->row)) )
324  SCIP_CALL( SCIPchgRowRhs(scip, consdata->row, SCIPvarGetUbLocal(var) ) );
325  if ( SCIPisFeasLT(scip, SCIPvarGetLbLocal(var), SCIProwGetLhs(consdata->row)) )
326  SCIP_CALL( SCIPchgRowLhs(scip, consdata->row, SCIPvarGetLbLocal(var) ) );
327  }
328 
329  return SCIP_OKAY;
330 }
331 
332 
333 /** adds a variable to an SOS2 constraint, a position given by weight - ascending order */
334 static
336  SCIP* scip, /**< SCIP data structure */
337  SCIP_CONS* cons, /**< constraint */
338  SCIP_VAR* var, /**< variable to add to the constraint */
339  SCIP_Real weight /**< weight to determine position */
340  )
341 {
342  SCIP_CONSDATA* consdata;
343  SCIP_Bool transformed;
344  int j;
345  int pos;
346 
347  assert( var != NULL );
348  assert( cons != NULL );
349 
350  consdata = SCIPconsGetData(cons);
351  assert( consdata != NULL );
352 
353  if ( consdata->weights == NULL && consdata->maxvars > 0 )
354  {
355  SCIPerrorMessage("cannot add variable to SOS2 constraint <%s> that does not contain weights.\n", SCIPconsGetName(cons));
356  return SCIP_INVALIDCALL;
357  }
358 
359  /* are we in the transformed problem? */
360  transformed = SCIPconsIsTransformed(cons);
361 
362  /* always use transformed variables in transformed constraints */
363  if ( transformed )
364  {
365  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
366  }
367  assert( var != NULL );
368  assert( transformed == SCIPvarIsTransformed(var) );
369 
370  SCIP_CALL( consdataEnsurevarsSizeSOS2(scip, consdata, consdata->nvars + 1, TRUE) );
371  assert( consdata->weights != NULL );
372  assert( consdata->maxvars >= consdata->nvars+1 );
373 
374  /* find variable position */
375  for (pos = 0; pos < consdata->nvars; ++pos)
376  {
377  if ( consdata->weights[pos] > weight )
378  break;
379  }
380  assert( 0 <= pos && pos <= consdata->nvars );
381 
382  /* move other variables, if necessary */
383  for (j = consdata->nvars; j > pos; --j)
384  {
385  consdata->vars[j] = consdata->vars[j-1];
386  consdata->weights[j] = consdata->weights[j-1];
387  }
388 
389  /* insert variable */
390  consdata->vars[pos] = var;
391  consdata->weights[pos] = weight;
392  ++consdata->nvars;
393 
394  /* handle the new variable */
395  SCIP_CALL( handleNewVariableSOS2(scip, cons, consdata, var, transformed) );
396 
397  return SCIP_OKAY;
398 }
399 
400 
401 /** appends a variable to an SOS2 constraint */
402 static
404  SCIP* scip, /**< SCIP data structure */
405  SCIP_CONS* cons, /**< constraint */
406  SCIP_VAR* var /**< variable to add to the constraint */
407  )
408 {
409  SCIP_CONSDATA* consdata;
410  SCIP_Bool transformed;
411 
412  assert( var != NULL );
413  assert( cons != NULL );
414 
415  consdata = SCIPconsGetData(cons);
416  assert( consdata != NULL );
417 
418  /* are we in the transformed problem? */
419  transformed = SCIPconsIsTransformed(cons);
420 
421  /* always use transformed variables in transformed constraints */
422  if ( transformed )
423  {
424  SCIP_CALL( SCIPgetTransformedVar(scip, var, &var) );
425  }
426  assert( var != NULL );
427  assert( transformed == SCIPvarIsTransformed(var) );
428 
429  SCIP_CALL( consdataEnsurevarsSizeSOS2(scip, consdata, consdata->nvars + 1, FALSE) );
430 
431  /* insert variable */
432  consdata->vars[consdata->nvars] = var;
433  assert( consdata->weights != NULL || consdata->nvars > 0 );
434  if ( consdata->weights != NULL && consdata->nvars > 0 )
435  consdata->weights[consdata->nvars] = consdata->weights[consdata->nvars-1] + 1.0;
436  ++consdata->nvars;
437 
438  /* handle the new variable */
439  SCIP_CALL( handleNewVariableSOS2(scip, cons, consdata, var, transformed) );
440 
441  return SCIP_OKAY;
442 }
443 
444 
445 /** deletes a variable of an SOS2 constraint */
446 static
448  SCIP* scip, /**< SCIP data structure */
449  SCIP_CONS* cons, /**< constraint */
450  SCIP_CONSDATA* consdata, /**< constraint data */
451  SCIP_EVENTHDLR* eventhdlr, /**< corresponding event handler */
452  int pos /**< position of variable in array */
453  )
454 {
455  int j;
456 
457  assert( 0 <= pos && pos < consdata->nvars );
458 
459  /* remove lock of variable */
460  SCIP_CALL( unlockVariableSOS2(scip, cons, consdata->vars[pos]) );
461 
462  /* drop events on variable */
463  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[pos], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
464 
465  /* delete variable - need to copy since order is important */
466  for (j = pos; j < consdata->nvars-1; ++j)
467  {
468  consdata->vars[j] = consdata->vars[j+1]; /*lint !e679*/
469  if ( consdata->weights != NULL )
470  consdata->weights[j] = consdata->weights[j+1]; /*lint !e679*/
471  }
472  --consdata->nvars;
473 
474  return SCIP_OKAY;
475 }
476 
477 
478 /** perform one presolving round
479  *
480  * We perform the following presolving steps.
481  *
482  * - If the bounds of one variable force it to be nonzero, we can fix all other variables with distance at least two to
483  * zero. If two variables are certain to be nonzero, we can fix all other variables to 0 and remove the constraint.
484  * - All variables fixed to zero, that are at the beginning or end of the constraint can be removed.
485  * - We substitute appregated variables.
486  * - If a constraint has at most two variables, we delete it.
487  *
488  * We currently do not handle the following:
489  *
490  * - If we have at least two variables fixed to zero next to each-other, that are positioned in the inner part of this
491  * constraint, we can delete all but one of these variables.
492  * - If a variable appears twice not next to each-other, it can be fixed to 0. If one variable appears next to
493  * each-other and is already certain to be nonzero, we can fix all variables.
494  * - If a binary variable and its negation appear in the constraint, we might fix variables to zero or can forbid a zero
495  * value for them.
496  * - When, after removing all zero "border" variables, a constraint with more than two variables has at most two
497  * variables that are not fixed to 0, only one of these can take a nonzero value, because these variables need to be
498  * the "border" variables of this constraint. The same holds if we have exactly three variables in one constraint and
499  * the middle variable is certain to be not zero. In both cases we can upgrade this constraint constraint to an sos1
500  * consisting only of the "border" variables. If these "border" variables are negations of each other, we can delete
501  * this constraint.
502  * - When, after removing all variables fixed to 0, that are possible, in a constraint each even positioned variable is
503  * fixed to 0, we can upgrade this constraint to an sos1 that holds all non-fixed variables.
504  * - Extract cliques for all odd and also for all even positioned binary variables
505  */
506 static
508  SCIP* scip, /**< SCIP pointer */
509  SCIP_CONS* cons, /**< constraint */
510  SCIP_CONSDATA* consdata, /**< constraint data */
511  SCIP_EVENTHDLR* eventhdlr, /**< event handler */
512  SCIP_Bool* cutoff, /**< whether a cutoff happened */
513  SCIP_Bool* success, /**< whether we performed a successful reduction */
514  int* ndelconss, /**< number of deleted constraints */
515  int* nfixedvars, /**< number of fixed variables */
516  int* nremovedvars /**< number of variables removed */
517  )
518 {
519  SCIP_VAR** vars;
520  SCIP_Bool infeasible;
521  SCIP_Bool fixed;
522  int nfixednonzeros;
523  int lastFixedNonzero;
524  int lastzero;
525  int localnremovedvars;
526  int oldnfixedvars;
527  int j;
528 
529  assert( scip != NULL );
530  assert( cons != NULL );
531  assert( consdata != NULL );
532  assert( eventhdlr != NULL );
533  assert( cutoff != NULL );
534  assert( success != NULL );
535  assert( ndelconss != NULL );
536  assert( nfixedvars != NULL );
537  assert( nremovedvars != NULL );
538 
539  *cutoff = FALSE;
540  *success = FALSE;
541 
542  SCIPdebugMessage("Presolving SOS2 constraint <%s>.\n", SCIPconsGetName(cons) );
543 
544  /* if the number of variables is at most 2 */
545  if( consdata->nvars <= 2 )
546  {
547  SCIPdebugMessage("Deleting constraint with <= 2 variables.\n");
548 
549  /* delete constraint */
550  assert( ! SCIPconsIsModifiable(cons) );
551  SCIP_CALL( SCIPdelCons(scip, cons) );
552  ++(*ndelconss);
553  *success = TRUE;
554 
555  return SCIP_OKAY;
556  }
557 
558  nfixednonzeros = 0;
559  lastFixedNonzero = -1;
560  vars = consdata->vars;
561  lastzero = consdata->nvars;
562  localnremovedvars = 0;
563 
564  /* check for variables fixed to 0 and bounds that guarantee a variable to be nonzero; downward loop is important */
565  for( j = consdata->nvars - 1; j >= 0; --j )
566  {
567  SCIP_VAR* var;
568  SCIP_Real lb;
569  SCIP_Real ub;
570  SCIP_Real scalar;
571  SCIP_Real constant;
572 
573  /* check that our vars array is still correct */
574  assert(vars == consdata->vars);
575 
576  scalar = 1.0;
577  constant = 0.0;
578 
579  /* check aggregation: if the constant is zero, the variable is zero iff the aggregated variable is 0 */
580  var = vars[j];
581  SCIP_CALL( SCIPgetProbvarSum(scip, &var, &scalar, &constant) );
582 
583  /* if constant is zero and we get a different variable, substitute variable */
584  if ( SCIPisZero(scip, constant) && ! SCIPisZero(scip, scalar) && var != vars[j] )
585  {
586  SCIPdebugMessage("substituted variable <%s> by <%s>.\n", SCIPvarGetName(vars[j]), SCIPvarGetName(var));
587  SCIP_CALL( SCIPdropVarEvent(scip, consdata->vars[j], SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, (SCIP_EVENTDATA*)consdata, -1) );
588  SCIP_CALL( SCIPcatchVarEvent(scip, var, SCIP_EVENTTYPE_BOUNDCHANGED, eventhdlr, (SCIP_EVENTDATA*)consdata, NULL) );
589 
590  /* change the rounding locks */
591  SCIP_CALL( unlockVariableSOS2(scip, cons, consdata->vars[j]) );
592  SCIP_CALL( lockVariableSOS2(scip, cons, var) );
593 
594  vars[j] = var;
595  }
596 
597  /* get bounds */
598  lb = SCIPvarGetLbLocal(vars[j]);
599  ub = SCIPvarGetUbLocal(vars[j]);
600 
601  /* if the variable if fixed to nonzero */
602  if ( SCIPisFeasPositive(scip, lb) || SCIPisFeasNegative(scip, ub) )
603  {
604  ++nfixednonzeros;
605 
606  /* two variables certain to be nonzero which are not next to each other, so we are infeasible */
607  if( lastFixedNonzero != -1 && lastFixedNonzero != j + 1 )
608  {
609  SCIPdebugMessage("The problem is infeasible: two non-consecutive variables have bounds that keep them from being 0.\n");
610  *cutoff = TRUE;
611  return SCIP_OKAY;
612  }
613 
614  /* if more than two variables are fixed to be nonzero, we are infeasible */
615  if( nfixednonzeros > 2 )
616  {
617  SCIPdebugMessage("The problem is infeasible: more than two variables have bounds that keep them from being 0.\n");
618  *cutoff = TRUE;
619  return SCIP_OKAY;
620  }
621 
622  if( lastFixedNonzero == -1)
623  lastFixedNonzero = j;
624  }
625 
626  /* if the variable is fixed to 0 we may delete it from our constraint */
627  if( SCIPisFeasZero(scip, lb) && SCIPisFeasZero(scip, ub) )
628  {
629  /* all rear variables fixed to 0 can be deleted */
630  if( j == consdata->nvars - 1 )
631  {
632  ++(*nremovedvars);
633 
634  SCIPdebugMessage("deleting variable <%s> fixed to 0.\n", SCIPvarGetName(vars[j]));
635  SCIP_CALL( deleteVarSOS2(scip, cons, consdata, eventhdlr, j) );
636 
637  *success = TRUE;
638  }
639  /* remember position of last variable for which all up front and this one are fixed to 0 */
640  else if( lastzero > j + 1 )
641  lastzero = j;
642  }
643  else
644  lastzero = consdata->nvars;
645  }
646 
647  /* check that our vars array is still correct */
648  assert(vars == consdata->vars);
649 
650  /* remove first "lastzero" many variables, that are already fixed to 0 */
651  if( lastzero < consdata->nvars )
652  {
653  assert(lastzero >= 0);
654 
655  for( j = lastzero; j >= 0; --j )
656  {
657  /* the variables should all be fixed to zero */
658  assert(SCIPisFeasZero(scip, SCIPvarGetLbGlobal(vars[j])) && SCIPisFeasZero(scip, SCIPvarGetUbGlobal(vars[j])));
659 
660  SCIPdebugMessage("deleting variable <%s> fixed to 0.\n", SCIPvarGetName(vars[j]));
661  SCIP_CALL( deleteVarSOS2(scip, cons, consdata, eventhdlr, j) );
662  }
663  localnremovedvars += (lastzero + 1);
664  *success = TRUE;
665  }
666 
667  /* check that our variable array is still correct */
668  assert(vars == consdata->vars);
669 
670  *nremovedvars += localnremovedvars;
671 
672  /* we might need to correct the position of the first variable which is certain to be not zero */
673  if( lastFixedNonzero >= 0 )
674  {
675  lastFixedNonzero -= localnremovedvars;
676  assert(0 <= lastFixedNonzero && lastFixedNonzero < consdata->nvars);
677  assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero])) || SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero])));
678  }
679 
680  /* if the number of variables is at most 2 */
681  if( consdata->nvars <= 2 )
682  {
683  SCIPdebugMessage("Deleting constraint with <= 2 variables.\n");
684 
685  /* delete constraint */
686  assert( ! SCIPconsIsModifiable(cons) );
687  SCIP_CALL( SCIPdelCons(scip, cons) );
688  ++(*ndelconss);
689  *success = TRUE;
690 
691  return SCIP_OKAY;
692  }
693 
694  oldnfixedvars = *nfixedvars;
695 
696  /* if there is exactly one fixed nonzero variable */
697  if ( nfixednonzeros == 1 )
698  {
699  assert(0 <= lastFixedNonzero && lastFixedNonzero < consdata->nvars);
700  assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero])) ||
701  SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero])));
702 
703  /* fix all other variables with distance two to zero */
704  for( j = 0; j < lastFixedNonzero - 1; ++j )
705  {
706  SCIPdebugMessage("fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
707  SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
708 
709  if( infeasible )
710  {
711  *cutoff = TRUE;
712  return SCIP_OKAY;
713  }
714 
715  if ( fixed )
716  ++(*nfixedvars);
717  }
718  for( j = lastFixedNonzero + 2; j < consdata->nvars; ++j )
719  {
720  SCIPdebugMessage("fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
721  SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
722 
723  if( infeasible )
724  {
725  *cutoff = TRUE;
726  return SCIP_OKAY;
727  }
728 
729  if ( fixed )
730  ++(*nfixedvars);
731  }
732 
733  if( *nfixedvars > oldnfixedvars )
734  *success = TRUE;
735  }
736  /* if there are exactly two fixed nonzero variables */
737  else if ( nfixednonzeros == 2 )
738  {
739  assert(0 < lastFixedNonzero && lastFixedNonzero < consdata->nvars);
740  assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero])) ||
741  SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero])));
742  /* the previous variable need also to be nonzero, otherwise the infeasibility should have been detected earlier */
743  assert(SCIPisFeasPositive(scip, SCIPvarGetLbGlobal(vars[lastFixedNonzero - 1])) ||
744  SCIPisFeasNegative(scip, SCIPvarGetUbGlobal(vars[lastFixedNonzero - 1])));
745 
746  /* fix all variables before lastFixedNonzero to zero */
747  for( j = 0; j < lastFixedNonzero - 1; ++j )
748  {
749  SCIPdebugMessage("fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
750  SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
751 
752  if( infeasible )
753  {
754  *cutoff = TRUE;
755  return SCIP_OKAY;
756  }
757  if ( fixed )
758  ++(*nfixedvars);
759  }
760  /* fix all variables after lastFixedNonzero + 1 to zero */
761  for( j = lastFixedNonzero + 1; j < consdata->nvars; ++j )
762  {
763  SCIPdebugMessage("fixing variable <%s> to 0.\n", SCIPvarGetName(vars[j]));
764  SCIP_CALL( SCIPfixVar(scip, vars[j], 0.0, &infeasible, &fixed) );
765 
766  if( infeasible )
767  {
768  *cutoff = TRUE;
769  return SCIP_OKAY;
770  }
771  if ( fixed )
772  ++(*nfixedvars);
773  }
774 
775  /* delete constraint */
776  assert( ! SCIPconsIsModifiable(cons) );
777  SCIP_CALL( SCIPdelCons(scip, cons) );
778  ++(*ndelconss);
779  *success = TRUE;
780  }
781 
782  return SCIP_OKAY;
783 }
784 
785 
786 /** propagate variables */
787 static
789  SCIP* scip, /**< SCIP pointer */
790  SCIP_CONS* cons, /**< constraint */
791  SCIP_CONSDATA* consdata, /**< constraint data */
792  SCIP_Bool* cutoff, /**< whether a cutoff happened */
793  int* ngen /**< pointer to incremental counter for domain changes */
794  )
795 {
796  int ngenold;
797 
798  assert( scip != NULL );
799  assert( cons != NULL );
800  assert( consdata != NULL );
801  assert( cutoff != NULL );
802  assert( ngen != NULL );
803 
804  *cutoff = FALSE;
805  ngenold = *ngen;
806 
807  /* if more than two variables are fixed to be nonzero */
808  if ( consdata->nfixednonzeros > 2 )
809  {
810  SCIPdebugMessage("the node is infeasible, more than 2 variables are fixed to be nonzero.\n");
811  SCIP_CALL( SCIPresetConsAge(scip, cons) );
812  *cutoff = TRUE;
813  return SCIP_OKAY;
814  }
815 
816  /* if exactly one variable is fixed to be nonzero */
817  if ( consdata->nfixednonzeros == 1 )
818  {
819  SCIP_VAR** vars;
820  SCIP_Bool infeasible;
821  SCIP_Bool tightened;
822  SCIP_Bool success;
823  int firstFixedNonzero;
824  int nvars;
825  int j;
826 
827  firstFixedNonzero = -1;
828  nvars = consdata->nvars;
829  vars = consdata->vars;
830  assert( vars != NULL );
831 
832  /* search nonzero variable */
833  for (j = 0; j < nvars; ++j)
834  {
835  if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(vars[j])) )
836  {
837  firstFixedNonzero = j;
838  break;
839  }
840  }
841  assert( firstFixedNonzero >= 0 );
842 
843  SCIPdebugMessage("variable <%s> is nonzero, fixing variables with distance at least 2 to 0.\n", SCIPvarGetName(vars[firstFixedNonzero]));
844 
845  /* fix variables before firstFixedNonzero-1 to 0 */
846  for (j = 0; j < firstFixedNonzero-1; ++j)
847  {
848  /* fix variable */
849  SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
850  assert( ! infeasible );
851 
852  if ( tightened )
853  ++(*ngen);
854  }
855 
856  /* fix variables after firstFixedNonzero+1 to 0 */
857  for (j = firstFixedNonzero+2; j < nvars; ++j)
858  {
859  /* fix variable */
860  SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
861 
862  /* no variable after firstFixedNonzero+1 should be fixed to be nonzero */
863  if ( infeasible )
864  {
865  assert( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(vars[j])) );
866  SCIPdebugMessage("the node is infeasible: variable <%s> is fixed nonzero and variable <%s> with distance at least 2 as well.\n",
867  SCIPvarGetName(vars[firstFixedNonzero]), SCIPvarGetName(vars[j]));
868  *cutoff = TRUE;
869  return SCIP_OKAY;
870  }
871 
872  if ( tightened )
873  ++(*ngen);
874  }
875  /* cannot locally delete constraint, since position of second entry is not fixed! */
876  }
877  /* if exactly two variables are fixed to be nonzero */
878  else if ( consdata->nfixednonzeros == 2 )
879  {
880  SCIP_VAR** vars;
881  SCIP_Bool infeasible;
882  SCIP_Bool tightened;
883  SCIP_Bool success;
884  SCIP_Bool allVarFixed;
885  int firstFixedNonzero;
886  int nvars;
887  int j;
888 
889  firstFixedNonzero = -1;
890  nvars = consdata->nvars;
891  vars = consdata->vars;
892  assert( vars != NULL );
893 
894  /* search nonzero variable */
895  for (j = 0; j < nvars; ++j)
896  {
897  if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(vars[j])) )
898  {
899  firstFixedNonzero = j;
900  break;
901  }
902  }
903  assert( 0 <= firstFixedNonzero && firstFixedNonzero < nvars-1 );
904 
905  SCIPdebugMessage("variable <%s> is fixed to be nonzero, fixing variables to 0.\n", SCIPvarGetName(vars[firstFixedNonzero]));
906 
907  /* fix variables before firstFixedNonzero to 0 */
908  allVarFixed = TRUE;
909  for (j = 0; j < firstFixedNonzero; ++j)
910  {
911  /* fix variable */
912  SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero+1, &infeasible, &tightened, &success) );
913  assert( ! infeasible );
914  allVarFixed = allVarFixed && success;
915  if ( tightened )
916  ++(*ngen);
917  }
918 
919  /* fix variables after firstFixedNonzero+1 to 0 */
920  for (j = firstFixedNonzero+2; j < nvars; ++j)
921  {
922  /* fix variable */
923  SCIP_CALL( inferVariableZero(scip, vars[j], cons, firstFixedNonzero, &infeasible, &tightened, &success) );
924 
925  /* no variable after firstFixedNonzero+1 should be fixed to be nonzero */
926  if ( infeasible )
927  {
928  assert( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(vars[j])) );
929  SCIPdebugMessage("the node is infeasible: variable <%s> is fixed nonzero and variable <%s> with distance at least 2 as well.\n",
930  SCIPvarGetName(vars[firstFixedNonzero]), SCIPvarGetName(vars[j]));
931  *cutoff = TRUE;
932  return SCIP_OKAY;
933  }
934  allVarFixed = allVarFixed && success;
935 
936  if ( tightened )
937  ++(*ngen);
938  }
939 
940  /* delete constraint locally, since the nonzero positions are fixed */
941  if ( allVarFixed )
942  {
943  SCIPdebugMessage("locally deleting constraint <%s>.\n", SCIPconsGetName(cons));
944  assert( !SCIPconsIsModifiable(cons) );
945  SCIP_CALL( SCIPdelConsLocal(scip, cons) );
946  }
947  }
948 
949  /* reset constraint age counter */
950  if ( *ngen > ngenold )
951  SCIP_CALL( SCIPresetConsAge(scip, cons) );
952 
953  return SCIP_OKAY;
954 }
955 
956 
957 /** enforcement method
958  *
959  * We check whether the current solution is feasible, i.e., contains
960  * at most one nonzero variable. If not, we branch along the lines
961  * indicated by Beale and Tomlin:
962  *
963  * We first compute \f$W = \sum_{j=1}^n |x_i|\f$ and \f$w =
964  * \sum_{j=1}^n j\, |x_i|\f$. Then we search for the index \f$k\f$ that
965  * satisfies
966  * \f[
967  * k \leq \frac{w}{W} < k+1.
968  * \f]
969  * The branches are then
970  * \f[
971  * x_1 = 0, \ldots, x_{k-1} = 0 \qquad \mbox{and}\qquad
972  * x_{k+1} = 0, \ldots, x_n = 0.
973  * \f]
974  *
975  * There is one special case that we have to consider: It can happen
976  * that \f$k\f$ is one too small. Example: \f$x_1 = 1 - \epsilon, x_2
977  * = 0, x_3 = \epsilon\f$. Then \f$w = 1 - \epsilon + 3 \epsilon = 1
978  * + 2 \epsilon\f$. This yields \f$k = 1\f$ and hence the first
979  * branch does not change the solution. We therefore increase \f$k\f$
980  * by one if \f$x_k \neq 0\f$. This is valid, since we know that
981  * \f$x_{k+1} \neq 0\f$ (with respect to the original \f$k\f$); the
982  * corresponding branch will cut off the current solution, since
983  * \f$x_k \neq 0\f$.
984  */
985 static
987  SCIP* scip, /**< SCIP pointer */
988  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
989  int nconss, /**< number of constraints */
990  SCIP_CONS** conss, /**< indicator constraints */
991  SCIP_RESULT* result /**< result */
992  )
993 {
994  SCIP_CONSDATA* consdata;
995  SCIP_Bool infeasible;
996  SCIP_NODE* node1;
997  SCIP_NODE* node2;
999  SCIP_VAR** vars;
1000  SCIP_Real nodeselest;
1001  SCIP_Real objest;
1002  int nvars;
1003  int maxNonzeros;
1004  int maxInd;
1005  int j;
1006  int c;
1007 
1008  assert( scip != NULL );
1009  assert( conshdlr != NULL );
1010  assert( conss != NULL );
1011  assert( result != NULL );
1012 
1013  maxNonzeros = 0;
1014  maxInd = -1;
1015 
1016  SCIPdebugMessage("Enforcing SOS2 constraints <%s>.\n", SCIPconshdlrGetName(conshdlr) );
1017  *result = SCIP_FEASIBLE;
1018 
1019  /* check each constraint */
1020  for (c = 0; c < nconss; ++c)
1021  {
1022  SCIP_CONS* cons;
1023  SCIP_Bool cutoff;
1024  SCIP_Real weight1;
1025  SCIP_Real weight2;
1026  SCIP_Real w;
1027  int lastNonzero;
1028  int ngen;
1029  int cnt;
1030  int ind;
1031 
1032  cons = conss[c];
1033  assert( cons != NULL );
1034 
1035  consdata = SCIPconsGetData(cons);
1036  assert( consdata != NULL );
1037 
1038  nvars = consdata->nvars;
1039  vars = consdata->vars;
1040 
1041  /* do nothing if there are not enough variables - this is usually eliminated by preprocessing */
1042  if ( nvars <= 2 )
1043  return SCIP_OKAY;
1044 
1045  ngen = 0;
1046 
1047  /* first perform propagation (it might happen that standard propagation is turned off) */
1048  SCIP_CALL( propSOS2(scip, cons, consdata, &cutoff, &ngen) );
1049  SCIPdebugMessage("propagating <%s> in enforcing (cutoff: %u, domain reductions: %d).\n", SCIPconsGetName(cons), cutoff, ngen);
1050  if ( cutoff )
1051  {
1052  *result = SCIP_CUTOFF;
1053  return SCIP_OKAY;
1054  }
1055  if ( ngen > 0 )
1056  {
1057  *result = SCIP_REDUCEDDOM;
1058  return SCIP_OKAY;
1059  }
1060 
1061  cnt = 0;
1062  weight1 = 0.0;
1063  weight2 = 0.0;
1064  lastNonzero = -1;
1065 
1066  /* compute weight */
1067  for (j = 0; j < nvars; ++j)
1068  {
1069  SCIP_Real val;
1070 
1071  val = REALABS(SCIPgetSolVal(scip, NULL, vars[j]));
1072  weight1 += val * (SCIP_Real) j;
1073  weight2 += val;
1074 
1075  if ( ! SCIPisFeasZero(scip, val) )
1076  {
1077  lastNonzero = j;
1078  ++cnt;
1079  }
1080  }
1081 
1082  /* if at most one variable is nonzero, the constraint is feasible */
1083  if ( cnt < 2 )
1084  continue;
1085 
1086  /* if two adjacent variables are nonzero */
1087  assert( 0 < lastNonzero && lastNonzero < nvars );
1088  if ( cnt == 2 && ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, NULL, vars[lastNonzero-1])) )
1089  continue;
1090 
1091  assert( !SCIPisFeasZero(scip, weight2) );
1092  w = weight1/weight2; /*lint !e795*/
1093 
1094  ind = (int) SCIPfeasFloor(scip, w);
1095  assert( 0 <= ind && ind < nvars-1 );
1096 
1097  /* correct index if necessary - see above for an explanation */
1098  if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, NULL, vars[ind])) && ind < lastNonzero-1 )
1099  ++ind;
1100 
1101  /* check if the constraint has more nonzeros */
1102  if ( cnt > maxNonzeros )
1103  {
1104  maxNonzeros = cnt;
1105  branchCons = cons;
1106  maxInd = ind;
1107  }
1108  }
1109 
1110  /* if all constraints are feasible */
1111  if ( branchCons == NULL )
1112  {
1113  SCIPdebugMessage("All SOS2 constraints are feasible.\n");
1114  return SCIP_OKAY;
1115  }
1116 
1117  /* create branches */
1118  consdata = SCIPconsGetData(branchCons);
1119  assert( consdata != NULL );
1120  nvars = consdata->nvars;
1121  vars = consdata->vars;
1122 
1123  assert( 0 < maxInd && maxInd < nvars-1 );
1124 
1125  /* branch on variable ind: either all variables before ind or all variables after ind are zero */
1126  SCIPdebugMessage("Branching on variable <%s> in constraint <%s> (nonzeros: %d).\n", SCIPvarGetName(vars[maxInd]),
1127  SCIPconsGetName(branchCons), maxNonzeros);
1128 
1129  /* calculate node selection and objective estimate for node 1 */
1130  nodeselest = 0.0;
1131  objest = 0.0;
1132  for (j = 0; j < maxInd; ++j)
1133  {
1134  nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
1135  objest += SCIPcalcChildEstimate(scip, vars[j], 0.0);
1136  }
1137  /* take the average of the individual estimates */
1138  objest = objest/((SCIP_Real) maxInd);
1139 
1140  /* create node 1 */
1141  SCIP_CALL( SCIPcreateChild(scip, &node1, nodeselest, objest) );
1142 
1143  for (j = 0; j < maxInd; ++j)
1144  {
1145  SCIP_CALL( fixVariableZeroNode(scip, vars[j], node1, &infeasible) );
1146  assert( ! infeasible );
1147  }
1148 
1149  /* calculate node selection and objective estimate for node 2 */
1150  nodeselest = 0.0;
1151  objest = 0.0;
1152  for (j = maxInd+1; j < nvars; ++j)
1153  {
1154  nodeselest += SCIPcalcNodeselPriority(scip, vars[j], SCIP_BRANCHDIR_DOWNWARDS, 0.0);
1155  objest += SCIPcalcChildEstimate(scip, vars[j], 0.0);
1156  }
1157  /* take the average of the individual estimates */
1158  objest = objest/((SCIP_Real) (nvars-maxInd-1));
1159 
1160  /* create node 2 */
1161  SCIP_CALL( SCIPcreateChild(scip, &node2, nodeselest, objest) );
1162  for (j = maxInd+1; j < nvars; ++j)
1163  {
1164  SCIP_CALL( fixVariableZeroNode(scip, vars[j], node2, &infeasible) );
1165  assert( ! infeasible );
1166  }
1167  SCIP_CALL( SCIPresetConsAge(scip, branchCons) );
1168  *result = SCIP_BRANCHED;
1169 
1170  return SCIP_OKAY;
1171 }
1172 
1173 
1174 /** Generate basic row
1175  *
1176  * We generate the row corresponding to the following simple valid
1177  * inequalities. Let \f$U\f$ and \f$U'\f$ be the largest and second
1178  * largest upper bound of variables appearing in the
1179  * constraint. Similarly let \f$L\f$ and \f$L'\f$ be the smallest and
1180  * second smallest lower bound. The inequalities are:
1181  * \f[
1182  * x_1 + \ldots + x_n \leq U + U' \qquad\mbox{and}\qquad
1183  * x_1 + \ldots + x_n \geq L + L'.
1184  * \f]
1185  * Of course, these inequalities are only added if the upper and
1186  * lower bounds are all finite and \f$L+L' < 0\f$ or \f$U+U' > 0\f$.
1187  */
1188 static
1190  SCIP* scip, /**< SCIP pointer */
1191  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
1192  SCIP_CONS* cons, /**< constraint */
1193  SCIP_Bool local /**< produce local cut? */
1194  )
1195 {
1196  char name[SCIP_MAXSTRLEN];
1197  SCIP_CONSDATA* consdata;
1198  SCIP_VAR** vars;
1199  SCIP_Real minLb = SCIPinfinity(scip);
1200  SCIP_Real minLb2 = SCIPinfinity(scip);
1201  SCIP_Real maxUb = -SCIPinfinity(scip);
1202  SCIP_Real maxUb2 = -SCIPinfinity(scip);
1203  SCIP_Real lhs;
1204  SCIP_Real rhs;
1205  SCIP_ROW* row;
1206  int nvars;
1207  int j;
1208 
1209  assert( scip != NULL );
1210  assert( conshdlr != NULL );
1211  assert( cons != NULL );
1212 
1213  consdata = SCIPconsGetData(cons);
1214  assert( consdata != NULL );
1215  assert( consdata->row == NULL );
1216 
1217  nvars = consdata->nvars;
1218  vars = consdata->vars;
1219  assert( vars != NULL );
1220 
1221  /* find minimum and maximum lower and upper bounds */
1222  for (j = 0; j < nvars; ++j)
1223  {
1224  SCIP_Real val;
1225 
1226  if ( local )
1227  val = SCIPvarGetLbLocal(vars[j]);
1228  else
1229  val = SCIPvarGetLbGlobal(vars[j]);
1230 
1231  if ( val < minLb )
1232  {
1233  minLb2 = minLb;
1234  minLb = val;
1235  }
1236  else
1237  {
1238  if ( val < minLb2 )
1239  minLb2 = val;
1240  }
1241 
1242  if ( local )
1243  val = SCIPvarGetUbLocal(vars[j]);
1244  else
1245  val = SCIPvarGetUbGlobal(vars[j]);
1246 
1247  if ( val > maxUb )
1248  {
1249  maxUb2 = maxUb;
1250  maxUb = val;
1251  }
1252  else
1253  {
1254  if ( val > maxUb2 )
1255  maxUb2 = val;
1256  }
1257  }
1258  lhs = minLb + minLb2;
1259  rhs = maxUb + maxUb2;
1260 
1261  /* ignore trivial inequality if left hand side would be 0 */
1262  if ( SCIPisFeasZero(scip, lhs) )
1263  lhs = -SCIPinfinity(scip);
1264 
1265  /* ignore trivial inequality if right hand side would be 0 */
1266  if ( SCIPisFeasZero(scip, rhs) )
1267  rhs = SCIPinfinity(scip);
1268 
1269  /* create upper and lower bound inequality if one of the bounds is finite */
1270  if ( ! SCIPisInfinity(scip, REALABS(lhs)) || ! SCIPisInfinity(scip, REALABS(rhs)) )
1271  {
1272  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sos2bnd#%s", SCIPconsGetName(cons));
1273  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, name, lhs, rhs, local, FALSE, FALSE) );
1274  SCIP_CALL( SCIPaddVarsToRowSameCoef(scip, row, nvars, vars, 1.0) );
1275  consdata->row = row;
1276 
1277  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
1278  }
1279 
1280  return SCIP_OKAY;
1281 }
1282 
1283 
1284 /* ---------------------------- constraint handler callback methods ----------------------*/
1285 
1286 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1287 static
1288 SCIP_DECL_CONSHDLRCOPY(conshdlrCopySOS2)
1289 { /*lint --e{715}*/
1290  assert( scip != NULL );
1291  assert( conshdlr != NULL );
1292  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1293 
1294  /* call inclusion method of constraint handler */
1296 
1297  *valid = TRUE;
1298 
1299  return SCIP_OKAY;
1300 }
1301 
1302 
1303 /** destructor of constraint handler to free constraint handler data (called when SCIP is exiting) */
1304 static
1305 SCIP_DECL_CONSFREE(consFreeSOS2)
1307  SCIP_CONSHDLRDATA* conshdlrdata;
1308 
1309  assert( scip != NULL );
1310  assert( conshdlr != NULL );
1311  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1312 
1313  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1314  assert(conshdlrdata != NULL);
1315 
1316  SCIPfreeMemory(scip, &conshdlrdata);
1317 
1318  return SCIP_OKAY;
1319 }
1320 
1321 
1322 /** solving process deinitialization method of constraint handler (called before branch and bound process data is freed) */
1323 static
1324 SCIP_DECL_CONSEXITSOL(consExitsolSOS2)
1325 { /*lint --e{715}*/
1326  int c;
1327 
1328  assert( scip != NULL );
1329  assert( conshdlr != NULL );
1330  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1331 
1332  /* check each constraint */
1333  for (c = 0; c < nconss; ++c)
1334  {
1335  SCIP_CONSDATA* consdata;
1336 
1337  assert( conss != NULL );
1338  assert( conss[c] != NULL );
1339  consdata = SCIPconsGetData(conss[c]);
1340  assert( consdata != NULL );
1341 
1342  SCIPdebugMessage("Exiting SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
1343 
1344  /* free row */
1345  if ( consdata->row != NULL )
1346  {
1347  SCIP_CALL( SCIPreleaseRow(scip, &consdata->row) );
1348  }
1349  }
1350  return SCIP_OKAY;
1351 }
1352 
1353 
1354 /** frees specific constraint data */
1355 static
1356 SCIP_DECL_CONSDELETE(consDeleteSOS2)
1358  assert( scip != NULL );
1359  assert( conshdlr != NULL );
1360  assert( cons != NULL );
1361  assert( consdata != NULL );
1362  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1363 
1364  SCIPdebugMessage("Deleting SOS2 constraint <%s>.\n", SCIPconsGetName(cons) );
1365 
1366  /* drop events on transformed variables */
1367  if ( SCIPconsIsTransformed(cons) )
1368  {
1369  SCIP_CONSHDLRDATA* conshdlrdata;
1370  int j;
1371 
1372  /* get constraint handler data */
1373  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1374  assert( conshdlrdata != NULL );
1375  assert( conshdlrdata->eventhdlr != NULL );
1376 
1377  for (j = 0; j < (*consdata)->nvars; ++j)
1378  {
1379  SCIP_CALL( SCIPdropVarEvent(scip, (*consdata)->vars[j], SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlr,
1380  (SCIP_EVENTDATA*)*consdata, -1) );
1381  }
1382  }
1383 
1384  SCIPfreeBlockMemoryArray(scip, &(*consdata)->vars, (*consdata)->maxvars);
1385  if ( (*consdata)->weights != NULL )
1386  {
1387  SCIPfreeBlockMemoryArray(scip, &(*consdata)->weights, (*consdata)->maxvars);
1388  }
1389 
1390  /* free row */
1391  if ( (*consdata)->row != NULL )
1392  {
1393  SCIP_CALL( SCIPreleaseRow(scip, &(*consdata)->row) );
1394  }
1395  assert( (*consdata)->row == NULL );
1396 
1397  SCIPfreeBlockMemory(scip, consdata);
1398 
1399  return SCIP_OKAY;
1400 }
1401 
1402 
1403 /** transforms constraint data into data belonging to the transformed problem */
1404 static
1405 SCIP_DECL_CONSTRANS(consTransSOS2)
1407  SCIP_CONSDATA* consdata;
1408  SCIP_CONSHDLRDATA* conshdlrdata;
1409  SCIP_CONSDATA* sourcedata;
1410  char s[SCIP_MAXSTRLEN];
1411  int j;
1412 
1413  assert( scip != NULL );
1414  assert( conshdlr != NULL );
1415  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1416  assert( sourcecons != NULL );
1417  assert( targetcons != NULL );
1418 
1419  /* get constraint handler data */
1420  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1421  assert( conshdlrdata != NULL );
1422  assert( conshdlrdata->eventhdlr != NULL );
1423 
1424  SCIPdebugMessage("Transforming SOS2 constraint: <%s>.\n", SCIPconsGetName(sourcecons) );
1425 
1426  /* get data of original constraint */
1427  sourcedata = SCIPconsGetData(sourcecons);
1428  assert( sourcedata != NULL );
1429  assert( sourcedata->nvars > 0 );
1430  assert( sourcedata->nvars <= sourcedata->maxvars );
1431 
1432  /* create constraint data */
1433  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
1434 
1435  consdata->nvars = sourcedata->nvars;
1436  consdata->maxvars = sourcedata->nvars;
1437  consdata->row = NULL;
1438  consdata->nfixednonzeros = 0;
1439  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, consdata->nvars) );
1440 
1441  /* if weights were used */
1442  if ( sourcedata->weights != NULL )
1443  {
1444  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, sourcedata->weights, consdata->nvars) );
1445  }
1446  else
1447  consdata->weights = NULL;
1448 
1449  for (j = 0; j < sourcedata->nvars; ++j)
1450  {
1451  assert( sourcedata->vars[j] != 0 );
1452  SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[j], &(consdata->vars[j])) );
1453 
1454  /* if variable is fixed to be nonzero */
1455  if ( SCIPisFeasPositive(scip, SCIPvarGetLbLocal(consdata->vars[j])) || SCIPisFeasNegative(scip, SCIPvarGetUbLocal(consdata->vars[j])) )
1456  ++(consdata->nfixednonzeros);
1457  }
1458 
1459  /* create transformed constraint with the same flags */
1460  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
1461  SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
1462  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
1463  SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
1464  SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
1465  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
1466  SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1467 
1468  /* catch bound change events on variable */
1469  for (j = 0; j < consdata->nvars; ++j)
1470  {
1471  SCIP_CALL( SCIPcatchVarEvent(scip, consdata->vars[j], SCIP_EVENTTYPE_BOUNDCHANGED, conshdlrdata->eventhdlr,
1472  (SCIP_EVENTDATA*)consdata, NULL) );
1473  }
1474 
1475 #ifdef SCIP_DEBUG
1476  if ( consdata->nfixednonzeros > 0 )
1477  {
1478  SCIPdebugMessage("constraint <%s> has %d variables fixed to be nonzero.\n", SCIPconsGetName(*targetcons), consdata->nfixednonzeros );
1479  }
1480 #endif
1481 
1482  return SCIP_OKAY;
1483 }
1484 
1485 
1486 /** presolving method of constraint handler */
1487 static
1488 SCIP_DECL_CONSPRESOL(consPresolSOS2)
1489 { /*lint --e{715}*/
1490  int oldnfixedvars;
1491  int oldndelconss;
1492  int nremovedvars;
1493  SCIP_EVENTHDLR* eventhdlr;
1494  int c;
1495 
1496  assert( scip != NULL );
1497  assert( conshdlr != NULL );
1498  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1499  assert( result != NULL );
1500 
1501  *result = SCIP_DIDNOTRUN;
1502  oldnfixedvars = *nfixedvars;
1503  oldndelconss = *ndelconss;
1504  nremovedvars = 0;
1505 
1506  /* only run if success is possible */
1507  if( nrounds == 0 || nnewfixedvars > 0 || nnewaggrvars > 0 || nnewchgcoefs > 0 )
1508  {
1509  /* get constraint handler data */
1510  assert( SCIPconshdlrGetData(conshdlr) != NULL );
1511  eventhdlr = SCIPconshdlrGetData(conshdlr)->eventhdlr;
1512  assert( eventhdlr != NULL );
1513 
1514  *result = SCIP_DIDNOTFIND;
1515 
1516  /* check each constraint */
1517  for (c = 0; c < nconss; ++c)
1518  {
1519  SCIP_CONSDATA* consdata;
1520  SCIP_CONS* cons;
1521  SCIP_Bool cutoff;
1522  SCIP_Bool success;
1523 
1524  assert( conss != NULL );
1525  assert( conss[c] != NULL );
1526 
1527  cons = conss[c];
1528  consdata = SCIPconsGetData(cons);
1529 
1530  assert( consdata != NULL );
1531  assert( consdata->nvars >= 0 );
1532  assert( consdata->nvars <= consdata->maxvars );
1533  assert( ! SCIPconsIsModifiable(cons) );
1534 
1535  /* perform one presolving round */
1536  SCIP_CALL( presolRoundSOS2(scip, cons, consdata, eventhdlr, &cutoff, &success, ndelconss, nfixedvars, &nremovedvars) );
1537 
1538  if ( cutoff )
1539  {
1540  *result = SCIP_CUTOFF;
1541  return SCIP_OKAY;
1542  }
1543 
1544  if ( success )
1545  *result = SCIP_SUCCESS;
1546  }
1547  }
1548  (*nchgcoefs) += nremovedvars;
1549 
1550  SCIPdebugMessage("presolving fixed %d variables, removed %d variables, and deleted %d constraints.\n",
1551  *nfixedvars - oldnfixedvars, nremovedvars, *ndelconss - oldndelconss);
1552 
1553  return SCIP_OKAY;
1554 }
1555 
1556 
1557 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1558 static
1559 SCIP_DECL_CONSINITLP(consInitlpSOS2)
1561  int c;
1562 
1563  assert( scip != NULL );
1564  assert( conshdlr != NULL );
1565  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1566 
1567  /* check each constraint */
1568  for (c = 0; c < nconss; ++c)
1569  {
1570  SCIP_CONSDATA* consdata;
1571 
1572  assert( conss != NULL );
1573  assert( conss[c] != NULL );
1574  consdata = SCIPconsGetData(conss[c]);
1575  assert( consdata != NULL );
1576 
1577  SCIPdebugMessage("Checking for initial rows for SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
1578 
1579  /* possibly generate row if not yet done */
1580  if ( consdata->row == NULL )
1581  {
1582  SCIP_CALL( generateRowSOS2(scip, conshdlr, conss[c], FALSE) );
1583  }
1584 
1585  /* put corresponding rows into LP */
1586  if ( consdata->row != NULL && ! SCIProwIsInLP(consdata->row) )
1587  {
1588  SCIP_Bool infeasible;
1589 
1590  assert( ! SCIPisInfinity(scip, REALABS(SCIProwGetLhs(consdata->row))) || ! SCIPisInfinity(scip, REALABS(SCIProwGetRhs(consdata->row))) );
1591 
1592  SCIP_CALL( SCIPaddCut(scip, NULL, consdata->row, FALSE, &infeasible) );
1593  assert( ! infeasible );
1594  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, consdata->row, NULL) ) );
1595  }
1596  }
1597 
1598  return SCIP_OKAY;
1599 }
1600 
1601 
1602 /** separation method of constraint handler for LP solutions */
1603 static
1604 SCIP_DECL_CONSSEPALP(consSepalpSOS2)
1605 { /*lint --e{715}*/
1606  SCIP_Bool cutoff = FALSE;
1607  int c;
1608  int ngen = 0;
1609 
1610  assert( scip != NULL );
1611  assert( conshdlr != NULL );
1612  assert( conss != NULL );
1613  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1614  assert( result != NULL );
1615 
1616  *result = SCIP_DIDNOTRUN;
1617 
1618  /* check each constraint */
1619  for (c = 0; c < nconss && ! cutoff; ++c)
1620  {
1621  SCIP_CONSDATA* consdata;
1622  SCIP_ROW* row;
1623 
1624  *result = SCIP_DIDNOTFIND;
1625  assert( conss[c] != NULL );
1626  consdata = SCIPconsGetData(conss[c]);
1627  assert( consdata != NULL );
1628  SCIPdebugMessage("Separating inequalities for SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
1629 
1630  /* put corresponding rows into LP if they are useful */
1631  row = consdata->row;
1632 
1633  /* possibly generate row if not yet done */
1634  if ( row == NULL )
1635  {
1636  SCIP_CALL( generateRowSOS2(scip, conshdlr, conss[c], FALSE) );
1637  }
1638 
1639  /* possibly add row to LP if it is useful */
1640  if ( row != NULL && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, NULL, row) )
1641  {
1642  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, &cutoff) );
1643  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
1644  SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
1645  ++ngen;
1646  }
1647  }
1648  SCIPdebugMessage("Separated %d SOS2 constraints.\n", ngen);
1649  if ( cutoff )
1650  *result = SCIP_CUTOFF;
1651  else if ( ngen > 0 )
1652  *result = SCIP_SEPARATED;
1653 
1654  return SCIP_OKAY;
1655 }
1656 
1657 
1658 /** separation method of constraint handler for arbitrary primal solutions */
1659 static
1660 SCIP_DECL_CONSSEPASOL(consSepasolSOS2)
1661 { /*lint --e{715}*/
1662  SCIP_Bool cutoff = FALSE;
1663  int c;
1664  int ngen = 0;
1665 
1666  assert( scip != NULL );
1667  assert( conshdlr != NULL );
1668  assert( conss != NULL );
1669  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1670  assert( result != NULL );
1671 
1672  *result = SCIP_DIDNOTRUN;
1673 
1674  /* check each constraint */
1675  for (c = 0; c < nconss && ! cutoff; ++c)
1676  {
1677  SCIP_CONSDATA* consdata;
1678  SCIP_ROW* row;
1679 
1680  *result = SCIP_DIDNOTFIND;
1681  assert( conss[c] != NULL );
1682  consdata = SCIPconsGetData(conss[c]);
1683  assert( consdata != NULL );
1684  SCIPdebugMessage("Separating solution for SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]) );
1685 
1686  /* put corresponding row into LP if it is useful */
1687  row = consdata->row;
1688 
1689  /* possibly generate row if not yet done */
1690  if ( row == NULL )
1691  {
1692  SCIP_CALL( generateRowSOS2(scip, conshdlr, conss[c], FALSE) );
1693  }
1694 
1695  /* possibly add row to LP if it is useful */
1696  if ( row != NULL && ! SCIProwIsInLP(row) && SCIPisCutEfficacious(scip, sol, row) )
1697  {
1698  SCIP_CALL( SCIPaddCut(scip, sol, row, FALSE, &cutoff) );
1699  SCIPdebug( SCIP_CALL( SCIPprintRow(scip, row, NULL) ) );
1700  SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
1701  ++ngen;
1702  }
1703  }
1704  SCIPdebugMessage("Separated %d SOS2 constraints.\n", ngen);
1705  if ( cutoff )
1706  *result = SCIP_CUTOFF;
1707  else if ( ngen > 0 )
1708  *result = SCIP_SEPARATED;
1709 
1710  return SCIP_OKAY;
1711 }
1712 
1713 
1714 /** constraint enforcing method of constraint handler for LP solutions */
1715 static
1716 SCIP_DECL_CONSENFOLP(consEnfolpSOS2)
1717 { /*lint --e{715}*/
1718  assert( scip != NULL );
1719  assert( conshdlr != NULL );
1720  assert( conss != NULL );
1721  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1722  assert( result != NULL );
1723 
1724  SCIP_CALL( enforceSOS2(scip, conshdlr, nconss, conss, result) );
1725 
1726  return SCIP_OKAY;
1727 }
1728 
1729 
1730 /** constraint enforcing method of constraint handler for pseudo solutions */
1731 static
1732 SCIP_DECL_CONSENFOPS(consEnfopsSOS2)
1733 { /*lint --e{715}*/
1734  assert( scip != NULL );
1735  assert( conshdlr != NULL );
1736  assert( conss != NULL );
1737  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1738  assert( result != NULL );
1739 
1740  SCIP_CALL( enforceSOS2(scip, conshdlr, nconss, conss, result) );
1741 
1742  return SCIP_OKAY;
1743 }
1744 
1745 
1746 /** feasibility check method of constraint handler for integral solutions
1747  *
1748  * We simply check whether at most two variable are nonzero and in the
1749  * case there are exactly two nonzero, then they have to be direct
1750  * neighbors in the given solution.
1751  */
1752 static
1753 SCIP_DECL_CONSCHECK(consCheckSOS2)
1754 { /*lint --e{715}*/
1755  int c;
1756 
1757  assert( scip != NULL );
1758  assert( conshdlr != NULL );
1759  assert( conss != NULL );
1760  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1761  assert( result != NULL );
1762 
1763  /* check each constraint */
1764  for (c = 0; c < nconss; ++c)
1765  {
1766  SCIP_CONSDATA* consdata;
1767  int firstNonzero;
1768  int j;
1769 
1770  firstNonzero = -1;
1771  assert( conss[c] != NULL );
1772  consdata = SCIPconsGetData(conss[c]);
1773  assert( consdata != NULL );
1774  SCIPdebugMessage("Checking SOS2 constraint <%s>.\n", SCIPconsGetName(conss[c]));
1775 
1776  /* check all variables */
1777  for (j = 0; j < consdata->nvars; ++j)
1778  {
1779  /* if variable is nonzero */
1780  if ( ! SCIPisFeasZero(scip, SCIPgetSolVal(scip, sol, consdata->vars[j])) )
1781  {
1782  if ( firstNonzero < 0 )
1783  firstNonzero = j;
1784  else
1785  {
1786  /* if we are more than one position away from the firstNonzero variable */
1787  if ( j > firstNonzero+1 )
1788  {
1789  SCIP_CALL( SCIPresetConsAge(scip, conss[c]) );
1790  *result = SCIP_INFEASIBLE;
1791 
1792  if ( printreason )
1793  {
1794  SCIP_CALL( SCIPprintCons(scip, conss[c], NULL) );
1795 
1796  SCIPinfoMessage(scip, NULL, ";\nviolation: <%s> = %.15g and <%s> = %.15g\n",
1797  SCIPvarGetName(consdata->vars[firstNonzero]),
1798  SCIPgetSolVal(scip, sol, consdata->vars[firstNonzero]),
1799  SCIPvarGetName(consdata->vars[j]),
1800  SCIPgetSolVal(scip, sol, consdata->vars[j]));
1801  }
1802 
1803  SCIPdebugMessage("SOS2 constraint <%s> infeasible.\n", SCIPconsGetName(conss[c]));
1804  return SCIP_OKAY;
1805  }
1806  }
1807  }
1808  }
1809  }
1810  SCIPdebugMessage("All SOS2 constraint are feasible.\n");
1811  *result = SCIP_FEASIBLE;
1812 
1813  return SCIP_OKAY;
1814 }
1815 
1816 
1817 /** domain propagation method of constraint handler */
1818 static
1819 SCIP_DECL_CONSPROP(consPropSOS2)
1820 { /*lint --e{715}*/
1821  int c;
1822  int ngen = 0;
1823 
1824  assert( scip != NULL );
1825  assert( conshdlr != NULL );
1826  assert( conss != NULL );
1827  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1828  assert( result != NULL );
1829  *result = SCIP_DIDNOTRUN;
1830 
1831  assert( SCIPisTransformed(scip) );
1832 
1833  /* check each constraint */
1834  for (c = 0; c < nconss; ++c)
1835  {
1836  SCIP_CONS* cons;
1837  SCIP_CONSDATA* consdata;
1838  SCIP_Bool cutoff;
1839 
1840  assert( conss[c] != NULL );
1841  cons = conss[c];
1842  consdata = SCIPconsGetData(cons);
1843  assert( consdata != NULL );
1844  SCIPdebugMessage("Propagating SOS2 constraint <%s>.\n", SCIPconsGetName(cons) );
1845 
1846  *result = SCIP_DIDNOTFIND;
1847  SCIP_CALL( propSOS2(scip, cons, consdata, &cutoff, &ngen) );
1848  if ( cutoff )
1849  {
1850  *result = SCIP_CUTOFF;
1851  return SCIP_OKAY;
1852  }
1853  }
1854  SCIPdebugMessage("Propagated %d domains.\n", ngen);
1855  if ( ngen > 0 )
1856  *result = SCIP_REDUCEDDOM;
1857 
1858  return SCIP_OKAY;
1859 }
1860 
1861 
1862 /** propagation conflict resolving method of constraint handler
1863  *
1864  * We check which bound changes were the reason for infeasibility. We
1865  * use that @a inferinfo stores the index of the variable that has
1866  * bounds that fix it to be nonzero (these bounds are the reason). */
1867 static
1868 SCIP_DECL_CONSRESPROP(consRespropSOS2)
1869 { /*lint --e{715}*/
1870  SCIP_CONSDATA* consdata;
1871  SCIP_VAR* var;
1872 
1873  assert( scip != NULL );
1874  assert( cons != NULL );
1875  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1876  assert( infervar != NULL );
1877  assert( bdchgidx != NULL );
1878  assert( result != NULL );
1879 
1880  *result = SCIP_DIDNOTFIND;
1881  SCIPdebugMessage("Propagation resolution method of SOS2 constraint <%s>.\n", SCIPconsGetName(cons));
1882 
1883  consdata = SCIPconsGetData(cons);
1884  assert( consdata != NULL );
1885  assert( 0 <= inferinfo && inferinfo < consdata->nvars );
1886  var = consdata->vars[inferinfo];
1887  assert( var != infervar );
1888 
1889  /* check if lower bound of var was the reason */
1890  if ( SCIPisFeasPositive(scip, SCIPvarGetLbAtIndex(var, bdchgidx, FALSE)) )
1891  {
1892  SCIP_CALL( SCIPaddConflictLb(scip, var, bdchgidx) );
1893  *result = SCIP_SUCCESS;
1894  }
1895 
1896  /* check if upper bound of var was the reason */
1897  if ( SCIPisFeasNegative(scip, SCIPvarGetUbAtIndex(var, bdchgidx, FALSE)) )
1898  {
1899  SCIP_CALL( SCIPaddConflictUb(scip, var, bdchgidx) );
1900  *result = SCIP_SUCCESS;
1901  }
1902 
1903  return SCIP_OKAY;
1904 }
1905 
1906 
1907 /** variable rounding lock method of constraint handler
1908  *
1909  * Let lb and ub be the lower and upper bounds of a
1910  * variable. Preprocessing usually makes sure that lb <= 0 <= ub.
1911  *
1912  * - If lb < 0 then rounding down may violate the constraint.
1913  * - If ub > 0 then rounding up may violated the constraint.
1914  * - If lb > 0 or ub < 0 then the constraint is infeasible and we do
1915  * not have to deal with it here.
1916  * - If lb == 0 then rounding down does not violate the constraint.
1917  * - If ub == 0 then rounding up does not violate the constraint.
1918  */
1919 static
1920 SCIP_DECL_CONSLOCK(consLockSOS2)
1922  SCIP_CONSDATA* consdata;
1923  SCIP_VAR** vars;
1924  int nvars;
1925  int j;
1926 
1927  assert( scip != NULL );
1928  assert( conshdlr != NULL );
1929  assert( cons != NULL );
1930  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1931  consdata = SCIPconsGetData(cons);
1932  assert( consdata != NULL );
1933 
1934  SCIPdebugMessage("Locking constraint <%s>.\n", SCIPconsGetName(cons));
1935 
1936  vars = consdata->vars;
1937  nvars = consdata->nvars;
1938  assert( vars != NULL );
1939 
1940  for (j = 0; j < nvars; ++j)
1941  {
1942  SCIP_VAR* var;
1943  var = vars[j];
1944 
1945  /* if lower bound is negative, rounding down may violate constraint */
1946  if ( SCIPisFeasNegative(scip, SCIPvarGetLbLocal(var)) )
1947  SCIP_CALL( SCIPaddVarLocks(scip, var, nlockspos, nlocksneg) );
1948 
1949  /* additionally: if upper bound is positive, rounding up may violate constraint */
1950  if ( SCIPisFeasPositive(scip, SCIPvarGetUbLocal(var)) )
1951  SCIP_CALL( SCIPaddVarLocks(scip, var, nlocksneg, nlockspos) );
1952  }
1953 
1954  return SCIP_OKAY;
1955 }
1956 
1957 
1958 /** constraint display method of constraint handler */
1959 static
1960 SCIP_DECL_CONSPRINT(consPrintSOS2)
1961 { /*lint --e{715}*/
1962  SCIP_CONSDATA* consdata;
1963  int j;
1964 
1965  assert( scip != NULL );
1966  assert( conshdlr != NULL );
1967  assert( cons != NULL );
1968  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1969 
1970  consdata = SCIPconsGetData(cons);
1971  assert( consdata != NULL );
1972 
1973  for (j = 0; j < consdata->nvars; ++j)
1974  {
1975  if ( j > 0 )
1976  SCIPinfoMessage(scip, file, ", ");
1977  SCIP_CALL( SCIPwriteVarName(scip, file, consdata->vars[j], FALSE) );
1978  if ( consdata->weights == NULL )
1979  SCIPinfoMessage(scip, file, " (%d)", j+1);
1980  else
1981  SCIPinfoMessage(scip, file, " (%3.2f)", consdata->weights[j]);
1982  }
1983 
1984  return SCIP_OKAY;
1985 }
1986 
1987 
1988 /** constraint copying method of constraint handler */
1989 static
1990 SCIP_DECL_CONSCOPY(consCopySOS2)
1991 { /*lint --e{715}*/
1992  SCIP_CONSDATA* sourceconsdata;
1993  SCIP_VAR** sourcevars;
1994  SCIP_VAR** targetvars;
1995  SCIP_Real* sourceweights;
1996  SCIP_Real* targetweights;
1997  const char* consname;
1998  int nvars;
1999  int v;
2000 
2001  assert( scip != NULL );
2002  assert( sourcescip != NULL );
2003  assert( sourcecons != NULL );
2004  assert( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(sourcecons)), CONSHDLR_NAME) == 0 );
2005 
2006  *valid = TRUE;
2007 
2008  if ( name != NULL )
2009  consname = name;
2010  else
2011  consname = SCIPconsGetName(sourcecons);
2012 
2013  SCIPdebugMessage("Copying SOS2 constraint <%s> ...\n", consname);
2014 
2015  sourceconsdata = SCIPconsGetData(sourcecons);
2016  assert( sourceconsdata != NULL );
2017 
2018  /* get variables and weights of the source constraint */
2019  nvars = sourceconsdata->nvars;
2020 
2021  if ( nvars == 0 )
2022  return SCIP_OKAY;
2023 
2024  sourcevars = sourceconsdata->vars;
2025  assert( sourcevars != NULL );
2026  sourceweights = sourceconsdata->weights;
2027  assert( sourceweights != NULL );
2028 
2029  /* duplicate variable array */
2030  SCIP_CALL( SCIPallocBufferArray(sourcescip, &targetvars, nvars) );
2031  SCIP_CALL( SCIPduplicateBufferArray(sourcescip, &targetweights, sourceweights, nvars) );
2032 
2033  /* get copied variables in target SCIP */
2034  for( v = 0; v < nvars && *valid; ++v )
2035  {
2036  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[v], &(targetvars[v]), varmap, consmap, global, valid) );
2037  }
2038 
2039  /* only create the target constraint, if all variables could be copied */
2040  if( *valid )
2041  {
2042  SCIP_CALL( SCIPcreateConsSOS2(scip, cons, consname, nvars, targetvars, targetweights,
2043  initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
2044  }
2045 
2046  /* free buffer array */
2047  SCIPfreeBufferArray(sourcescip, &targetweights);
2048  SCIPfreeBufferArray(sourcescip, &targetvars);
2049 
2050  return SCIP_OKAY;
2051 }
2052 
2053 
2054 /** constraint parsing method of constraint handler */
2055 static
2056 SCIP_DECL_CONSPARSE(consParseSOS2)
2057 { /*lint --e{715}*/
2058  SCIP_VAR* var;
2059  SCIP_Real weight;
2060  const char* s;
2061  char* t;
2062 
2063  *success = TRUE;
2064  s = str;
2065 
2066  /* create empty SOS2 constraint */
2067  SCIP_CALL( SCIPcreateConsSOS2(scip, cons, name, 0, NULL, NULL, initial, separate, enforce, check, propagate, local, dynamic, removable, stickingatnode) );
2068 
2069  /* loop through string */
2070  do
2071  {
2072  /* parse variable name */
2073  SCIP_CALL( SCIPparseVarName(scip, s, &var, &t) );
2074  s = t;
2075 
2076  /* skip until beginning of weight */
2077  while ( *s != '\0' && *s != '(' )
2078  ++s;
2079 
2080  if ( *s == '\0' )
2081  {
2082  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error: expected weight at input: %s\n", s);
2083  *success = FALSE;
2084  return SCIP_OKAY;
2085  }
2086  /* skip '(' */
2087  ++s;
2088 
2089  /* find weight */
2090  weight = strtod(s, &t);
2091  if ( t == NULL )
2092  {
2093  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error during parsing of the weight: %s\n", s);
2094  *success = FALSE;
2095  return SCIP_OKAY;
2096  }
2097  s = t;
2098 
2099  /* skip white space, ',', and ')' */
2100  while ( *s != '\0' && ( isspace((unsigned char)*s) || *s == ',' || *s == ')' ) )
2101  ++s;
2102 
2103  /* add variable */
2104  SCIP_CALL( SCIPaddVarSOS2(scip, *cons, var, weight) );
2105  }
2106  while ( *s != '\0' );
2107 
2108  return SCIP_OKAY;
2109 }
2110 
2111 
2112 /** constraint method of constraint handler which returns the variables (if possible) */
2113 static
2114 SCIP_DECL_CONSGETVARS(consGetVarsSOS2)
2115 { /*lint --e{715}*/
2116  SCIP_CONSDATA* consdata;
2117 
2118  consdata = SCIPconsGetData(cons);
2119  assert(consdata != NULL);
2120 
2121  if( varssize < consdata->nvars )
2122  (*success) = FALSE;
2123  else
2124  {
2125  assert(vars != NULL);
2126 
2127  BMScopyMemoryArray(vars, consdata->vars, consdata->nvars);
2128  (*success) = TRUE;
2129  }
2130 
2131  return SCIP_OKAY;
2132 }
2133 
2134 
2135 /** constraint method of constraint handler which returns the number of variables (if possible) */
2136 static
2137 SCIP_DECL_CONSGETNVARS(consGetNVarsSOS2)
2138 { /*lint --e{715}*/
2139  SCIP_CONSDATA* consdata;
2140 
2141  consdata = SCIPconsGetData(cons);
2142  assert(consdata != NULL);
2143 
2144  (*nvars) = consdata->nvars;
2145  (*success) = TRUE;
2146 
2147  return SCIP_OKAY;
2148 }
2149 
2150 
2151 /* ---------------- Callback methods of event handler ---------------- */
2152 
2153 /* exec the event handler
2154  *
2155  * We update the number of variables fixed to be nonzero
2156  */
2157 static
2158 SCIP_DECL_EVENTEXEC(eventExecSOS2)
2160  SCIP_EVENTTYPE eventtype;
2161  SCIP_CONSDATA* consdata;
2162  SCIP_Real oldbound, newbound;
2163 
2164  assert( eventhdlr != NULL );
2165  assert( eventdata != NULL );
2166  assert( strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0 );
2167  assert( event != NULL );
2168 
2169  consdata = (SCIP_CONSDATA*)eventdata;
2170  assert( consdata != NULL );
2171  assert( 0 <= consdata->nfixednonzeros && consdata->nfixednonzeros <= consdata->nvars );
2172 
2173  oldbound = SCIPeventGetOldbound(event);
2174  newbound = SCIPeventGetNewbound(event);
2175 
2176  eventtype = SCIPeventGetType(event);
2177  switch ( eventtype )
2178  {
2180  /* if variable is now fixed to be nonzero */
2181  if ( ! SCIPisFeasPositive(scip, oldbound) && SCIPisFeasPositive(scip, newbound) )
2182  ++(consdata->nfixednonzeros);
2183  break;
2185  /* if variable is now fixed to be nonzero */
2186  if ( ! SCIPisFeasNegative(scip, oldbound) && SCIPisFeasNegative(scip, newbound) )
2187  ++(consdata->nfixednonzeros);
2188  break;
2190  /* if variable is not fixed to be nonzero anymore */
2191  if ( SCIPisFeasPositive(scip, oldbound) && ! SCIPisFeasPositive(scip, newbound) )
2192  --(consdata->nfixednonzeros);
2193  break;
2195  /* if variable is not fixed to be nonzero anymore */
2196  if ( SCIPisFeasNegative(scip, oldbound) && ! SCIPisFeasNegative(scip, newbound) )
2197  --(consdata->nfixednonzeros);
2198  break;
2199  default:
2200  SCIPerrorMessage("invalid event type.\n");
2201  return SCIP_INVALIDDATA;
2202  }
2203  assert( 0 <= consdata->nfixednonzeros && consdata->nfixednonzeros <= consdata->nvars );
2204 
2205  SCIPdebugMessage("changed bound of variable <%s> from %f to %f (nfixednonzeros: %d).\n", SCIPvarGetName(SCIPeventGetVar(event)),
2206  oldbound, newbound, consdata->nfixednonzeros);
2207 
2208  return SCIP_OKAY;
2209 }
2210 
2211 
2212 /* ---------------- Constraint specific interface methods ---------------- */
2213 
2214 /** creates the handler for SOS2 constraints and includes it in SCIP */
2216  SCIP* scip /**< SCIP data structure */
2217  )
2218 {
2219  SCIP_CONSHDLRDATA* conshdlrdata;
2220  SCIP_CONSHDLR* conshdlr;
2221 
2222  /* create constraint handler data */
2223  SCIP_CALL( SCIPallocMemory(scip, &conshdlrdata) );
2224 
2225  conshdlrdata->eventhdlr = NULL;
2226  /* create event handler for bound change events */
2227  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &(conshdlrdata->eventhdlr), EVENTHDLR_NAME, EVENTHDLR_DESC,
2228  eventExecSOS2, NULL) );
2229  if ( conshdlrdata->eventhdlr == NULL )
2230  {
2231  SCIPerrorMessage("event handler for SOS2 constraints not found.\n");
2232  return SCIP_PLUGINNOTFOUND;
2233  }
2234 
2235  /* include constraint handler */
2238  consEnfolpSOS2, consEnfopsSOS2, consCheckSOS2, consLockSOS2, conshdlrdata) );
2239  assert(conshdlr != NULL);
2240 
2241  /* set non-fundamental callbacks via specific setter functions */
2242  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopySOS2, consCopySOS2) );
2243  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSOS2) );
2244  SCIP_CALL( SCIPsetConshdlrExitsol(scip, conshdlr, consExitsolSOS2) );
2245  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSOS2) );
2246  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSOS2) );
2247  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSOS2) );
2248  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSOS2) );
2249  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseSOS2) );
2250  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolSOS2, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
2251  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSOS2) );
2253  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSOS2) );
2254  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSOS2, consSepasolSOS2, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
2255  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSOS2) );
2256 
2257  return SCIP_OKAY;
2258 }
2259 
2260 
2261 /** creates and captures a SOS2 constraint
2262  *
2263  * We set the constraint to not be modifable. If the weights are non
2264  * NULL, the variables are ordered according to these weights (in
2265  * ascending order).
2266  *
2267  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2268  */
2270  SCIP* scip, /**< SCIP data structure */
2271  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2272  const char* name, /**< name of constraint */
2273  int nvars, /**< number of variables in the constraint */
2274  SCIP_VAR** vars, /**< array with variables of constraint entries */
2275  SCIP_Real* weights, /**< weights determining the variable order, or NULL if natural order should be used */
2276  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2277  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2278  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2279  * Usually set to TRUE. */
2280  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2281  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2282  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2283  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2284  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2285  * Usually set to TRUE. */
2286  SCIP_Bool local, /**< is constraint only valid locally?
2287  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2288  SCIP_Bool dynamic, /**< is constraint subject to aging?
2289  * Usually set to FALSE. Set to TRUE for own cuts which
2290  * are separated as constraints. */
2291  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2292  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2293  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2294  * if it may be moved to a more global node?
2295  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2296  )
2297 {
2298  SCIP_CONSHDLR* conshdlr;
2299  SCIP_CONSDATA* consdata;
2300  SCIP_Bool modifiable;
2301 
2302  modifiable = FALSE;
2303 
2304  /* find the SOS2 constraint handler */
2305  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2306  if ( conshdlr == NULL )
2307  {
2308  SCIPerrorMessage("<%s> constraint handler not found\n", CONSHDLR_NAME);
2309  return SCIP_PLUGINNOTFOUND;
2310  }
2311 
2312  /* create constraint data */
2313  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
2314  consdata->vars = NULL;
2315  consdata->nvars = nvars;
2316  consdata->maxvars = nvars;
2317  consdata->row = NULL;
2318  consdata->nfixednonzeros = -1;
2319  consdata->weights = NULL;
2320  if ( nvars > 0 )
2321  {
2322  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->vars, vars, nvars) );
2323 
2324  /* check weights */
2325  if ( weights != NULL )
2326  {
2327  /* store weights */
2328  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->weights, weights, nvars) );
2329 
2330  /* sort variables - ascending order */
2331  SCIPsortRealPtr(consdata->weights, (void**)consdata->vars, nvars);
2332  }
2333  }
2334  else
2335  assert( weights == NULL );
2336 
2337  /* create constraint */
2338  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2339  local, modifiable, dynamic, removable, stickingatnode) );
2340 
2341  return SCIP_OKAY;
2342 }
2343 
2344 
2345 /** creates and captures a SOS2 constraint with all constraint flags set to their default values.
2346  *
2347  * @warning Do NOT set the constraint to be modifiable manually, because this might lead
2348  * to wrong results as the variable array will not be resorted
2349  *
2350  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2351  */
2353  SCIP* scip, /**< SCIP data structure */
2354  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2355  const char* name, /**< name of constraint */
2356  int nvars, /**< number of variables in the constraint */
2357  SCIP_VAR** vars, /**< array with variables of constraint entries */
2358  SCIP_Real* weights /**< weights determining the variable order, or NULL if natural order should be used */
2359  )
2360 {
2361  SCIP_CALL( SCIPcreateConsSOS2( scip, cons, name, nvars, vars, weights, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
2362 
2363  return SCIP_OKAY;
2364 }
2365 
2366 
2367 /** adds variable to SOS2 constraint, the position is determined by the given weight */
2369  SCIP* scip, /**< SCIP data structure */
2370  SCIP_CONS* cons, /**< constraint */
2371  SCIP_VAR* var, /**< variable to add to the constraint */
2372  SCIP_Real weight /**< weight determining position of variable */
2373  )
2374 {
2375  assert( scip != NULL );
2376  assert( var != NULL );
2377  assert( cons != NULL );
2378 
2379  SCIPdebugMessage("adding variable <%s> to constraint <%s> with weight %g\n", SCIPvarGetName(var), SCIPconsGetName(cons), weight);
2380 
2381  if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2382  {
2383  SCIPerrorMessage("constraint is not an SOS2 constraint.\n");
2384  return SCIP_INVALIDDATA;
2385  }
2386 
2387  SCIP_CALL( addVarSOS2(scip, cons, var, weight) );
2388 
2389  return SCIP_OKAY;
2390 }
2391 
2392 
2393 /** appends variable to SOS2 constraint */
2395  SCIP* scip, /**< SCIP data structure */
2396  SCIP_CONS* cons, /**< constraint */
2397  SCIP_VAR* var /**< variable to add to the constraint */
2398  )
2399 {
2400  assert( scip != NULL );
2401  assert( var != NULL );
2402  assert( cons != NULL );
2403 
2404  SCIPdebugMessage("appending variable <%s> to constraint <%s>\n", SCIPvarGetName(var), SCIPconsGetName(cons));
2405 
2406  if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2407  {
2408  SCIPerrorMessage("constraint is not an SOS2 constraint.\n");
2409  return SCIP_INVALIDDATA;
2410  }
2411 
2412  SCIP_CALL( appendVarSOS2(scip, cons, var) );
2413 
2414  return SCIP_OKAY;
2415 }
2416 
2417 
2418 /** gets number of variables in SOS2 constraint */
2419 int SCIPgetNVarsSOS2(
2420  SCIP* scip, /**< SCIP data structure */
2421  SCIP_CONS* cons /**< constraint */
2422  )
2423 {
2424  SCIP_CONSDATA* consdata;
2425 
2426  assert( scip != NULL );
2427  assert( cons != NULL );
2428 
2429  if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2430  {
2431  SCIPerrorMessage("constraint is not an SOS2 constraint.\n");
2432  SCIPABORT();
2433  return -1; /*lint !e527*/
2434  }
2435 
2436  consdata = SCIPconsGetData(cons);
2437  assert( consdata != NULL );
2438 
2439  return consdata->nvars;
2440 }
2441 
2442 
2443 /** gets array of variables in SOS2 constraint */
2445  SCIP* scip, /**< SCIP data structure */
2446  SCIP_CONS* cons /**< constraint data */
2447  )
2448 {
2449  SCIP_CONSDATA* consdata;
2450 
2451  assert( scip != NULL );
2452  assert( cons != NULL );
2453 
2454  if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2455  {
2456  SCIPerrorMessage("constraint is not an SOS2 constraint.\n");
2457  SCIPABORT();
2458  return NULL; /*lint !e527*/
2459  }
2460 
2461  consdata = SCIPconsGetData(cons);
2462  assert( consdata != NULL );
2463 
2464  return consdata->vars;
2465 }
2466 
2467 
2468 /** gets array of weights in SOS2 constraint (or NULL if not existent) */
2470  SCIP* scip, /**< SCIP data structure */
2471  SCIP_CONS* cons /**< constraint data */
2472  )
2473 {
2474  SCIP_CONSDATA* consdata;
2475 
2476  assert( scip != NULL );
2477  assert( cons != NULL );
2478 
2479  if ( strcmp(SCIPconshdlrGetName(SCIPconsGetHdlr(cons)), CONSHDLR_NAME) != 0 )
2480  {
2481  SCIPerrorMessage("constraint is not an SOS2 constraint.\n");
2482  SCIPABORT();
2483  return NULL; /*lint !e527*/
2484  }
2485 
2486  consdata = SCIPconsGetData(cons);
2487  assert( consdata != NULL );
2488 
2489  return consdata->weights;
2490 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:22777
SCIP_RETCODE SCIPaddVarsToRowSameCoef(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real val)
Definition: scip.c:27932
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip.c:15853
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:5588
SCIP_RETCODE SCIPresetConsAge(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:25588
static SCIP_DECL_CONSSEPALP(consSepalpSOS2)
Definition: cons_sos2.c:1605
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
#define CONSHDLR_EAGERFREQ
Definition: cons_sos2.c:83
static SCIP_RETCODE deleteVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, int pos)
Definition: cons_sos2.c:448
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20573
static SCIP_DECL_CONSPRESOL(consPresolSOS2)
Definition: cons_sos2.c:1489
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11540
static SCIP_RETCODE fixVariableZeroNode(SCIP *scip, SCIP_VAR *var, SCIP_NODE *node, SCIP_Bool *infeasible)
Definition: cons_sos2.c:119
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41920
#define SCIP_MAXSTRLEN
Definition: def.h:201
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:5634
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5246
static SCIP_RETCODE presolRoundSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_EVENTHDLR *eventhdlr, SCIP_Bool *cutoff, SCIP_Bool *success, int *ndelconss, int *nfixedvars, int *nremovedvars)
Definition: cons_sos2.c:508
#define CONSHDLR_DELAYPROP
Definition: cons_sos2.c:88
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:42032
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:940
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:7849
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5334
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip.c:30859
static SCIP_RETCODE unlockVariableSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_sos2.c:232
SCIP_RETCODE SCIPgetProbvarSum(SCIP *scip, SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: scip.c:17429
SCIP_Real * SCIPgetWeightsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2470
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5818
SCIP_Bool SCIPconsIsTransformed(SCIP_CONS *cons)
Definition: cons.c:7909
#define FALSE
Definition: def.h:56
static SCIP_DECL_CONSRESPROP(consRespropSOS2)
Definition: cons_sos2.c:1869
SCIP_RETCODE SCIPincludeConshdlrSOS2(SCIP *scip)
Definition: cons_sos2.c:2216
static SCIP_DECL_CONSINITLP(consInitlpSOS2)
Definition: cons_sos2.c:1560
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7778
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:7640
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_RETCODE inferVariableZero(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened, SCIP_Bool *success)
Definition: cons_sos2.c:170
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:5795
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20556
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15737
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
SCIP_RETCODE SCIPchgRowRhs(SCIP *scip, SCIP_ROW *row, SCIP_Real rhs)
Definition: scip.c:27783
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7839
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7779
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip.c:26237
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:30967
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:99
#define CONSHDLR_MAXPREROUNDS
Definition: cons_sos2.c:86
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:20554
static SCIP_DECL_CONSLOCK(consLockSOS2)
Definition: cons_sos2.c:1921
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:5359
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:7769
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20572
static SCIP_DECL_CONSENFOPS(consEnfopsSOS2)
Definition: cons_sos2.c:1733
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip.c:16156
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:56
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3917
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36622
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1096
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16585
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1781
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41984
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:17075
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:7879
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
static SCIP_DECL_CONSDELETE(consDeleteSOS2)
Definition: cons_sos2.c:1357
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:19526
SCIP_Real SCIPcalcNodeselPriority(SCIP *scip, SCIP_VAR *var, SCIP_BRANCHDIR branchdir, SCIP_Real targetvalue)
Definition: scip.c:33651
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:41996
static SCIP_DECL_CONSEXITSOL(consExitsolSOS2)
Definition: cons_sos2.c:1325
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3897
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15859
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:5527
static SCIP_DECL_CONSGETVARS(consGetVarsSOS2)
Definition: cons_sos2.c:2115
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7620
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19126
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
Definition: scip.h:20562
#define CONSHDLR_DELAYSEPA
Definition: cons_sos2.c:87
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:58
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
static SCIP_RETCODE generateRowSOS2(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_Bool local)
Definition: cons_sos2.c:1190
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5292
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:55
#define CONSHDLR_ENFOPRIORITY
Definition: cons_sos2.c:79
#define CONSHDLR_SEPAPRIORITY
Definition: cons_sos2.c:78
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5192
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41946
static SCIP_DECL_CONSPARSE(consParseSOS2)
Definition: cons_sos2.c:2057
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7650
SCIP_RETCODE SCIPaddConsNode(SCIP *scip, SCIP_NODE *node, SCIP_CONS *cons, SCIP_NODE *validnode)
Definition: scip.c:11929
static SCIP_DECL_CONSFREE(consFreeSOS2)
Definition: cons_sos2.c:1306
SCIP_RETCODE SCIPdelConsLocal(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12080
static SCIP_DECL_CONSENFOLP(consEnfolpSOS2)
Definition: cons_sos2.c:1717
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:997
public data structures and miscellaneous methods
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:24772
#define SCIP_Bool
Definition: def.h:53
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7859
SCIP_RETCODE SCIPaddVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos2.c:2369
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:24369
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopySOS2)
Definition: cons_sos2.c:1289
int SCIPgetNVarsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2420
static SCIP_RETCODE consdataEnsurevarsSizeSOS2(SCIP *scip, SCIP_CONSDATA *consdata, int num, SCIP_Bool reserveWeights)
Definition: cons_sos2.c:251
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:7869
SCIP_VAR ** SCIPgetVarsSOS2(SCIP *scip, SCIP_CONS *cons)
Definition: cons_sos2.c:2445
static SCIP_DECL_CONSPROP(consPropSOS2)
Definition: cons_sos2.c:1820
static SCIP_RETCODE appendVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_sos2.c:404
static SCIP_DECL_EVENTEXEC(eventExecSOS2)
Definition: cons_sos2.c:2159
#define CONSHDLR_PROP_TIMING
Definition: cons_sos2.c:91
SCIP_RETCODE SCIPcreateConsSOS2(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: cons_sos2.c:2270
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:5611
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:57
Constraint handler for linear constraints in their most general form, .
static SCIP_DECL_CONSTRANS(consTransSOS2)
Definition: cons_sos2.c:1406
#define CONSHDLR_PRESOLTIMING
Definition: cons_sos2.c:92
static SCIP_DECL_CONSPRINT(consPrintSOS2)
Definition: cons_sos2.c:1961
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1298
SCIP_RETCODE SCIPchgVarLbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19898
#define CONSHDLR_DESC
Definition: cons_sos2.c:77
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20469
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36668
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:5565
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
#define CONSHDLR_NAME
Definition: cons_sos2.c:76
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:5772
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1281
#define REALABS(x)
Definition: def.h:151
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_DECL_CONSSEPASOL(consSepasolSOS2)
Definition: cons_sos2.c:1661
#define EVENTHDLR_DESC
Definition: cons_sos2.c:96
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:20593
SCIP_RETCODE SCIPsetConshdlrExitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXITSOL((*consexitsol)))
Definition: scip.c:5455
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_RETCODE SCIPappendVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_sos2.c:2395
static SCIP_RETCODE branchCons(SCIP *scip, SCIP_CONS *cons, SCIP_RESULT *result)
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition: scip.c:19453
SCIP_RETCODE SCIPchgVarUbNode(SCIP *scip, SCIP_NODE *node, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19931
static SCIP_RETCODE enforceSOS2(SCIP *scip, SCIP_CONSHDLR *conshdlr, int nconss, SCIP_CONS **conss, SCIP_RESULT *result)
Definition: cons_sos2.c:987
#define SCIP_Real
Definition: def.h:127
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7799
static SCIP_RETCODE handleNewVariableSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_VAR *var, SCIP_Bool transformed)
Definition: cons_sos2.c:279
#define EVENTHDLR_NAME
Definition: cons_sos2.c:95
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:27600
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip.c:28334
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:20568
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27738
void SCIPsortRealPtr(SCIP_Real *realarray, void **ptrarray, int len)
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:20571
#define CONSHDLR_PROPFREQ
Definition: cons_sos2.c:82
#define CONSHDLR_NEEDSCONS
Definition: cons_sos2.c:89
static SCIP_DECL_CONSGETNVARS(consGetNVarsSOS2)
Definition: cons_sos2.c:2138
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:19399
static SCIP_RETCODE lockVariableSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var)
Definition: cons_sos2.c:213
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
constraint handler for SOS type 2 constraints
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
#define CONSHDLR_CHECKPRIORITY
Definition: cons_sos2.c:80
SCIP_RETCODE SCIPcreateChild(SCIP *scip, SCIP_NODE **node, SCIP_Real nodeselprio, SCIP_Real estimate)
Definition: scip.c:33701
#define SCIPdebug(x)
Definition: pub_message.h:74
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:24436
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:41422
#define CONSHDLR_SEPAFREQ
Definition: cons_sos2.c:81
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1120
SCIP_Real SCIPcalcChildEstimate(SCIP *scip, SCIP_VAR *var, SCIP_Real targetvalue)
Definition: scip.c:33678
static SCIP_RETCODE addVarSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real weight)
Definition: cons_sos2.c:336
static SCIP_RETCODE propSOS2(SCIP *scip, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *cutoff, int *ngen)
Definition: cons_sos2.c:789
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5841
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:27864
#define SCIPABORT()
Definition: def.h:238
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7789
static SCIP_DECL_CONSCOPY(consCopySOS2)
Definition: cons_sos2.c:1991
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7819
SCIP_RETCODE SCIPchgRowLhs(SCIP *scip, SCIP_ROW *row, SCIP_Real lhs)
Definition: scip.c:27759
static SCIP_DECL_CONSCHECK(consCheckSOS2)
Definition: cons_sos2.c:1754
SCIP_RETCODE SCIPcreateConsBasicSOS2(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *weights)
Definition: cons_sos2.c:2353