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