Scippy

SCIP

Solving Constraint Integer Programs

cons_orbisack.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-2021 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 visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_orbisack.c
17  * @ingroup DEFPLUGINS_CONS
18  * @brief constraint handler for orbisack constraints
19  * @author Christopher Hojny
20  *
21  *
22  * The type of constraints of this constraint handler is described in cons_orbisack.h.
23  *
24  * The details of the method implemented here are described in the following papers:
25  *
26  * Describing Orbitopes by Linear Inequalities and Projection Based Tools@n
27  * Andreas Loos,@n
28  * PhD thesis, Otto-von-Guericke-Universitaet Magdeburg (2010).
29  *
30  * This thesis provides a complete linear description of orbisacks and a separation
31  * routine for its inequalities.
32  *
33  * Polytopes Associated with Symmetry Handling@n
34  * Christopher Hojny and Marc E. Pfetsch,@n
35  * (2017), preprint available at http://www.optimization-online.org/DB_HTML/2017/01/5835.html
36  *
37  * This paper describes a linear time separation routine for so-called cover inequalities of
38  * orbisacks.
39  */
40 
41 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
42 
43 #include "blockmemshell/memory.h"
44 #include "scip/cons_orbisack.h"
45 #include "scip/cons_orbitope.h"
46 #include "scip/cons_setppc.h"
47 #include "scip/pub_cons.h"
48 #include "scip/pub_message.h"
49 #include "scip/pub_var.h"
50 #include "scip/scip.h"
51 #include "scip/scip_branch.h"
52 #include "scip/scip_conflict.h"
53 #include "scip/scip_cons.h"
54 #include "scip/scip_cut.h"
55 #include "scip/scip_general.h"
56 #include "scip/scip_lp.h"
57 #include "scip/scip_mem.h"
58 #include "scip/scip_message.h"
59 #include "scip/scip_numerics.h"
60 #include "scip/scip_param.h"
61 #include "scip/scip_sol.h"
62 #include "scip/scip_var.h"
63 #include <string.h>
64 
65 /* constraint handler properties */
66 #define CONSHDLR_NAME "orbisack"
67 #define CONSHDLR_DESC "symmetry breaking constraint handler for orbisacks"
68 #define CONSHDLR_SEPAPRIORITY +40100 /**< priority of the constraint handler for separation */
69 #define CONSHDLR_ENFOPRIORITY -1005200 /**< priority of the constraint handler for constraint enforcing */
70 #define CONSHDLR_CHECKPRIORITY -1005200 /**< priority of the constraint handler for checking feasibility */
71 #define CONSHDLR_SEPAFREQ 5 /**< frequency for separating cuts; zero means to separate only in the root node */
72 #define CONSHDLR_PROPFREQ 5 /**< frequency for propagating domains; zero means only preprocessing propagation */
73 #define CONSHDLR_EAGERFREQ -1 /**< 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_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
79 
80 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
81 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_EXHAUSTIVE
82 
83 /* default parameters for separation routines: */
84 #define DEFAULT_ORBISEPARATION FALSE /**< whether orbisack inequalities should be separated */
85 #define DEFAULT_COVERSEPARATION TRUE /**< whether cover inequalities should be separated */
86 
87 /* default parameters for constraints */
88 #define DEFAULT_COEFFBOUND 1000000.0 /**< maximum size of coefficients in orbisack inequalities */
89 #define DEFAULT_PPORBISACK TRUE /**< whether we allow upgrading to packing/partitioning orbisacks */
90 #define DEFAULT_FORCECONSCOPY FALSE /**< whether orbisack constraints should be forced to be copied to sub SCIPs */
91 
92 
93 /*
94  * Data structures
95  */
96 
97 /** constraint handler data */
98 struct SCIP_ConshdlrData
99 {
100  SCIP_Bool coverseparation; /**< whether only cover inequalities should be separated */
101  SCIP_Bool orbiseparation; /**< whether orbisack as well as cover inequalities should be separated */
102  SCIP_Real coeffbound; /**< maximum size of coefficients in orbisack inequalities */
103  SCIP_Bool checkpporbisack; /**< whether we allow upgrading to packing/partitioning orbisacks */
104  int maxnrows; /**< maximal number of rows in an orbisack constraint */
105  SCIP_Bool forceconscopy; /**< whether orbisack constraints should be forced to be copied to sub SCIPs */
106 };
107 
108 /** constraint data for orbisack constraints */
109 struct SCIP_ConsData
110 {
111  SCIP_VAR** vars1; /**< first column of variable matrix */
112  SCIP_VAR** vars2; /**< second column of variable matrix */
113  int nrows; /**< number of rows of variable matrix */
114  SCIP_Bool ismodelcons; /**< whether the orbisack is a model constraint */
115 };
116 
117 
118 /*
119  * Local methods
120  */
121 
122 /** frees orbisack constraint data */
123 static
125  SCIP* scip, /**< SCIP data structure */
126  SCIP_CONSDATA** consdata /**< pointer to orbisack constraint data */
127  )
128 {
129  int nrows;
130 
131  assert( consdata != NULL );
132  assert( *consdata != NULL );
133 
134  nrows = (*consdata)->nrows;
135  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars2), nrows);
136  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars1), nrows);
137 
138  SCIPfreeBlockMemory(scip, consdata);
139 
140  return SCIP_OKAY;
141 }
142 
143 
144 /** creates orbisack constraint data */
145 static
147  SCIP* scip, /**< SCIP data structure */
148  SCIP_CONSDATA** consdata, /**< pointer to store constraint data */
149  SCIP_VAR*const* vars1, /**< first column of variable matrix */
150  SCIP_VAR*const* vars2, /**< second column of variable matrix */
151  int nrows, /**< number of rows in variable matrix */
152  SCIP_Bool ismodelcons /**< whether the orbisack is a model constraint */
153  )
154 {
155  int i;
156 
157  assert( consdata != NULL );
158 
159  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
160 
161  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars1, vars1, nrows) );
162  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars2, vars2, nrows) );
163 
164 #ifndef NDEBUG
165  {
166  for (i = 0; i < nrows; ++i)
167  {
168  assert( SCIPvarIsBinary(vars1[i]) );
169  assert( SCIPvarIsBinary(vars2[i]) );
170  }
171  }
172 #endif
173 
174  (*consdata)->nrows = nrows;
175  (*consdata)->ismodelcons = ismodelcons;
176 
177  /* get transformed variables, if we are in the transformed problem */
178  if ( SCIPisTransformed(scip) )
179  {
180  /* Make sure that all variables cannot be multiaggregated (cannot be handled by cons_orbisack, since one cannot
181  * easily eliminate single variables from an orbisack constraint. */
182  for (i = 0; i < nrows; ++i)
183  {
184  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vars1[i], &(*consdata)->vars1[i]) );
185  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars1[i]) );
186 
187  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vars2[i], &(*consdata)->vars2[i]) );
188  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars2[i]) );
189  }
190  }
191 
192  return SCIP_OKAY;
193 }
194 
195 
196 /** check wether an orbisack is even a packing/partitioning orbisack */
197 static
199  SCIP* scip, /**< SCIP pointer */
200  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
201  SCIP_VAR*const* vars2, /**< variables of second column */
202  int nrows, /**< number of rows of orbisack */
203  SCIP_Bool* success, /**< memory address to store whether constraint can be upgraded */
204  SCIP_Bool* isparttype /**< memory address to store whether upgraded orbisack is partitioning orbisack */
205  )
206 {
207  SCIP_CONSHDLR* setppcconshdlr;
208  SCIP_CONS** setppcconss;
209  SCIP_Bool* rowcovered;
210  int nsetppcconss;
211  int i;
212  int c;
213 
214  assert( scip != NULL );
215  assert( vars1 != NULL );
216  assert( vars2 != NULL );
217  assert( success != NULL );
218  assert( isparttype != NULL );
219 
220  *success = FALSE;
221 
222  /* get data of setppc conshdlr */
223  setppcconshdlr = SCIPfindConshdlr(scip, "setppc");
224  if ( setppcconshdlr == NULL )
225  {
226  SCIPwarningMessage(scip, "Check for upgrading orbisacks to packing/partitioning orbisacks not possible - setppc constraint handler not found.\n");
227  return SCIP_OKAY;
228  }
229  setppcconss = SCIPconshdlrGetConss(setppcconshdlr);
230  nsetppcconss = SCIPconshdlrGetNConss(setppcconshdlr);
231 
232  /* upgrade cannot be successful */
233  if ( nsetppcconss == 0 )
234  return SCIP_OKAY;
235  assert( setppcconss != NULL );
236 
237  SCIP_CALL( SCIPallocClearBufferArray(scip, &rowcovered, nrows) );
238 
239  /* iterate over orbisack rows and check whether rows are contained in partitioning constraints */
240  *success = TRUE;
241  for (i = 0; i < nrows; ++i)
242  {
243  /* iterate over constraints */
244  for (c = 0; c < nsetppcconss; ++c)
245  {
246  int nsetppcvars;
247  SCIP_VAR** setppcvars;
248  SCIP_VAR* var;
249  int varidx1;
250  int varidx2;
251 
252  /* check type */
253  if ( SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_COVERING ||
254  SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_PACKING )
255  continue;
256  assert( SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_PARTITIONING );
257 
258  /* get set packing/partitioning variables */
259  nsetppcvars = SCIPgetNVarsSetppc(scip, setppcconss[c]);
260  assert( nsetppcvars > 0 );
261 
262  /* partitioning constraint contains too much variables */
263  if ( nsetppcvars != 2 )
264  continue;
265  assert( nsetppcvars == 2 );
266 
267  setppcvars = SCIPgetVarsSetppc(scip, setppcconss[c]);
268  assert( setppcvars != NULL );
269 
270  /* check whether i-th row is contained in partitioning constraint */
271  var = setppcvars[0];
272  if ( SCIPvarIsNegated(var) )
273  continue;
274 
275  varidx1 = SCIPvarGetProbindex(var);
276 
277  var = setppcvars[1];
278  if ( SCIPvarIsNegated(var) )
279  continue;
280 
281  varidx2 = SCIPvarGetProbindex(var);
282 
283  if ( (varidx1 == SCIPvarGetProbindex(vars1[i]) && varidx2 == SCIPvarGetProbindex(vars2[i])) ||
284  (varidx2 == SCIPvarGetProbindex(vars1[i]) && varidx1 == SCIPvarGetProbindex(vars2[i])))
285  {
286  rowcovered[i] = TRUE;
287  break;
288  }
289  }
290 
291  /* no partitioning constraint corresponds to row i */
292  if ( c >= nsetppcconss )
293  *success = FALSE;
294  }
295 
296  if ( *success )
297  {
298  *isparttype = TRUE;
299  SCIPfreeBufferArray(scip, &rowcovered);
300 
301  return SCIP_OKAY;
302  }
303 
304  /* Iterate over orbisack rows and check whether rows are contained in packing constraints.
305  * In particular, it is possible that variables in row i form a subset of variables in the
306  * a packing/partitioning constraint. */
307  *success = TRUE;
308  for (i = 0; i < nrows; ++i)
309  {
310  /* skip already covered rows */
311  if ( rowcovered[i] )
312  continue;
313 
314  /* iterate over constraints */
315  for (c = 0; c < nsetppcconss; ++c)
316  {
317  SCIP_VAR** setppcvars;
318  SCIP_VAR* var;
319  int nsetppcvars;
320  int varidx;
321  int nfound = 0;
322  int j;
323 
324  /* check type */
325  if ( SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_COVERING )
326  continue;
327  assert( SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_PARTITIONING ||
328  SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_PACKING );
329 
330  /* get set packing/partitioning variables */
331  nsetppcvars = SCIPgetNVarsSetppc(scip, setppcconss[c]);
332 
333  /* skip empty constraints (might not have been removed by presolving yet) */
334  if ( nsetppcvars == 0 )
335  continue;
336  assert( nsetppcvars > 0 );
337 
338  setppcvars = SCIPgetVarsSetppc(scip, setppcconss[c]);
339  assert( setppcvars != NULL );
340 
341  /* check whether all variables of the cycle are contained in setppc constraint */
342  for (j = 0; j < nsetppcvars && nfound < 2; ++j)
343  {
344  var = setppcvars[j];
345 
346  if ( SCIPvarIsNegated(var) )
347  continue;
348 
349  varidx = SCIPvarGetProbindex(var);
350 
351  if ( varidx == SCIPvarGetProbindex(vars1[i]) || varidx == SCIPvarGetProbindex(vars2[i]) )
352  ++nfound;
353  }
354 
355  if ( nfound == 2 )
356  break;
357  }
358 
359  /* row i is not contained in an setppc constraint */
360  if ( c >= nsetppcconss )
361  *success = FALSE;
362  }
363 
364  /* we have found a packing orbisack */
365  if ( *success )
366  *isparttype = FALSE;
367 
368  SCIPfreeBufferArray(scip, &rowcovered);
369 
370  return SCIP_OKAY;
371 }
372 
373 
374 /** generate initial LP cut
375  *
376  * We generate the inequality of the orbisack on the elements of the first row, i.e.,
377  * the inequality \f$-x_{1,1} + x_{1,2} \leq 0\f$.
378  */
379 static
381  SCIP* scip, /**< SCIP pointer */
382  SCIP_CONS* cons, /**< constraint */
383  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
384  )
385 {
386  SCIP_CONSDATA* consdata;
387  SCIP_VAR** vars1;
388  SCIP_VAR** vars2;
389  SCIP_VAR* tmpvars[2];
390  SCIP_ROW* row;
391 
392  assert( scip != NULL );
393  assert( cons != NULL );
394  assert( infeasible != NULL );
395 
396  *infeasible = FALSE;
397 
398  consdata = SCIPconsGetData(cons);
399  assert( consdata != 0 );
400  assert( consdata->nrows > 0 );
401  assert( consdata->vars1 != NULL );
402  assert( consdata->vars2 != NULL );
403 
404  vars1 = consdata->vars1;
405  vars2 = consdata->vars2;
406 
407  tmpvars[0] = vars1[0];
408  tmpvars[1] = vars2[0];
409 
410  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisack0#0", -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
411  SCIP_CALL( SCIPaddVarToRow(scip, row, tmpvars[0], -1.0) );
412  SCIP_CALL( SCIPaddVarToRow(scip, row, tmpvars[1], 1.0) );
413 
414  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
415 #ifdef SCIP_DEBUG
416  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
417 #endif
418  SCIP_CALL( SCIPreleaseRow(scip, &row) );
419 
420  return SCIP_OKAY;
421 }
422 
423 
424 /** add orbisack cover inequality */
425 static
427  SCIP* scip, /**< SCIP pointer */
428  SCIP_CONS* cons, /**< constraint */
429  int nrows, /**< number of rows of orbisack */
430  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
431  SCIP_VAR*const* vars2, /**< variables of second column */
432  SCIP_Real* coeffs1, /**< coefficients of the variables of the first column of the inequality to be added */
433  SCIP_Real* coeffs2, /**< coefficients of the variables of the second column of the inequality to be added */
434  SCIP_Real rhs, /**< right-hand side of inequality to be added */
435  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
436  )
437 {
438  SCIP_ROW* row;
439  int i;
440 
441  assert( scip != NULL );
442  assert( cons != NULL );
443  assert( vars1 != NULL );
444  assert( vars2 != NULL );
445  assert( coeffs1 != NULL );
446  assert( coeffs2 != NULL );
447  assert( infeasible != NULL );
448 
449  *infeasible = FALSE;
450 
451  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisackcover", -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
452  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
453  for (i = 0; i < nrows; ++i)
454  {
455  SCIP_CALL( SCIPaddVarToRow(scip, row, vars1[i], coeffs1[i]) );
456  SCIP_CALL( SCIPaddVarToRow(scip, row, vars2[i], coeffs2[i]) );
457  }
458  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
459 
460  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
461 #ifdef SCIP_DEBUG
462  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
463 #endif
464  SCIP_CALL( SCIPreleaseRow(scip, &row) );
465 
466  return SCIP_OKAY;
467 }
468 
469 
470 /** Separate lifted orbisack cover inequalities
471  *
472  * We currently do NOT enter cuts into the pool.
473  *
474  * We iterate over the nrows-many cover inequalities which are potentially
475  * maximal w.r.t. their violation.
476  */
477 static
479  SCIP* scip, /**< SCIP pointer */
480  SCIP_CONS* cons, /**< constraint */
481  int nrows, /**< number of rows of orbisack */
482  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
483  SCIP_VAR*const* vars2, /**< variables of second column */
484  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
485  SCIP_Real* vals2, /**< LP-solution for those variables in second column */
486  int* ngen, /**< number of separated covers */
487  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
488  )
489 {
490  SCIP_Real rhs = 0.0;
491  SCIP_Real lhs = 0.0;
492  SCIP_Real* coeff1;
493  SCIP_Real* coeff2;
494  int i;
495 
496  assert( scip != NULL );
497  assert( cons != NULL );
498  assert( nrows > 0 );
499  assert( vars1 != NULL );
500  assert( vars2 != NULL );
501  assert( infeasible != NULL );
502  assert( ngen != NULL );
503 
504  *infeasible = FALSE;
505  *ngen = 0;
506 
507  /* allocate memory for inequality coefficients */
508  SCIP_CALL( SCIPallocBufferArray(scip, &coeff1, nrows) );
509  SCIP_CALL( SCIPallocBufferArray(scip, &coeff2, nrows) );
510 
511  /* initialize coefficient matrix */
512  for (i = 0; i < nrows; ++i)
513  {
514  coeff1[i] = 0.0;
515  coeff2[i] = 0.0;
516  }
517 
518  /* detect violated covers */
519  for (i = 0; i < nrows; ++i)
520  {
521  /* cover inequality is violated */
522  if ( SCIPisEfficacious(scip, -vals1[i] + vals2[i] + lhs - rhs) )
523  {
524  /* set coefficients for inequality */
525  coeff1[i] = -1.0;
526  coeff2[i] = 1.0;
527 
528  SCIP_CALL( addOrbisackCover(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
529  ++(*ngen);
530  if ( *infeasible )
531  break;
532 
533  /* reset coefficients for next inequality */
534  coeff1[i] = 0.0;
535  coeff2[i] = 0.0;
536  }
537 
538  /* add argmax( 1 - vals[i][0], vals[i][1] ) as coefficient and ensure that both vars1[0] and vars2[0] are
539  * contained in the LIFTED cover inequality */
540  if ( SCIPisEfficacious(scip, 1.0 - vals1[i] - vals2[i]) )
541  {
542  coeff1[i] = -1.0;
543  lhs = lhs - vals1[i];
544 
545  /* lifting */
546  if ( i == 0 )
547  {
548  coeff2[0] = 1.0;
549  lhs += vals2[i];
550  }
551  }
552  else
553  {
554  coeff2[i] = 1.0;
555  rhs += 1.0;
556  lhs = lhs + vals2[i];
557 
558  /* lifting */
559  if ( i == 0 )
560  {
561  coeff1[0] = -1.0;
562  lhs -= vals1[i];
563  rhs -= 1.0;
564  }
565  }
566  }
567 
568  /* free coefficient matrix */
569  SCIPfreeBufferArray(scip, &coeff2);
570  SCIPfreeBufferArray(scip, &coeff1);
571 
572  return SCIP_OKAY;
573 }
574 
575 
576 /** add orbisack inequality */
577 static
579  SCIP* scip, /**< SCIP pointer */
580  SCIP_CONS* cons, /**< constraint */
581  int nrows, /**< number of rows of orbisack */
582  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
583  SCIP_VAR*const* vars2, /**< variables of second column */
584  SCIP_Real* coeffs1, /**< first column of coefficient matrix of inequality to be added */
585  SCIP_Real* coeffs2, /**< second column of coefficient matrix of inequality to be added */
586  SCIP_Real rhs, /**< right-hand side of inequality to be added */
587  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
588  )
589 {
590  SCIP_ROW* row;
591  int i;
592 
593  assert( scip != NULL );
594  assert( cons != NULL );
595  assert( vars1 != NULL );
596  assert( vars2 != NULL );
597  assert( coeffs1 != NULL );
598  assert( coeffs2 != NULL );
599  assert( infeasible != NULL );
600 
601  *infeasible = FALSE;
602 
603  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisack", -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
604  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
605 
606  for (i = 0; i < nrows; ++i)
607  {
608  SCIP_CALL( SCIPaddVarToRow(scip, row, vars1[i], coeffs1[i]) );
609  SCIP_CALL( SCIPaddVarToRow(scip, row, vars2[i], coeffs2[i]) );
610  }
611  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
612 
613  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
614 #ifdef SCIP_DEBUG
615  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
616 #endif
617  SCIP_CALL( SCIPreleaseRow(scip, &row) );
618 
619  return SCIP_OKAY;
620 }
621 
622 
623 /** separate orbisack inequalities
624  *
625  * We currently do NOT enter cuts into the pool.
626  *
627  * We stop if we checked for each possible basement row, whether a cut could be added. If the coefficients grow too
628  * large, we start separating cover inequalities.
629  *
630  * We implement the separation algorithm for orbisacks described in@n
631  * A. Loos. Describing Orbitopes by Linear Inequalities and Projection Based Tools.
632  * PhD thesis, Otto-von-Guericke-Universitaet Magdeburg, 2010.
633  */
634 static
636  SCIP* scip, /**< SCIP pointer */
637  SCIP_CONS* cons, /**< constraint */
638  int nrows, /**< number of rows of orbisack */
639  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
640  SCIP_VAR*const* vars2, /**< variables of second column */
641  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
642  SCIP_Real* vals2, /**< LP-solution for those variables in second column */
643  SCIP_Bool coverseparation, /**< whether we separate cover inequalities */
644  SCIP_Real coeffbound, /**< maximum size of coefficients in orbisack inequalities */
645  int* ngen, /**< pointer to store the number of generated cuts */
646  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
647  )
648 {
649  SCIP_Real* coeff1;
650  SCIP_Real* coeff2;
651  SCIP_Real rhs;
652  SCIP_Real lhs;
653  SCIP_Real valueA;
654  SCIP_Real valueB;
655  SCIP_Real valueC;
656  int basement;
657  int i;
658 
659  assert( scip != NULL );
660  assert( cons != NULL );
661  assert( nrows > 0 );
662  assert( vars1 != NULL );
663  assert( vars2 != NULL );
664  assert( coeffbound >= 0.0 );
665  assert( ngen != NULL );
666  assert( infeasible != NULL );
667 
668  *infeasible = FALSE;
669  *ngen = 0;
670 
671  /* if there is only one row, all cuts are added by initLP */
672  if ( nrows < 2 )
673  return SCIP_OKAY;
674 
675  /* allocate memory for inequality coefficients */
676  SCIP_CALL( SCIPallocBufferArray(scip, &coeff1, nrows) );
677  SCIP_CALL( SCIPallocBufferArray(scip, &coeff2, nrows) );
678 
679  /* initialize coefficient matrix row 0 */
680  coeff1[0] = -1.0;
681  coeff2[0] = 1.0;
682  for (i = 2; i < nrows; ++i)
683  {
684  coeff1[i] = 0.0;
685  coeff2[i] = 0.0;
686  }
687 
688  /* initialize right-hand side and left-hand side (lhs for row 0) */
689  rhs = 0.0;
690  lhs = - vals1[0] + vals2[0];
691 
692  /* basement row of orbisack */
693  basement = 1;
694 
695  /* update value of left-hand side and coefficients for basement row = 1 */
696  lhs += - vals1[1] + vals2[1];
697  coeff1[1] = -1.0;
698  coeff2[1] = 1.0;
699 
700  /* check whether cut for basement row = 1 is violated */
701  if ( SCIPisEfficacious(scip, lhs - rhs) )
702  {
703  SCIP_CALL( addOrbisackInequality(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
704  ++(*ngen);
705  }
706 
707  /* check whether there exists a cut with basement rows > 1 that is violated */
708  while ( basement < nrows - 1 && ! *infeasible )
709  {
710  valueA = lhs + vals1[basement] - vals1[basement + 1] + vals2[basement + 1] - rhs - 1.0; /*lint !e679, !e834*/
711  valueB = lhs - vals2[basement] - vals1[basement + 1] + vals2[basement + 1] - rhs; /*lint !e679, !e834*/
712  valueC = 2.0 * lhs + vals1[basement] - vals2[basement] - vals1[basement + 1] + vals2[basement + 1] - 2.0 * rhs; /*lint !e679, !e834*/
713 
714  /* update inequality */
715  if ( valueA >= valueB && valueA >= valueC )
716  {
717  ++rhs;
718  coeff1[basement] = 0.0;
719  lhs += vals1[basement++];
720  coeff1[basement] = -1.0;
721  coeff2[basement] = 1.0;
722  lhs += - vals1[basement] + vals2[basement];
723  }
724  else if ( valueB >= valueA && valueB >= valueC )
725  {
726  coeff2[basement] = 0.0;
727  lhs -= vals2[basement++];
728  coeff1[basement] = -1.0;
729  coeff2[basement] = 1.0;
730  lhs += - vals1[basement] + vals2[basement];
731  }
732  else
733  {
734  rhs *= 2.0;
735  lhs = 0.0;
736  for (i = 0; i < basement; ++i)
737  {
738  coeff1[i] = 2.0 * coeff1[i];
739  coeff2[i] = 2.0 * coeff2[i];
740  lhs += coeff1[i] * vals1[i] + coeff2[i] * vals2[i];
741  }
742  coeff1[basement] = -1.0;
743  coeff2[basement] = 1.0;
744  lhs -= vals1[basement];
745  lhs += vals2[basement++];
746  coeff1[basement] = -1.0;
747  coeff2[basement] = 1.0;
748  lhs -= vals1[basement];
749  lhs += vals2[basement];
750  }
751 
752  /* to avoid numerical troubles, we bound the size of coefficients and rhs */
753  if ( rhs > coeffbound || -coeff1[0] > coeffbound || coeff2[0] > coeffbound )
754  {
755  /* avoid separating cover inequalities twice */
756  if ( ! coverseparation )
757  {
758  int ncuts;
759  SCIP_CALL( separateOrbisackCovers(scip, cons, nrows, vars1, vars2, vals1, vals2, &ncuts, infeasible) );
760  *ngen += ncuts;
761  }
762  break;
763  }
764 
765  /* if current inequality is violated */
766  if ( SCIPisEfficacious(scip, lhs - rhs) )
767  {
768  SCIP_CALL( addOrbisackInequality(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
769  ++(*ngen);
770  }
771  }
772 
773  /* free allocated memory */
774  SCIPfreeBufferArray(scip, &coeff2);
775  SCIPfreeBufferArray(scip, &coeff1);
776 
777  return SCIP_OKAY;
778 }
779 
780 
781 /** propagation */
782 static
784  SCIP* scip, /**< SCIP pointer */
785  SCIP_CONS* cons, /**< constraint to be propagated */
786  SCIP_Bool* infeasible, /**< pointer to store whether it was detected that the node is infeasible */
787  SCIP_Bool* found, /**< pointer to store whether a new propagation could be found */
788  int* ngen /**< pointer to store the number of generated bound strengthenings */
789  )
790 {
791  SCIP_CONSDATA* consdata;
792  SCIP_VAR** vars1;
793  SCIP_VAR** vars2;
794  SCIP_Bool tightened = FALSE;
795  SCIP_VAR* var;
796  SCIP_Real ub;
797  SCIP_Real lb;
798  SCIP_VAR* var1;
799  SCIP_VAR* var2;
800  int* solu1;
801  int* solu2;
802  int nrows;
803  int i;
804  int r;
805 
806  assert( scip != NULL );
807  assert( cons != NULL );
808  assert( infeasible != NULL );
809  assert( ngen != NULL );
810  assert( found != NULL );
811 
812  SCIPdebugMsg(scip, "Propagating variables of constraint <%s>.\n", SCIPconsGetName(cons));
813 
814  *ngen = 0;
815  *infeasible = FALSE;
816  *found = FALSE;
817 
818  /* get data of constraint */
819  consdata = SCIPconsGetData(cons);
820  assert( consdata != NULL );
821  assert( consdata->vars1 != NULL );
822  assert( consdata->vars2 != NULL );
823  assert( consdata->nrows > 0 );
824 
825  nrows = consdata->nrows;
826  vars1 = consdata->vars1;
827  vars2 = consdata->vars2;
828 
829  /* determine current solution */
830  SCIP_CALL( SCIPallocBufferArray(scip, &solu1, nrows) );
831  SCIP_CALL( SCIPallocBufferArray(scip, &solu2, nrows) );
832 
833  for (i = 0; i < nrows; ++i)
834  {
835  /* determine value in first column */
836  var = vars1[i];
837  assert( SCIPvarIsBinary(var) );
838 
839  /* get local upper and lower bound on variable */
840  ub = SCIPvarGetUbLocal(var);
841  lb = SCIPvarGetLbLocal(var);
842 
843  /* if variable is fixed to 1 -> solu[i][j] = 1,
844  * if it is fixed to 0 -> solu[i][j] = 0,
845  * else, -> solu[i][j] = 2 */
846  if ( lb > 0.5 )
847  solu1[i] = 1;
848  else if (ub < 0.5)
849  solu1[i] = 0;
850  else
851  solu1[i] = 2;
852 
853  /* determine value in second column */
854  var = vars2[i];
855  assert( SCIPvarIsBinary(var) );
856 
857  /* get local upper and lower bound on variable */
858  ub = SCIPvarGetUbLocal(var);
859  lb = SCIPvarGetLbLocal(var);
860 
861  /* if variable is fixed to 1 -> solu[i][j] = 1,
862  * if it is fixed to 0 -> solu[i][j] = 0,
863  * else, -> solu[i][j] = 2 */
864  if ( lb > 0.5 )
865  solu2[i] = 1;
866  else if (ub < 0.5)
867  solu2[i] = 0;
868  else
869  solu2[i] = 2;
870  }
871 
872  /* loop through all variables */
873  for (i = 0; i < nrows; ++i)
874  {
875  /* get variables of first and second column */
876  var1 = vars1[i];
877  var2 = vars2[i];
878  assert( var1 != NULL );
879  assert( var2 != NULL );
880 
881  /* if variable in first column is fixed to 0 and variable in second column is fixed to 1 */
882  if ( SCIPvarGetUbLocal(var1) < 0.5 && SCIPvarGetLbLocal(var2) > 0.5 )
883  {
884  SCIP_Bool nocritical = TRUE;
885 
886  SCIPdebugMsg(scip, "Check variable pair (%d,0) and (%d,1).\n", i, i);
887 
888  /* check whether there is a critical row above row i, otherwise the solution is infeasible
889  * if there is a row without fixing (2) above the current row, we cannot obtain a result */
890  for (r = 0; r < i; ++r)
891  {
892  if ( (solu1[r] == 1 && solu2[r] == 0) || solu1[r] == 2 || solu2[r] == 2 )
893  {
894  nocritical = FALSE;
895  break;
896  }
897  }
898 
899  if ( nocritical )
900  {
901  SCIPdebugMsg(scip, " -> node infeasible (row was fixed to 0,1 but there was no critical row above).\n");
902 
903  /* perform conflict analysis */
905  {
907 
908  for (r = 0; r <= i; ++r)
909  {
910  SCIP_CALL( SCIPaddConflictBinvar(scip, vars1[r]) );
911  SCIP_CALL( SCIPaddConflictBinvar(scip, vars2[r]) );
912  }
913 
914  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
915 
916  *infeasible = TRUE;
917 
918  /* free current solution */
919  SCIPfreeBufferArray(scip, &solu2);
920  SCIPfreeBufferArray(scip, &solu1);
921 
922  return SCIP_OKAY;
923  }
924  }
925  }
926  /* if variable in the first column is fixed to 0 and the variable in the second column is free */
927  else if ( SCIPvarGetUbLocal(var1) < 0.5 && SCIPvarGetUbLocal(var2) > 0.5 )
928  {
929  SCIP_Bool allconstant = TRUE;
930 
931  SCIPdebugMsg(scip, "Check variable pair (%d,0) and (%d,1).\n", i, i);
932 
933  /* Check whether all rows above row i are constant. In this case, the variable in the second */
934  /* column can be fixed to 0. If an entry above row i is unfixed or a row is not constant, we cannot */
935  /* fix the second entry in row i. */
936  for (r = 0; r < i; ++r)
937  {
938  if ( solu1[r] == 2 || solu2[r] == 2 || solu1[r] != solu2[r] )
939  {
940  allconstant = FALSE;
941  break;
942  }
943  }
944 
945  /* fix variable in the second column to 0 */
946  if ( allconstant )
947  {
948  assert( SCIPvarGetLbLocal(var2) < 0.5 );
949  SCIP_CALL( SCIPinferVarUbCons(scip, var2, 0.0, cons, i, FALSE, infeasible, &tightened) ); /*lint !e713*/
950  assert( ! *infeasible );
951 
952  *found = *found || tightened;
953  if ( tightened )
954  ++(*ngen);
955  }
956  }
957  }
958 
959  /* free current solution */
960  SCIPfreeBufferArray(scip, &solu2);
961  SCIPfreeBufferArray(scip, &solu1);
962 
963  return SCIP_OKAY;
964 }
965 
966 
967 /** separate orbisack and cover inequalities */
968 static
970  SCIP* scip, /**< pointer to scip */
971  SCIP_RESULT* result, /**< pointer to store the result of separation */
972  SCIP_CONS* cons, /**< constraint */
973  int nrows, /**< number of rows of orbisack */
974  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
975  SCIP_VAR*const* vars2, /**< variables of second column */
976  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
977  SCIP_Real* vals2 /**< LP-solution for those variables in second column */
978  )
979 {
980  SCIP_CONSHDLRDATA* conshdlrdata;
981  SCIP_Bool infeasible = FALSE;
982  int ngen1 = 0;
983  int ngen2 = 0;
984 
985  assert( scip != NULL );
986  assert( result != NULL );
987  assert( cons != NULL );
988  assert( vars1 != NULL );
989  assert( vars2 != NULL );
990  assert( vals1 != NULL );
991  assert( vals2 != NULL );
992 
993  conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
994  assert( conshdlrdata != NULL );
995 
996  if ( conshdlrdata->orbiseparation )
997  {
998  SCIP_CALL( separateOrbisack(scip, cons, nrows, vars1, vars2, vals1, vals2, FALSE, conshdlrdata->coeffbound, &ngen1, &infeasible) );
999  }
1000 
1001  if ( ! infeasible && conshdlrdata->coverseparation )
1002  {
1003  SCIP_CALL( separateOrbisackCovers(scip, cons, nrows, vars1, vars2, vals1, vals2, &ngen2, &infeasible) );
1004  }
1005 
1006  if ( infeasible )
1007  {
1008  *result = SCIP_CUTOFF;
1009  return SCIP_OKAY;
1010  }
1011 
1012  if ( ngen1 + ngen2 > 0 )
1013  *result = SCIP_SEPARATED;
1014 
1015  return SCIP_OKAY;
1016 }
1017 
1018 
1019 /*--------------------------------------------------------------------------------------------
1020  *--------------------------------- SCIP functions -------------------------------------------
1021  *--------------------------------------------------------------------------------------------*/
1022 
1023 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1024 static
1025 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbisack)
1026 { /*lint --e{715}*/
1027  assert(scip != NULL);
1028  assert(conshdlr != NULL);
1029  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1030 
1031  /* call inclusion method of constraint handler */
1033 
1034  *valid = TRUE;
1035 
1036  return SCIP_OKAY;
1037 }
1038 
1039 /** frees specific constraint data */
1040 static
1041 SCIP_DECL_CONSDELETE(consDeleteOrbisack)
1042 { /*lint --e{715}*/
1043  assert( scip != 0 );
1044  assert( conshdlr != 0 );
1045  assert( consdata != 0 );
1046  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1047 
1048  SCIP_CALL( consdataFree(scip, consdata) );
1049 
1050  return SCIP_OKAY;
1051 }
1052 
1053 
1054 /** frees constraint handler */
1055 static
1056 SCIP_DECL_CONSFREE(consFreeOrbisack)
1057 { /*lint --e{715}*/
1058  SCIP_CONSHDLRDATA* conshdlrdata;
1059 
1060  assert( scip != 0 );
1061  assert( conshdlr != 0 );
1062  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1063 
1064  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1065  assert( conshdlrdata != NULL );
1066 
1067  SCIPfreeBlockMemory(scip, &conshdlrdata);
1068 
1069  return SCIP_OKAY;
1070 }
1071 
1072 
1073 /** transforms constraint data into data belonging to the transformed problem */
1074 static
1075 SCIP_DECL_CONSTRANS(consTransOrbisack)
1077  SCIP_CONSDATA* sourcedata;
1078  SCIP_CONSDATA* consdata = NULL;
1079  int nrows;
1080 
1081  assert( scip != NULL );
1082  assert( conshdlr != NULL );
1083  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1084  assert( sourcecons != NULL );
1085  assert( targetcons != NULL );
1086 
1087  SCIPdebugMsg(scip, "Transforming constraint.\n");
1088 
1089  /* get data of original constraint */
1090  sourcedata = SCIPconsGetData(sourcecons);
1091  assert( sourcedata != NULL );
1092  assert( sourcedata->nrows > 0 );
1093  assert( sourcedata->vars1 != NULL );
1094  assert( sourcedata->vars2 != NULL );
1095 
1096  /* create transformed constraint data (copy data where necessary) */
1097  nrows = sourcedata->nrows;
1098 
1099  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
1100 
1101  consdata->nrows = nrows;
1102  consdata->ismodelcons = sourcedata->ismodelcons;
1103 
1104  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars1, nrows) );
1105  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars2, nrows) );
1106 
1107  SCIP_CALL( SCIPgetTransformedVars(scip, nrows, sourcedata->vars1, consdata->vars1) );
1108  SCIP_CALL( SCIPgetTransformedVars(scip, nrows, sourcedata->vars2, consdata->vars2) );
1109 
1110  /* create transformed constraint */
1111  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, consdata,
1112  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
1113  SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
1114  SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
1115  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
1116  SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1117 
1118  return SCIP_OKAY;
1119 }
1120 
1121 
1122 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1123 static
1124 SCIP_DECL_CONSINITLP(consInitlpOrbisack)
1126  int c;
1127 
1128  assert( infeasible != NULL );
1129  *infeasible = FALSE;
1130 
1131  assert( scip != 0 );
1132  assert( conshdlr != 0 );
1133  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1134 
1135  /* loop through constraints */
1136  for (c = 0; c < nconss; ++c)
1137  {
1138  assert( conss[c] != 0 );
1139 
1140  SCIPdebugMsg(scip, "Generating initial orbisack cut for constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1141 
1142  SCIP_CALL( initLP(scip, conss[c], infeasible) );
1143  if ( *infeasible )
1144  break;
1145 
1146  SCIPdebugMsg(scip, "Generated initial orbisack cut.\n");
1147  }
1148 
1149  return SCIP_OKAY;
1150 }
1151 
1152 
1153 /** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
1154 static
1155 SCIP_DECL_CONSINITSOL(consInitsolOrbisack)
1157  SCIP_CONSHDLRDATA* conshdlrdata;
1158  int c;
1159 
1160  assert( scip != NULL );
1161  assert( conshdlr != NULL );
1162  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1163 
1164  /* determine maximum number of rows in an orbisack constraint */
1165  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1166  assert( conshdlrdata != NULL );
1167 
1168  conshdlrdata->maxnrows = 0;
1169 
1170  /* loop through constraints */
1171  for (c = 0; c < nconss; ++c)
1172  {
1173  SCIP_CONSDATA* consdata;
1174 
1175  assert( conss[c] != NULL );
1176 
1177  consdata = SCIPconsGetData(conss[c]);
1178  assert( consdata != NULL );
1179 
1180  /* update conshdlrdata if necessary */
1181  if ( consdata->nrows > conshdlrdata->maxnrows )
1182  conshdlrdata->maxnrows = consdata->nrows;
1183  }
1184 
1185  return SCIP_OKAY;
1186 }
1187 
1188 
1189 /** separation method of constraint handler for LP solution */
1190 static
1191 SCIP_DECL_CONSSEPALP(consSepalpOrbisack)
1192 { /*lint --e{715}*/
1193  SCIP_CONSDATA* consdata;
1194  SCIP_Real* vals1;
1195  SCIP_Real* vals2;
1196  int c;
1197 
1198  assert( scip != NULL );
1199  assert( conshdlr != NULL );
1200  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1201  assert( result != NULL );
1202 
1203  SCIPdebugMsg(scip, "Separation method for orbisack constraints.\n");
1204 
1205  *result = SCIP_DIDNOTRUN;
1206 
1207  /* if solution is not integer */
1208  if ( SCIPgetNLPBranchCands(scip) > 0 )
1209  {
1210  SCIP_CONSHDLRDATA* conshdlrdata;
1211  int nvals;
1212 
1213  *result = SCIP_DIDNOTFIND;
1214 
1215  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1216  assert( conshdlrdata != NULL );
1217 
1218  nvals = conshdlrdata->maxnrows;
1219  assert( nvals > 0 );
1220 
1221  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1222  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1223 
1224  /* loop through constraints */
1225  for (c = 0; c < nconss; ++c)
1226  {
1227  /* get data of constraint */
1228  assert( conss[c] != NULL );
1229  consdata = SCIPconsGetData(conss[c]);
1230 
1231  /* get solution */
1232  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars1, vals1) );
1233  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars2, vals2) );
1234 
1235  SCIPdebugMsg(scip, "Separating orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1236 
1237  SCIP_CALL( separateInequalities(scip, result, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2) );
1238 
1239  if ( *result == SCIP_CUTOFF )
1240  break;
1241  }
1242 
1243  SCIPfreeBufferArray(scip, &vals2);
1244  SCIPfreeBufferArray(scip, &vals1);
1245  }
1246 
1247  return SCIP_OKAY;
1248 }
1249 
1250 
1251 /** separation method of constraint handler for arbitrary primal solution */
1252 static
1253 SCIP_DECL_CONSSEPASOL(consSepasolOrbisack)
1254 { /*lint --e{715}*/
1255  SCIP_CONSDATA* consdata;
1256  SCIP_Real* vals1;
1257  SCIP_Real* vals2;
1258  int c;
1259 
1260  assert( scip != NULL );
1261  assert( conshdlr != NULL );
1262  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1263  assert( result != NULL );
1264 
1265  SCIPdebugMsg(scip, "Separation method for orbisack constraints\n");
1266 
1267  *result = SCIP_DIDNOTFIND;
1268 
1269  if ( nconss > 0 )
1270  {
1271  SCIP_CONSHDLRDATA* conshdlrdata;
1272  int nvals;
1273 
1274  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1275  assert( conshdlrdata != NULL );
1276 
1277  nvals = conshdlrdata->maxnrows;
1278  assert( nvals > 0 );
1279 
1280  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1281  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1282 
1283  /* loop through constraints */
1284  for (c = 0; c < nconss; ++c)
1285  {
1286  /* get data of constraint */
1287  assert( conss[c] != NULL );
1288  consdata = SCIPconsGetData(conss[c]);
1289 
1290  /* get solution */
1291  assert( consdata->nrows <= nvals );
1292  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars1, vals1) );
1293  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars2, vals2) );
1294 
1295  SCIPdebugMsg(scip, "Separating orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1296 
1297  SCIP_CALL( separateInequalities(scip, result, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2) );
1298  if ( *result == SCIP_CUTOFF )
1299  break;
1300  }
1301 
1302  SCIPfreeBufferArray(scip, &vals2);
1303  SCIPfreeBufferArray(scip, &vals1);
1304  }
1305 
1306  return SCIP_OKAY;
1307 }
1308 
1309 
1310 /** constraint enforcing method of constraint handler for LP solutions
1311  *
1312  * @pre It is assumed that the solution is integral (this can be ensured by appropriate priorities).
1313  */
1314 static
1315 SCIP_DECL_CONSENFOLP(consEnfolpOrbisack)
1316 { /*lint --e{715}*/
1317  SCIP_CONSDATA* consdata;
1318  SCIP_Bool infeasible = FALSE;
1319  SCIP_Real* vals1;
1320  SCIP_Real* vals2;
1321  int ngen = 0;
1322  int c;
1323 
1324  assert( scip != 0 );
1325  assert( conshdlr != 0 );
1326  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1327  assert( result != 0 );
1328 
1329  SCIPdebugMsg(scip, "Enfolp method for orbisack constraints\n");
1330 
1331  /* we have a negative priority, so we should come after the integrality conshdlr. */
1332  assert( SCIPgetNLPBranchCands(scip) == 0 );
1333 
1334  *result = SCIP_FEASIBLE;
1335 
1336  if ( nconss > 0 )
1337  {
1338  SCIP_CONSHDLRDATA* conshdlrdata;
1339  int nvals;
1340 
1341  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1342  assert( conshdlrdata != NULL );
1343 
1344  nvals = conshdlrdata->maxnrows;
1345  assert( nvals > 0 );
1346 
1347  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1348  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1349 
1350  /* loop through constraints */
1351  for (c = 0; c < nconss; ++c)
1352  {
1353  /* get data of constraint */
1354  assert( conss[c] != 0 );
1355  consdata = SCIPconsGetData(conss[c]);
1356  assert( consdata != NULL );
1357 
1358  /* do not enforce non-model constraints */
1359  if ( !consdata->ismodelcons )
1360  continue;
1361 
1362  /* get solution */
1363  assert( consdata->nrows <= nvals );
1364  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars1, vals1) );
1365  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars2, vals2) );
1366 
1367  SCIPdebugMsg(scip, "Enforcing orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1368 
1369  /* Separate only cover inequalities to ensure that enforcing works correctly. */
1370  /* Otherwise, it may happen that infeasible solutions cannot be detected, since */
1371  /* we bound the size of the coefficients for the orbisack inequalities. */
1372  SCIP_CALL( separateOrbisackCovers(scip, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2, &ngen, &infeasible) );
1373 
1374  if ( infeasible )
1375  {
1376  *result = SCIP_CUTOFF;
1377  break;
1378  }
1379 
1380  SCIPdebugMsg(scip, "Generated orbisack inequalities for <%s>: %d\n", SCIPconsGetName(conss[c]), ngen);
1381 
1382  if ( ngen > 0 )
1383  *result = SCIP_SEPARATED;
1384  }
1385 
1386  SCIPfreeBufferArray(scip, &vals2);
1387  SCIPfreeBufferArray(scip, &vals1);
1388  }
1389 
1390  return SCIP_OKAY;
1391 }
1392 
1393 
1394 /** constraint enforcing method of constraint handler for pseudo solutions */
1395 static
1396 SCIP_DECL_CONSENFOPS(consEnfopsOrbisack)
1397 { /*lint --e{715}*/
1398  SCIP_Bool feasible = TRUE;
1399  SCIP_CONSDATA* consdata;
1400  int c;
1401 
1402  assert( scip != NULL );
1403  assert( conshdlr != NULL );
1404  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1405  assert( result != NULL );
1406 
1407  SCIPdebugMsg(scip, "Enforcing method for orbisack constraints (pseudo solutions) ...\n");
1408 
1409  *result = SCIP_FEASIBLE;
1410 
1411  if ( objinfeasible || solinfeasible )
1412  return SCIP_OKAY;
1413 
1414  /* loop through constraints */
1415  for (c = 0; c < nconss; ++c)
1416  {
1417  /* get data of constraint */
1418  assert( conss[c] != NULL );
1419  consdata = SCIPconsGetData(conss[c]);
1420  assert( consdata != NULL);
1421  assert( consdata->nrows > 0 );
1422  assert( consdata->vars1 != NULL );
1423  assert( consdata->vars2 != NULL );
1424 
1425  /* do not enforce non-model constraints */
1426  if ( !consdata->ismodelcons )
1427  continue;
1428 
1429  SCIP_CALL( SCIPcheckSolutionOrbisack(scip, NULL, consdata->vars1, consdata->vars2, consdata->nrows, FALSE, &feasible) );
1430 
1431  if ( ! feasible )
1432  {
1433  *result = SCIP_INFEASIBLE;
1434  break;
1435  }
1436  }
1437 
1438  return SCIP_OKAY;
1439 }
1440 
1441 
1442 /** constraint enforcing method of constraint handler for relaxation solutions */
1443 static
1444 SCIP_DECL_CONSENFORELAX(consEnforelaxOrbisack)
1445 { /*lint --e{715}*/
1446  SCIP_CONSDATA* consdata;
1447  SCIP_Bool infeasible = FALSE;
1448  SCIP_Real* vals1;
1449  SCIP_Real* vals2;
1450  int ngen = 0;
1451  int c;
1452 
1453  assert( scip != 0 );
1454  assert( conshdlr != 0 );
1455  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1456  assert( result != 0 );
1457 
1458  SCIPdebugMsg(scip, "Enforelax method for orbisack constraints.\n");
1459 
1460  /* we have a negative priority, so we should come after the integrality conshdlr. */
1461  assert( SCIPgetNLPBranchCands(scip) == 0 );
1462 
1463  *result = SCIP_FEASIBLE;
1464 
1465  if ( nconss > 0 )
1466  {
1467  SCIP_CONSHDLRDATA* conshdlrdata;
1468  int nvals;
1469 
1470  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1471  assert( conshdlrdata != NULL );
1472 
1473  nvals = conshdlrdata->maxnrows;
1474  assert( nvals > 0 );
1475 
1476  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1477  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1478 
1479  /* loop through constraints */
1480  for (c = 0; c < nconss; ++c)
1481  {
1482  /* get data of constraint */
1483  assert( conss[c] != 0 );
1484  consdata = SCIPconsGetData(conss[c]);
1485  assert( consdata != NULL );
1486 
1487  /* do not enforce non-model constraints */
1488  if ( !consdata->ismodelcons )
1489  continue;
1490 
1491  /* get solution */
1492  assert( consdata->nrows <= nvals );
1493  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars1, vals1) );
1494  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars2, vals2) );
1495 
1496  SCIPdebugMsg(scip, "Enforcing orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1497 
1498  /* Separate only cover inequalities to ensure that enforcing works correctly. */
1499  /* Otherwise, it may happen that infeasible solutions cannot be detected, since */
1500  /* we bound the size of the coefficients for the orbisack inequalities. */
1501  SCIP_CALL( separateOrbisackCovers(scip, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2, &ngen, &infeasible) );
1502 
1503  if ( infeasible )
1504  {
1505  *result = SCIP_CUTOFF;
1506  break;
1507  }
1508 
1509  SCIPdebugMsg(scip, "Generated orbisack inequalities for <%s>: %d\n", SCIPconsGetName(conss[c]), ngen);
1510 
1511  if ( ngen > 0 )
1512  *result = SCIP_SEPARATED;
1513  }
1514 
1515  SCIPfreeBufferArray(scip, &vals2);
1516  SCIPfreeBufferArray(scip, &vals1);
1517  }
1518 
1519  return SCIP_OKAY;
1520 }
1521 
1522 
1523 /** feasibility check method of constraint handler for integral solutions */
1524 static
1525 SCIP_DECL_CONSCHECK(consCheckOrbisack)
1526 { /*lint --e{715}*/
1527  SCIP_Bool feasible = TRUE;
1528  SCIP_CONSDATA* consdata;
1529  int c;
1530 
1531  assert( scip != NULL );
1532  assert( conshdlr != NULL );
1533  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1534  assert( result != NULL );
1535 
1536  *result = SCIP_FEASIBLE;
1537 
1538  /* loop through constraints */
1539  for (c = 0; c < nconss; ++c)
1540  {
1541  /* get data of constraint */
1542  assert( conss[c] != NULL );
1543  consdata = SCIPconsGetData(conss[c]);
1544  assert( consdata != NULL);
1545  assert( consdata->nrows > 0 );
1546  assert( consdata->vars1 != NULL );
1547  assert( consdata->vars2 != NULL );
1548 
1549  SCIPdebugMsg(scip, "Check method for orbisack constraint <%s> (%d rows) ...\n", SCIPconsGetName(conss[c]), consdata->nrows);
1550 
1551  /* do not check non-model constraints */
1552  if ( !consdata->ismodelcons )
1553  continue;
1554 
1555  SCIP_CALL( SCIPcheckSolutionOrbisack(scip, sol, consdata->vars1, consdata->vars2, consdata->nrows, printreason, &feasible) );
1556 
1557  if ( ! feasible )
1558  {
1559  *result = SCIP_INFEASIBLE;
1560  SCIPdebugMsg(scip, "Solution is feasible.\n");
1561  break;
1562  }
1563  }
1564 
1565  if ( feasible )
1566  SCIPdebugMsg(scip, "Solution is feasible.\n");
1567 
1568  return SCIP_OKAY;
1569 }
1570 
1571 
1572 /** domain propagation method of constraint handler */
1573 static
1574 SCIP_DECL_CONSPROP(consPropOrbisack)
1575 { /*lint --e{715}*/
1576  int c;
1577 
1578  assert( scip != NULL );
1579  assert( conshdlr != NULL );
1580  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1581  assert( result != NULL );
1582 
1583  *result = SCIP_DIDNOTRUN;
1584 
1585  SCIPdebugMsg(scip, "Propagation method of orbisack constraint handler.\n");
1586 
1587  /* loop through constraints */
1588  for (c = 0; c < nconss; ++c)
1589  {
1590  SCIP_Bool infeasible = FALSE;
1591  SCIP_Bool found = FALSE;
1592  int ngen = 0;
1593 
1594  assert( conss[c] != NULL );
1595 
1596  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &found, &ngen) );
1597 
1598  if ( infeasible )
1599  {
1600  *result = SCIP_CUTOFF;
1601  return SCIP_OKAY;
1602  }
1603 
1604  if ( found )
1605  *result = SCIP_REDUCEDDOM;
1606  }
1607 
1608  return SCIP_OKAY;
1609 }
1610 
1611 
1612 /** presolving method of constraint handler */
1613 static
1614 SCIP_DECL_CONSPRESOL(consPresolOrbisack)
1615 { /*lint --e{715}*/
1616  int c;
1617  int ngen = 0;
1618 
1619  assert( scip != NULL );
1620  assert( conshdlr != NULL );
1621  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1622  assert( result != NULL );
1623 
1624  SCIPdebugMsg(scip, "Presolving method of orbisack constraint handler. Propagating orbisack inequalities.\n");
1625 
1626  *result = SCIP_DIDNOTFIND;
1627 
1628  /* loop through constraints */
1629  for (c = 0; c < nconss; ++c)
1630  {
1631  SCIP_Bool infeasible = FALSE;
1632  SCIP_Bool found = FALSE;
1633  int curngen = 0;
1634 
1635  assert( conss[c] != NULL );
1636  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &found, &curngen) );
1637 
1638  if ( infeasible )
1639  {
1640  *result = SCIP_CUTOFF;
1641  break;
1642  }
1643 
1644  ngen += curngen;
1645  }
1646 
1647  if ( ngen > 0 )
1648  {
1649  *nfixedvars += ngen;
1650  *result = SCIP_SUCCESS;
1651  }
1652 
1653  return SCIP_OKAY;
1654 }
1655 
1656 
1657 /** Propagation resolution for conflict analysis */
1658 static
1659 SCIP_DECL_CONSRESPROP(consRespropOrbisack)
1660 { /*lint --e{715}*/
1661  SCIP_CONSDATA* consdata;
1662  SCIP_VAR** vars1;
1663  SCIP_VAR** vars2;
1664  int i;
1665 
1666  assert( scip != NULL );
1667  assert( conshdlr != NULL );
1668  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1669  assert( cons != NULL );
1670  assert( infervar != NULL );
1671  assert( bdchgidx != NULL );
1672  assert( result != NULL );
1673 
1674  SCIPdebugMsg(scip, "Propagation resolution method of orbisack constraint handler.\n");
1675 
1676  *result = SCIP_DIDNOTFIND;
1677 
1678  consdata = SCIPconsGetData(cons);
1679  assert( consdata != NULL);
1680  assert( consdata->nrows > 0 );
1681  assert( consdata->vars1 != NULL );
1682  assert( consdata->vars2 != NULL );
1683 
1684  vars1 = consdata->vars1;
1685  vars2 = consdata->vars2;
1686 
1687  assert( 0 <= inferinfo && inferinfo < consdata->nrows );
1688 
1689  assert( vars2[inferinfo] == infervar );
1690  assert( SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, FALSE) > 0.5 && SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, TRUE) < 0.5 );
1691 
1692  if ( SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, FALSE) > 0.5 && SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, TRUE) < 0.5 )
1693  {
1694  SCIPdebugMsg(scip, " -> reason for setting x[%d][1] = 0 was fixing x[%d][0] to 0 and each row above is fixed to the same value.\n",
1695  inferinfo, inferinfo);
1696 
1697  for (i = 0; i < inferinfo; ++i)
1698  {
1699  SCIP_CALL( SCIPaddConflictUb(scip, vars1[i], bdchgidx) );
1700  SCIP_CALL( SCIPaddConflictLb(scip, vars1[i], bdchgidx) );
1701  SCIP_CALL( SCIPaddConflictUb(scip, vars2[i], bdchgidx) );
1702  SCIP_CALL( SCIPaddConflictLb(scip, vars2[i], bdchgidx) );
1703  }
1704  SCIP_CALL( SCIPaddConflictUb(scip, vars1[inferinfo], bdchgidx) );
1705 
1706  *result = SCIP_SUCCESS;
1707  }
1708 
1709  return SCIP_OKAY;
1710 }
1711 
1712 
1713 /** Lock variables
1714  *
1715  * We assume we have only one global (void) constraint and lock all variables.
1716  *
1717  * - Orbisack constraints may get violated if the variables of the first column
1718  * are rounded down, we therefor call SCIPaddVarLocksType(..., nlockspos, nlocksneg).
1719  * - Orbisack constraints may get violated if the variables of the second column
1720  * are rounded up , we therefor call SCIPaddVarLocksType(..., nlocksneg, nlockspo ).
1721  */
1722 static
1723 SCIP_DECL_CONSLOCK(consLockOrbisack)
1724 { /*lint --e{715}*/
1725  SCIP_CONSDATA* consdata;
1726  SCIP_VAR** vars1;
1727  SCIP_VAR** vars2;
1728  int nrows;
1729  int i;
1730 
1731  assert( scip != NULL );
1732  assert( conshdlr != NULL );
1733  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1734  assert( cons != NULL );
1735 
1736  SCIPdebugMsg(scip, "Locking method for orbisack constraint handler.\n");
1737 
1738  /* get data of original constraint */
1739  consdata = SCIPconsGetData(cons);
1740  assert( consdata != NULL);
1741  assert( consdata->nrows > 0 );
1742  assert( consdata->vars1 != NULL );
1743  assert( consdata->vars2 != NULL );
1744 
1745  nrows = consdata->nrows;
1746  vars1 = consdata->vars1;
1747  vars2 = consdata->vars2;
1748 
1749  for (i = 0; i < nrows; ++i)
1750  {
1751  SCIP_CALL( SCIPaddVarLocksType(scip, vars1[i], locktype, nlockspos, nlocksneg) );
1752  SCIP_CALL( SCIPaddVarLocksType(scip, vars2[i], locktype, nlocksneg, nlockspos) );
1753  }
1754 
1755  return SCIP_OKAY;
1756 }
1757 
1758 
1759 /** constraint copying method of constraint handler */
1760 static
1761 SCIP_DECL_CONSCOPY(consCopyOrbisack)
1763  SCIP_CONSHDLRDATA* conshdlrdata;
1764  SCIP_CONSDATA* sourcedata;
1765  SCIP_VAR** sourcevars1;
1766  SCIP_VAR** sourcevars2;
1767  SCIP_VAR** vars1;
1768  SCIP_VAR** vars2;
1769  int nrows;
1770  int i;
1771 
1772  assert( scip != NULL );
1773  assert( cons != NULL );
1774  assert( sourcescip != NULL );
1775  assert( sourceconshdlr != NULL );
1776  assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
1777  assert( sourcecons != NULL );
1778  assert( varmap != NULL );
1779  assert( valid != NULL );
1780 
1781  *valid = TRUE;
1782 
1783  SCIPdebugMsg(scip, "Copying method for orbisack constraint handler.\n");
1784 
1785  sourcedata = SCIPconsGetData(sourcecons);
1786  assert( sourcedata != NULL );
1787  assert( sourcedata->vars1 != NULL );
1788  assert( sourcedata->vars2 != NULL );
1789  assert( sourcedata->nrows > 0 );
1790 
1791  conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
1792  assert( conshdlrdata != NULL );
1793 
1794  /* do not copy non-model constraints */
1795  if ( !sourcedata->ismodelcons && !conshdlrdata->forceconscopy )
1796  {
1797  *valid = FALSE;
1798 
1799  return SCIP_OKAY;
1800  }
1801 
1802  sourcevars1 = sourcedata->vars1;
1803  sourcevars2 = sourcedata->vars2;
1804  nrows = sourcedata->nrows;
1805 
1806  SCIP_CALL( SCIPallocBufferArray(scip, &vars1, nrows) );
1807 
1808  for (i = 0; i < nrows && *valid; ++i)
1809  {
1810  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars1[i], &(vars1[i]), varmap, consmap, global, valid) );
1811  assert( !(*valid) || vars1[i] != NULL );
1812  }
1813 
1814  /* only create the target constraint, if all variables could be copied */
1815  if ( !(*valid) )
1816  {
1817  SCIPfreeBufferArray(scip, &vars1);
1818 
1819  return SCIP_OKAY;
1820  }
1821 
1822  SCIP_CALL( SCIPallocBufferArray(scip, &vars2, nrows) );
1823 
1824  for (i = 0; i < nrows && *valid; ++i)
1825  {
1826  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars2[i], &(vars2[i]), varmap, consmap, global, valid) );
1827  assert( !(*valid) || vars2[i] != NULL );
1828  }
1829 
1830  /* only create the target constraint, if all variables could be copied */
1831  if ( *valid )
1832  {
1833  /* create copied constraint */
1834  if ( name == NULL )
1835  name = SCIPconsGetName(sourcecons);
1836 
1837  SCIP_CALL( SCIPcreateConsOrbisack(scip, cons, name, vars1, vars2, nrows, FALSE, FALSE, sourcedata->ismodelcons,
1838  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1839  }
1840 
1841  SCIPfreeBufferArray(scip, &vars2);
1842  SCIPfreeBufferArray(scip, &vars1);
1843 
1844  return SCIP_OKAY;
1845 }
1846 
1847 
1848 /** constraint display method of constraint handler
1849  *
1850  * The constraint handler should output a representation of the constraint into the given text file.
1851  */
1852 static
1853 SCIP_DECL_CONSPRINT(consPrintOrbisack)
1854 { /*lint --e{715}*/
1855  SCIP_CONSDATA* consdata;
1856  SCIP_VAR** vars1;
1857  SCIP_VAR** vars2;
1858  int nrows;
1859  int i;
1860 
1861  assert( scip != NULL );
1862  assert( conshdlr != NULL );
1863  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1864  assert( cons != NULL );
1865 
1866  consdata = SCIPconsGetData(cons);
1867  assert( consdata != NULL );
1868  assert( consdata->vars1 != NULL );
1869  assert( consdata->vars2 != NULL );
1870  assert( consdata->nrows > 0 );
1871 
1872  vars1 = consdata->vars1;
1873  vars2 = consdata->vars2;
1874  nrows = consdata->nrows;
1875 
1876  SCIPdebugMsg(scip, "Printing method for orbisack constraint handler\n");
1877 
1878  SCIPinfoMessage(scip, file, "orbisack(");
1879 
1880  for (i = 0; i < nrows; ++i)
1881  {
1882  SCIPinfoMessage(scip, file, "%s,%s", SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
1883  if ( i < nrows-1 )
1884  SCIPinfoMessage(scip, file, ".");
1885  }
1886 
1887  return SCIP_OKAY;
1888 }
1889 
1890 
1891 /** checks given solution for feasibility */
1893  SCIP* scip, /**< SCIP data structure */
1894  SCIP_SOL* sol, /**< solution to check for feasibility */
1895  SCIP_VAR** vars1, /**< variables of first column */
1896  SCIP_VAR** vars2, /**< variables of second column */
1897  int nrows, /**< number of rows */
1898  SCIP_Bool printreason, /**< whether reason for infeasibility should be printed */
1899  SCIP_Bool* feasible /**< memory address to store whether sol is feasible */
1900  )
1901 {
1902  int i;
1903  int val1;
1904  int val2;
1905 
1906  assert( scip != NULL );
1907  assert( vars1 != NULL );
1908  assert( vars2 != NULL );
1909  assert( nrows > 0 );
1910  assert( feasible != NULL );
1911 
1912  *feasible = TRUE;
1913 
1914  /* find first non-constant row and check for feasibility */
1915  for (i = 0; i < nrows; ++i)
1916  {
1917  assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars1[i])) );
1918  assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars2[i])) );
1919 
1920  /* get values of i-th row */
1921  val1 = SCIPgetSolVal(scip, sol, vars1[i]) > 0.5 ? 1 : 0;
1922  val2 = SCIPgetSolVal(scip, sol, vars2[i]) > 0.5 ? 1 : 0;
1923 
1924  /* if row i is constrant */
1925  if ( val1 == val2 )
1926  continue;
1927  /* row i has type (1,0) -> feasible */
1928  else if ( val1 == 1 )
1929  {
1930  assert( val2 == 0 );
1931  break;
1932  }
1933  else /* infeasible */
1934  {
1935  if ( printreason )
1936  SCIPinfoMessage(scip, NULL, "First non-constant row %d is fixed to (0,1).\n", i);
1937  *feasible = FALSE;
1938  break;
1939  }
1940  }
1941 
1942  return SCIP_OKAY;
1943 }
1944 
1945 
1946 /** constraint method of constraint handler which returns the variables (if possible) */
1947 static
1948 SCIP_DECL_CONSGETVARS(consGetVarsOrbisack)
1949 { /*lint --e{715}*/
1950  SCIP_CONSDATA* consdata;
1951 
1952  assert( cons != NULL );
1953  assert( success != NULL );
1954  assert( vars != NULL );
1955 
1956  consdata = SCIPconsGetData(cons);
1957  assert( consdata != NULL );
1958 
1959  if ( varssize < 2 * consdata->nrows )
1960  (*success) = FALSE;
1961  else
1962  {
1963  int cnt = 0;
1964  int i;
1965 
1966  for (i = 0; i < consdata->nrows; ++i)
1967  {
1968  vars[cnt++] = consdata->vars1[i];
1969  vars[cnt++] = consdata->vars2[i];
1970  }
1971  (*success) = TRUE;
1972  }
1973 
1974  return SCIP_OKAY;
1975 }
1976 
1977 
1978 /** constraint method of constraint handler which returns the number of variables (if possible) */
1979 static
1980 SCIP_DECL_CONSGETNVARS(consGetNVarsOrbisack)
1981 { /*lint --e{715}*/
1982  SCIP_CONSDATA* consdata;
1983 
1984  assert( cons != NULL );
1985 
1986  consdata = SCIPconsGetData(cons);
1987  assert( consdata != NULL );
1988 
1989  (*nvars) = 2 * consdata->nrows;
1990  (*success) = TRUE;
1991 
1992  return SCIP_OKAY;
1993 }
1994 
1995 
1996 /** creates the handler for orbisack constraints and includes it in SCIP */
1998  SCIP* scip /**< SCIP data structure */
1999  )
2000 {
2001  SCIP_CONSHDLRDATA* conshdlrdata = NULL;
2002  SCIP_CONSHDLR* conshdlr;
2003 
2004  SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
2005 
2006  /* include constraint handler */
2010  consEnfolpOrbisack, consEnfopsOrbisack, consCheckOrbisack, consLockOrbisack,
2011  conshdlrdata) );
2012  assert( conshdlr != NULL );
2013 
2014  /* set non-fundamental callbacks via specific setter functions */
2015  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOrbisack, consCopyOrbisack) );
2016  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOrbisack) );
2017  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOrbisack) );
2018  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrbisack) );
2019  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOrbisack) );
2020  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOrbisack) );
2021  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolOrbisack, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
2022  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOrbisack) );
2024  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOrbisack) );
2025  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOrbisack, consSepasolOrbisack, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
2026  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOrbisack) );
2027  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpOrbisack) );
2028  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolOrbisack) );
2029 
2030  /* separation methods */
2031  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/coverseparation",
2032  "Separate cover inequalities for orbisacks?",
2033  &conshdlrdata->coverseparation, TRUE, DEFAULT_COVERSEPARATION, NULL, NULL) );
2034 
2035  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/orbiSeparation",
2036  "Separate orbisack inequalities?",
2037  &conshdlrdata->orbiseparation, TRUE, DEFAULT_ORBISEPARATION, NULL, NULL) );
2038 
2039  SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/coeffbound",
2040  "Maximum size of coefficients for orbisack inequalities",
2041  &conshdlrdata->coeffbound, TRUE, DEFAULT_COEFFBOUND, 0.0, DBL_MAX, NULL, NULL) );
2042 
2043  /* whether we allow upgrading to packing/partioning orbisack constraints*/
2044  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/checkpporbisack",
2045  "Upgrade orbisack constraints to packing/partioning orbisacks?",
2046  &conshdlrdata->checkpporbisack, TRUE, DEFAULT_PPORBISACK, NULL, NULL) );
2047 
2048  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/forceconscopy",
2049  "Whether orbisack constraints should be forced to be copied to sub SCIPs.",
2050  &conshdlrdata->forceconscopy, TRUE, DEFAULT_FORCECONSCOPY, NULL, NULL) );
2051 
2052  return SCIP_OKAY;
2053 }
2054 
2055 
2056 /*
2057  * constraint specific interface methods
2058  */
2059 
2060 /** creates and captures a orbisack constraint
2061  *
2062  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2063  */
2065  SCIP* scip, /**< SCIP data structure */
2066  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2067  const char* name, /**< name of constraint */
2068  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
2069  SCIP_VAR*const* vars2, /**< second column of matrix of variables on which the symmetry acts */
2070  int nrows, /**< number of rows in variable matrix */
2071  SCIP_Bool ispporbisack, /**< whether the orbisack is a packing/partitioning orbisack */
2072  SCIP_Bool isparttype, /**< whether the orbisack is a partitioning orbisack */
2073  SCIP_Bool ismodelcons, /**< whether the orbisack is a model constraint */
2074  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2075  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2076  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2077  * Usually set to TRUE. */
2078  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2079  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2080  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2081  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2082  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2083  * Usually set to TRUE. */
2084  SCIP_Bool local, /**< is constraint only valid locally?
2085  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2086  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2087  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2088  * adds coefficients to this constraint. */
2089  SCIP_Bool dynamic, /**< is constraint subject to aging?
2090  * Usually set to FALSE. Set to TRUE for own cuts which
2091  * are separated as constraints. */
2092  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2093  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2094  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2095  * if it may be moved to a more global node?
2096  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2097  )
2098 {
2099  SCIP_CONSHDLR* conshdlr;
2100  SCIP_CONSHDLRDATA* conshdlrdata;
2101  SCIP_CONSDATA* consdata;
2102  SCIP_VAR*** vars;
2103  SCIP_Bool success;
2104  SCIP_ORBITOPETYPE orbitopetype;
2105  int i;
2106 
2107  /* find the orbisack constraint handler */
2108  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2109  if ( conshdlr == NULL )
2110  {
2111  SCIPerrorMessage("orbisack constraint handler not found\n");
2112  return SCIP_PLUGINNOTFOUND;
2113  }
2114 
2115  assert( nrows > 0 );
2116 
2117  /* check for upgrade to packing/partitioning orbisacks*/
2118  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2119  if ( ! ispporbisack && conshdlrdata->checkpporbisack )
2120  {
2121  SCIP_CALL( packingUpgrade(scip, vars1, vars2, nrows, &success, &isparttype) );
2122 
2123  if ( success )
2124  ispporbisack = TRUE;
2125  }
2126 
2127  /* create constraint, if it is a packing/partitioning orbisack, add orbitope constraint
2128  * instead of orbitsack constraint */
2129  if ( ispporbisack )
2130  {
2131  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nrows) );
2132  for (i = 0; i < nrows; ++i)
2133  {
2134  SCIP_CALL( SCIPallocBufferArray(scip, &vars[i], 2) ); /*lint !e866*/
2135  vars[i][0] = vars1[i];
2136  vars[i][1] = vars2[i];
2137  }
2138 
2139  if ( isparttype )
2140  orbitopetype = SCIP_ORBITOPETYPE_PARTITIONING;
2141  else
2142  orbitopetype = SCIP_ORBITOPETYPE_PACKING;
2143 
2144  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, "pporbisack", vars, orbitopetype, nrows, 2, TRUE, ismodelcons,
2145  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2146 
2147  for (i = 0; i < nrows; ++i)
2148  SCIPfreeBufferArray(scip, &vars[i]);
2149  SCIPfreeBufferArray(scip, &vars);
2150  }
2151  else
2152  {
2153  /* create constraint data */
2154  SCIP_CALL( consdataCreate(scip, &consdata, vars1, vars2, nrows, ismodelcons) );
2155 
2156  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2157  local, modifiable, dynamic, removable, stickingatnode) );
2158  }
2159 
2160  return SCIP_OKAY;
2161 }
2162 
2163 
2164 /** creates and captures an orbisack constraint in its most basic variant
2165  *
2166  * All constraint flags set to their default values, which can be set afterwards using SCIPsetConsFLAGNAME() in scip.h.
2167  *
2168  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2169  */
2171  SCIP* scip, /**< SCIP data structure */
2172  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2173  const char* name, /**< name of constraint */
2174  SCIP_VAR** vars1, /**< first column of matrix of variables on which the symmetry acts */
2175  SCIP_VAR** vars2, /**< second column of matrix of variables on which the symmetry acts */
2176  int nrows, /**< number of rows in constraint matrix */
2177  SCIP_Bool ispporbisack, /**< whether the orbisack is a packing/partitioning orbisack */
2178  SCIP_Bool isparttype, /**< whether the orbisack is a partitioning orbisack */
2179  SCIP_Bool ismodelcons /**< whether the orbisack is a model constraint */
2180  )
2181 {
2182  SCIP_CALL( SCIPcreateConsOrbisack(scip, cons, name, vars1, vars2, nrows, ispporbisack, isparttype, ismodelcons,
2184 
2185  return SCIP_OKAY;
2186 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
static SCIP_DECL_CONSENFOPS(consEnfopsOrbisack)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:586
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:80
SCIP_EXPORT SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17172
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:877
public methods for SCIP parameter handling
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip_cons.c:934
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8316
public methods for memory management
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:308
static SCIP_RETCODE packingUpgrade(SCIP *scip, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, int nrows, SCIP_Bool *success, SCIP_Bool *isparttype)
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition: scip_mem.h:113
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8276
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:166
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4256
static SCIP_DECL_CONSRESPROP(consRespropOrbisack)
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1477
public methods for conflict handler plugins and conflict analysis
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:123
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:816
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1353
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2152
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:770
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4582
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:419
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
#define DEFAULT_COEFFBOUND
Definition: cons_orbisack.c:89
static SCIP_DECL_CONSGETVARS(consGetVarsOrbisack)
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5589
SCIP_EXPORT SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17197
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1368
#define FALSE
Definition: def.h:73
static SCIP_DECL_CONSSEPALP(consSepalpOrbisack)
constraint handler for orbisack constraints
static SCIP_RETCODE addOrbisackCover(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *coeffs1, SCIP_Real *coeffs2, SCIP_Real rhs, SCIP_Bool *infeasible)
#define TRUE
Definition: def.h:72
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
static SCIP_DECL_CONSINITSOL(consInitsolOrbisack)
#define CONSHDLR_NEEDSCONS
Definition: cons_orbisack.c:79
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8246
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:563
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9273
public methods for problem variables
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_param.c:48
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:95
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1604
static SCIP_RETCODE separateOrbisack(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *vals1, SCIP_Real *vals2, SCIP_Bool coverseparation, SCIP_Real coeffbound, int *ngen, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:525
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:123
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:839
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:78
public methods for SCIP variables
#define SCIPdebugMsg
Definition: scip_message.h:69
#define DEFAULT_ORBISEPARATION
Definition: cons_orbisack.c:85
static SCIP_RETCODE initLP(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:559
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:357
static SCIP_DECL_CONSTRANS(consTransOrbisack)
public methods for numerical tolerances
static SCIP_RETCODE addOrbisackInequality(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *coeffs1, SCIP_Real *coeffs2, SCIP_Real rhs, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:697
constraint handler for (partitioning/packing/full) orbitope constraints w.r.t. the full symmetric gro...
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:92
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8643
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbisack)
public methods for managing constraints
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1581
SCIP_EXPORT const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17017
#define CONSHDLR_DELAYPROP
Definition: cons_orbisack.c:78
static SCIP_DECL_CONSPRINT(consPrintOrbisack)
#define DEFAULT_FORCECONSCOPY
Definition: cons_orbisack.c:91
static SCIP_DECL_CONSCHECK(consCheckOrbisack)
#define SCIPerrorMessage
Definition: pub_message.h:55
#define CONSHDLR_DESC
Definition: cons_orbisack.c:67
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1508
SCIP_RETCODE SCIPcheckSolutionOrbisack(SCIP *scip, SCIP_SOL *sol, SCIP_VAR **vars1, SCIP_VAR **vars2, int nrows, SCIP_Bool printreason, SCIP_Bool *feasible)
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:429
#define CONSHDLR_SEPAFREQ
Definition: cons_orbisack.c:71
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1436
static SCIP_DECL_CONSCOPY(consCopyOrbisack)
#define NULL
Definition: lpi_spx1.cpp:155
#define CONSHDLR_PROP_TIMING
Definition: cons_orbisack.c:81
enum SCIP_OrbitopeType SCIP_ORBITOPETYPE
Definition: cons_orbitope.h:86
static SCIP_DECL_CONSPROP(consPropOrbisack)
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8107
#define CONSHDLR_CHECKPRIORITY
Definition: cons_orbisack.c:70
#define SCIP_CALL(x)
Definition: def.h:370
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:632
#define DEFAULT_PPORBISACK
Definition: cons_orbisack.c:90
static SCIP_RETCODE propVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, SCIP_Bool *found, int *ngen)
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:56
#define CONSHDLR_SEPAPRIORITY
Definition: cons_orbisack.c:68
public methods for constraint handler plugins and constraints
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8346
static SCIP_DECL_CONSGETNVARS(consGetNVarsOrbisack)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:111
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip_cons.c:220
#define SCIP_Bool
Definition: def.h:70
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:332
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4187
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
public methods for cuts and aggregation rows
#define CONSHDLR_ENFOPRIORITY
Definition: cons_orbisack.c:69
#define CONSHDLR_NAME
Definition: cons_orbisack.c:66
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8256
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8336
SCIP_EXPORT SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17723
static SCIP_DECL_CONSDELETE(consDeleteOrbisack)
static SCIP_RETCODE separateInequalities(SCIP *scip, SCIP_RESULT *result, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *vals1, SCIP_Real *vals2)
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:130
public methods for the LP relaxation, rows and columns
static SCIP_RETCODE separateOrbisackCovers(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *vals1, SCIP_Real *vals2, int *ngen, SCIP_Bool *infeasible)
static SCIP_DECL_CONSENFOLP(consEnfolpOrbisack)
SCIP_Real * r
Definition: circlepacking.c:50
SCIP_EXPORT SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17733
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_sol.c:1390
public methods for branching rule plugins and branching
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:221
general public methods
SCIP_RETCODE SCIPincludeConshdlrOrbisack(SCIP *scip)
static SCIP_DECL_CONSSEPASOL(consSepasolOrbisack)
public methods for solutions
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8266
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1641
SCIP_RETCODE SCIPcreateConsOrbitope(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, SCIP_ORBITOPETYPE orbitopetype, int nspcons, int nblocks, SCIP_Bool resolveprop, SCIP_Bool ismodelcons, 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)
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4539
public methods for message output
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9250
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8077
#define SCIP_Real
Definition: def.h:163
SCIP_EXPORT SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16427
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8097
public methods for message handling
#define CONSHDLR_MAXPREROUNDS
Definition: cons_orbisack.c:76
#define CONSHDLR_PRESOLTIMING
Definition: cons_orbisack.c:82
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8356
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4167
static SCIP_DECL_CONSPRESOL(consPresolOrbisack)
static SCIP_DECL_CONSLOCK(consLockOrbisack)
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9296
SCIP_EXPORT int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17360
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:55
static SCIP_DECL_CONSFREE(consFreeOrbisack)
#define CONSHDLR_DELAYSEPA
Definition: cons_orbisack.c:77
SCIP_RETCODE SCIPcreateConsOrbisack(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, int nrows, SCIP_Bool ispporbisack, SCIP_Bool isparttype, SCIP_Bool ismodelcons, 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 SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:98
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:199
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, int nrows, SCIP_Bool ismodelcons)
SCIP_RETCODE SCIPcreateConsBasicOrbisack(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR **vars1, SCIP_VAR **vars2, int nrows, SCIP_Bool ispporbisack, SCIP_Bool isparttype, SCIP_Bool ismodelcons)
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:266
#define CONSHDLR_PROPFREQ
Definition: cons_orbisack.c:72
static SCIP_DECL_CONSENFORELAX(consEnforelaxOrbisack)
#define CONSHDLR_EAGERFREQ
Definition: cons_orbisack.c:73
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip_cut.c:106
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8296
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:609
SCIP callable library.
#define DEFAULT_COVERSEPARATION
Definition: cons_orbisack.c:86
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8326
static SCIP_DECL_CONSINITLP(consInitlpOrbisack)
memory allocation routines