Scippy

SCIP

Solving Constraint Integer Programs

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