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-2020 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  assert( nsetppcvars > 0 );
333 
334  setppcvars = SCIPgetVarsSetppc(scip, setppcconss[c]);
335  assert( setppcvars != NULL );
336 
337  /* check whether all variables of the cycle are contained in setppc constraint */
338  for (j = 0; j < nsetppcvars && nfound < 2; ++j)
339  {
340  var = setppcvars[j];
341 
342  if ( SCIPvarIsNegated(var) )
343  continue;
344 
345  varidx = SCIPvarGetProbindex(var);
346 
347  if ( varidx == SCIPvarGetProbindex(vars1[i]) || varidx == SCIPvarGetProbindex(vars2[i]) )
348  ++nfound;
349  }
350 
351  if ( nfound == 2 )
352  break;
353  }
354 
355  /* row i is not contained in an setppc constraint */
356  if ( c >= nsetppcconss )
357  *success = FALSE;
358  }
359 
360  /* we have found a packing orbisack */
361  if ( *success )
362  *isparttype = FALSE;
363 
364  SCIPfreeBufferArray(scip, &rowcovered);
365 
366  return SCIP_OKAY;
367 }
368 
369 
370 /** generate initial LP cut
371  *
372  * We generate the inequality of the orbisack on the elements of the first row, i.e.,
373  * the inequality \f$-x_{1,1} + x_{1,2} \leq 0\f$.
374  */
375 static
377  SCIP* scip, /**< SCIP pointer */
378  SCIP_CONS* cons, /**< constraint */
379  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
380  )
381 {
382  SCIP_CONSDATA* consdata;
383  SCIP_VAR** vars1;
384  SCIP_VAR** vars2;
385  SCIP_VAR* tmpvars[2];
386  SCIP_ROW* row;
387 
388  assert( scip != NULL );
389  assert( cons != NULL );
390  assert( infeasible != NULL );
391 
392  *infeasible = FALSE;
393 
394  consdata = SCIPconsGetData(cons);
395  assert( consdata != 0 );
396  assert( consdata->nrows > 0 );
397  assert( consdata->vars1 != NULL );
398  assert( consdata->vars2 != NULL );
399 
400  vars1 = consdata->vars1;
401  vars2 = consdata->vars2;
402 
403  tmpvars[0] = vars1[0];
404  tmpvars[1] = vars2[0];
405 
406  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisack0#0", -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
407  SCIP_CALL( SCIPaddVarToRow(scip, row, tmpvars[0], -1.0) );
408  SCIP_CALL( SCIPaddVarToRow(scip, row, tmpvars[1], 1.0) );
409 
410  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
411 #ifdef SCIP_DEBUG
412  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
413 #endif
414  SCIP_CALL( SCIPreleaseRow(scip, &row) );
415 
416  return SCIP_OKAY;
417 }
418 
419 
420 /** add orbisack cover inequality */
421 static
423  SCIP* scip, /**< SCIP pointer */
424  SCIP_CONS* cons, /**< constraint */
425  int nrows, /**< number of rows of orbisack */
426  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
427  SCIP_VAR*const* vars2, /**< variables of second column */
428  SCIP_Real* coeffs1, /**< coefficients of the variables of the first column of the inequality to be added */
429  SCIP_Real* coeffs2, /**< coefficients of the variables of the second column of the inequality to be added */
430  SCIP_Real rhs, /**< right-hand side of inequality to be added */
431  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
432  )
433 {
434  SCIP_ROW* row;
435  int i;
436 
437  assert( scip != NULL );
438  assert( cons != NULL );
439  assert( vars1 != NULL );
440  assert( vars2 != NULL );
441  assert( coeffs1 != NULL );
442  assert( coeffs2 != NULL );
443  assert( infeasible != NULL );
444 
445  *infeasible = FALSE;
446 
447  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisackcover", -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
448  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
449  for (i = 0; i < nrows; ++i)
450  {
451  SCIP_CALL( SCIPaddVarToRow(scip, row, vars1[i], coeffs1[i]) );
452  SCIP_CALL( SCIPaddVarToRow(scip, row, vars2[i], coeffs2[i]) );
453  }
454  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
455 
456  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
457 #ifdef SCIP_DEBUG
458  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
459 #endif
460  SCIP_CALL( SCIPreleaseRow(scip, &row) );
461 
462  return SCIP_OKAY;
463 }
464 
465 
466 /** Separate lifted orbisack cover inequalities
467  *
468  * We currently do NOT enter cuts into the pool.
469  *
470  * We iterate over the nrows-many cover inequalities which are potentially
471  * maximal w.r.t. their violation.
472  */
473 static
475  SCIP* scip, /**< SCIP pointer */
476  SCIP_CONS* cons, /**< constraint */
477  int nrows, /**< number of rows of orbisack */
478  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
479  SCIP_VAR*const* vars2, /**< variables of second column */
480  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
481  SCIP_Real* vals2, /**< LP-solution for those variables in second column */
482  int* ngen, /**< number of separated covers */
483  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
484  )
485 {
486  SCIP_Real rhs = 0.0;
487  SCIP_Real lhs = 0.0;
488  SCIP_Real* coeff1;
489  SCIP_Real* coeff2;
490  int i;
491 
492  assert( scip != NULL );
493  assert( cons != NULL );
494  assert( nrows > 0 );
495  assert( vars1 != NULL );
496  assert( vars2 != NULL );
497  assert( infeasible != NULL );
498  assert( ngen != NULL );
499 
500  *infeasible = FALSE;
501  *ngen = 0;
502 
503  /* allocate memory for inequality coefficients */
504  SCIP_CALL( SCIPallocBufferArray(scip, &coeff1, nrows) );
505  SCIP_CALL( SCIPallocBufferArray(scip, &coeff2, nrows) );
506 
507  /* initialize coefficient matrix */
508  for (i = 0; i < nrows; ++i)
509  {
510  coeff1[i] = 0.0;
511  coeff2[i] = 0.0;
512  }
513 
514  /* detect violated covers */
515  for (i = 0; i < nrows; ++i)
516  {
517  /* cover inequality is violated */
518  if ( SCIPisEfficacious(scip, -vals1[i] + vals2[i] + lhs - rhs) )
519  {
520  /* set coefficients for inequality */
521  coeff1[i] = -1.0;
522  coeff2[i] = 1.0;
523 
524  SCIP_CALL( addOrbisackCover(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
525  ++(*ngen);
526  if ( *infeasible )
527  break;
528 
529  /* reset coefficients for next inequality */
530  coeff1[i] = 0.0;
531  coeff2[i] = 0.0;
532  }
533 
534  /* add argmax( 1 - vals[i][0], vals[i][1] ) as coefficient and ensure that both vars1[0] and vars2[0] are
535  * contained in the LIFTED cover inequality */
536  if ( SCIPisEfficacious(scip, 1.0 - vals1[i] - vals2[i]) )
537  {
538  coeff1[i] = -1.0;
539  lhs = lhs - vals1[i];
540 
541  /* lifting */
542  if ( i == 0 )
543  {
544  coeff2[0] = 1.0;
545  lhs += vals2[i];
546  }
547  }
548  else
549  {
550  coeff2[i] = 1.0;
551  rhs += 1.0;
552  lhs = lhs + vals2[i];
553 
554  /* lifting */
555  if ( i == 0 )
556  {
557  coeff1[0] = -1.0;
558  lhs -= vals1[i];
559  rhs -= 1.0;
560  }
561  }
562  }
563 
564  /* free coefficient matrix */
565  SCIPfreeBufferArray(scip, &coeff2);
566  SCIPfreeBufferArray(scip, &coeff1);
567 
568  return SCIP_OKAY;
569 }
570 
571 
572 /** add orbisack inequality */
573 static
575  SCIP* scip, /**< SCIP pointer */
576  SCIP_CONS* cons, /**< constraint */
577  int nrows, /**< number of rows of orbisack */
578  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
579  SCIP_VAR*const* vars2, /**< variables of second column */
580  SCIP_Real* coeffs1, /**< first column of coefficient matrix of inequality to be added */
581  SCIP_Real* coeffs2, /**< second column of coefficient matrix of inequality to be added */
582  SCIP_Real rhs, /**< right-hand side of inequality to be added */
583  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
584  )
585 {
586  SCIP_ROW* row;
587  int i;
588 
589  assert( scip != NULL );
590  assert( cons != NULL );
591  assert( vars1 != NULL );
592  assert( vars2 != NULL );
593  assert( coeffs1 != NULL );
594  assert( coeffs2 != NULL );
595  assert( infeasible != NULL );
596 
597  *infeasible = FALSE;
598 
599  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisack", -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
600  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
601 
602  for (i = 0; i < nrows; ++i)
603  {
604  SCIP_CALL( SCIPaddVarToRow(scip, row, vars1[i], coeffs1[i]) );
605  SCIP_CALL( SCIPaddVarToRow(scip, row, vars2[i], coeffs2[i]) );
606  }
607  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
608 
609  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
610 #ifdef SCIP_DEBUG
611  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
612 #endif
613  SCIP_CALL( SCIPreleaseRow(scip, &row) );
614 
615  return SCIP_OKAY;
616 }
617 
618 
619 /** separate orbisack inequalities
620  *
621  * We currently do NOT enter cuts into the pool.
622  *
623  * We stop if we checked for each possible basement row, whether a cut could be added. If the coefficients grow too
624  * large, we start separating cover inequalities.
625  *
626  * We implement the separation algorithm for orbisacks described in@n
627  * A. Loos. Describing Orbitopes by Linear Inequalities and Projection Based Tools.
628  * PhD thesis, Otto-von-Guericke-Universitaet Magdeburg, 2010.
629  */
630 static
632  SCIP* scip, /**< SCIP pointer */
633  SCIP_CONS* cons, /**< constraint */
634  int nrows, /**< number of rows of orbisack */
635  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
636  SCIP_VAR*const* vars2, /**< variables of second column */
637  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
638  SCIP_Real* vals2, /**< LP-solution for those variables in second column */
639  SCIP_Bool coverseparation, /**< whether we separate cover inequalities */
640  SCIP_Real coeffbound, /**< maximum size of coefficients in orbisack inequalities */
641  int* ngen, /**< pointer to store the number of generated cuts */
642  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
643  )
644 {
645  SCIP_Real* coeff1;
646  SCIP_Real* coeff2;
647  SCIP_Real rhs;
648  SCIP_Real lhs;
649  SCIP_Real valueA;
650  SCIP_Real valueB;
651  SCIP_Real valueC;
652  int basement;
653  int i;
654 
655  assert( scip != NULL );
656  assert( cons != NULL );
657  assert( nrows > 0 );
658  assert( vars1 != NULL );
659  assert( vars2 != NULL );
660  assert( coeffbound >= 0.0 );
661  assert( ngen != NULL );
662  assert( infeasible != NULL );
663 
664  *infeasible = FALSE;
665  *ngen = 0;
666 
667  /* if there is only one row, all cuts are added by initLP */
668  if ( nrows < 2 )
669  return SCIP_OKAY;
670 
671  /* allocate memory for inequality coefficients */
672  SCIP_CALL( SCIPallocBufferArray(scip, &coeff1, nrows) );
673  SCIP_CALL( SCIPallocBufferArray(scip, &coeff2, nrows) );
674 
675  /* initialize coefficient matrix row 0 */
676  coeff1[0] = -1.0;
677  coeff2[0] = 1.0;
678  for (i = 2; i < nrows; ++i)
679  {
680  coeff1[i] = 0.0;
681  coeff2[i] = 0.0;
682  }
683 
684  /* initialize right-hand side and left-hand side (lhs for row 0) */
685  rhs = 0.0;
686  lhs = - vals1[0] + vals2[0];
687 
688  /* basement row of orbisack */
689  basement = 1;
690 
691  /* update value of left-hand side and coefficients for basement row = 1 */
692  lhs += - vals1[1] + vals2[1];
693  coeff1[1] = -1.0;
694  coeff2[1] = 1.0;
695 
696  /* check whether cut for basement row = 1 is violated */
697  if ( SCIPisEfficacious(scip, lhs - rhs) )
698  {
699  SCIP_CALL( addOrbisackInequality(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
700  ++(*ngen);
701  }
702 
703  /* check whether there exists a cut with basement rows > 1 that is violated */
704  while ( basement < nrows - 1 && ! *infeasible )
705  {
706  valueA = lhs + vals1[basement] - vals1[basement + 1] + vals2[basement + 1] - rhs - 1.0; /*lint !e679, !e834*/
707  valueB = lhs - vals2[basement] - vals1[basement + 1] + vals2[basement + 1] - rhs; /*lint !e679, !e834*/
708  valueC = 2.0 * lhs + vals1[basement] - vals2[basement] - vals1[basement + 1] + vals2[basement + 1] - 2.0 * rhs; /*lint !e679, !e834*/
709 
710  /* update inequality */
711  if ( valueA >= valueB && valueA >= valueC )
712  {
713  ++rhs;
714  coeff1[basement] = 0.0;
715  lhs += vals1[basement++];
716  coeff1[basement] = -1.0;
717  coeff2[basement] = 1.0;
718  lhs += - vals1[basement] + vals2[basement];
719  }
720  else if ( valueB >= valueA && valueB >= valueC )
721  {
722  coeff2[basement] = 0.0;
723  lhs -= vals2[basement++];
724  coeff1[basement] = -1.0;
725  coeff2[basement] = 1.0;
726  lhs += - vals1[basement] + vals2[basement];
727  }
728  else
729  {
730  rhs *= 2.0;
731  lhs = 0.0;
732  for (i = 0; i < basement; ++i)
733  {
734  coeff1[i] = 2.0 * coeff1[i];
735  coeff2[i] = 2.0 * coeff2[i];
736  lhs += coeff1[i] * vals1[i] + coeff2[i] * vals2[i];
737  }
738  coeff1[basement] = -1.0;
739  coeff2[basement] = 1.0;
740  lhs -= vals1[basement];
741  lhs += vals2[basement++];
742  coeff1[basement] = -1.0;
743  coeff2[basement] = 1.0;
744  lhs -= vals1[basement];
745  lhs += vals2[basement];
746  }
747 
748  /* to avoid numerical troubles, we bound the size of coefficients and rhs */
749  if ( rhs > coeffbound || -coeff1[0] > coeffbound || coeff2[0] > coeffbound )
750  {
751  /* avoid separating cover inequalities twice */
752  if ( ! coverseparation )
753  {
754  int ncuts;
755  SCIP_CALL( separateOrbisackCovers(scip, cons, nrows, vars1, vars2, vals1, vals2, &ncuts, infeasible) );
756  *ngen += ncuts;
757  }
758  break;
759  }
760 
761  /* if current inequality is violated */
762  if ( SCIPisEfficacious(scip, lhs - rhs) )
763  {
764  SCIP_CALL( addOrbisackInequality(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
765  ++(*ngen);
766  }
767  }
768 
769  /* free allocated memory */
770  SCIPfreeBufferArray(scip, &coeff2);
771  SCIPfreeBufferArray(scip, &coeff1);
772 
773  return SCIP_OKAY;
774 }
775 
776 
777 /** propagation */
778 static
780  SCIP* scip, /**< SCIP pointer */
781  SCIP_CONS* cons, /**< constraint to be propagated */
782  SCIP_Bool* infeasible, /**< pointer to store whether it was detected that the node is infeasible */
783  SCIP_Bool* found, /**< pointer to store whether a new propagation could be found */
784  int* ngen /**< pointer to store the number of generated bound strengthenings */
785  )
786 {
787  SCIP_CONSDATA* consdata;
788  SCIP_VAR** vars1;
789  SCIP_VAR** vars2;
790  SCIP_Bool tightened = FALSE;
791  SCIP_VAR* var;
792  SCIP_Real ub;
793  SCIP_Real lb;
794  SCIP_VAR* var1;
795  SCIP_VAR* var2;
796  int* solu1;
797  int* solu2;
798  int nrows;
799  int i;
800  int r;
801 
802  assert( scip != NULL );
803  assert( cons != NULL );
804  assert( infeasible != NULL );
805  assert( ngen != NULL );
806  assert( found != NULL );
807 
808  SCIPdebugMsg(scip, "Propagating variables of constraint <%s>.\n", SCIPconsGetName(cons));
809 
810  *ngen = 0;
811  *infeasible = FALSE;
812  *found = FALSE;
813 
814  /* get data of constraint */
815  consdata = SCIPconsGetData(cons);
816  assert( consdata != NULL );
817  assert( consdata->vars1 != NULL );
818  assert( consdata->vars2 != NULL );
819  assert( consdata->nrows > 0 );
820 
821  nrows = consdata->nrows;
822  vars1 = consdata->vars1;
823  vars2 = consdata->vars2;
824 
825  /* determine current solution */
826  SCIP_CALL( SCIPallocBufferArray(scip, &solu1, nrows) );
827  SCIP_CALL( SCIPallocBufferArray(scip, &solu2, nrows) );
828 
829  for (i = 0; i < nrows; ++i)
830  {
831  /* determine value in first column */
832  var = vars1[i];
833  assert( SCIPvarIsBinary(var) );
834 
835  /* get local upper and lower bound on variable */
836  ub = SCIPvarGetUbLocal(var);
837  lb = SCIPvarGetLbLocal(var);
838 
839  /* if variable is fixed to 1 -> solu[i][j] = 1,
840  * if it is fixed to 0 -> solu[i][j] = 0,
841  * else, -> solu[i][j] = 2 */
842  if ( lb > 0.5 )
843  solu1[i] = 1;
844  else if (ub < 0.5)
845  solu1[i] = 0;
846  else
847  solu1[i] = 2;
848 
849  /* determine value in second column */
850  var = vars2[i];
851  assert( SCIPvarIsBinary(var) );
852 
853  /* get local upper and lower bound on variable */
854  ub = SCIPvarGetUbLocal(var);
855  lb = SCIPvarGetLbLocal(var);
856 
857  /* if variable is fixed to 1 -> solu[i][j] = 1,
858  * if it is fixed to 0 -> solu[i][j] = 0,
859  * else, -> solu[i][j] = 2 */
860  if ( lb > 0.5 )
861  solu2[i] = 1;
862  else if (ub < 0.5)
863  solu2[i] = 0;
864  else
865  solu2[i] = 2;
866  }
867 
868  /* loop through all variables */
869  for (i = 0; i < nrows; ++i)
870  {
871  /* get variables of first and second column */
872  var1 = vars1[i];
873  var2 = vars2[i];
874  assert( var1 != NULL );
875  assert( var2 != NULL );
876 
877  /* if variable in first column is fixed to 0 and variable in second column is fixed to 1 */
878  if ( SCIPvarGetUbLocal(var1) < 0.5 && SCIPvarGetLbLocal(var2) > 0.5 )
879  {
880  SCIP_Bool nocritical = TRUE;
881 
882  SCIPdebugMsg(scip, "Check variable pair (%d,0) and (%d,1).\n", i, i);
883 
884  /* check whether there is a critical row above row i, otherwise the solution is infeasible
885  * if there is a row without fixing (2) above the current row, we cannot obtain a result */
886  for (r = 0; r < i; ++r)
887  {
888  if ( (solu1[r] == 1 && solu2[r] == 0) || solu1[r] == 2 || solu2[r] == 2 )
889  {
890  nocritical = FALSE;
891  break;
892  }
893  }
894 
895  if ( nocritical )
896  {
897  SCIPdebugMsg(scip, " -> node infeasible (row was fixed to 0,1 but there was no critical row above).\n");
898 
899  /* perform conflict analysis */
901  {
903 
904  for (r = 0; r <= i; ++r)
905  {
906  SCIP_CALL( SCIPaddConflictBinvar(scip, vars1[r]) );
907  SCIP_CALL( SCIPaddConflictBinvar(scip, vars2[r]) );
908  }
909 
910  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
911 
912  *infeasible = TRUE;
913 
914  /* free current solution */
915  SCIPfreeBufferArray(scip, &solu2);
916  SCIPfreeBufferArray(scip, &solu1);
917 
918  return SCIP_OKAY;
919  }
920  }
921  }
922  /* if variable in the first column is fixed to 0 and the variable in the second column is free */
923  else if ( SCIPvarGetUbLocal(var1) < 0.5 && SCIPvarGetUbLocal(var2) > 0.5 )
924  {
925  SCIP_Bool allconstant = TRUE;
926 
927  SCIPdebugMsg(scip, "Check variable pair (%d,0) and (%d,1).\n", i, i);
928 
929  /* Check whether all rows above row i are constant. In this case, the variable in the second */
930  /* column can be fixed to 0. If an entry above row i is unfixed or a row is not constant, we cannot */
931  /* fix the second entry in row i. */
932  for (r = 0; r < i; ++r)
933  {
934  if ( solu1[r] == 2 || solu2[r] == 2 || solu1[r] != solu2[r] )
935  {
936  allconstant = FALSE;
937  break;
938  }
939  }
940 
941  /* fix variable in the second column to 0 */
942  if ( allconstant )
943  {
944  assert( SCIPvarGetLbLocal(var2) < 0.5 );
945  SCIP_CALL( SCIPinferVarUbCons(scip, var2, 0.0, cons, i, FALSE, infeasible, &tightened) ); /*lint !e713*/
946  assert( ! *infeasible );
947 
948  *found = *found || tightened;
949  if ( tightened )
950  ++(*ngen);
951  }
952  }
953  }
954 
955  /* free current solution */
956  SCIPfreeBufferArray(scip, &solu2);
957  SCIPfreeBufferArray(scip, &solu1);
958 
959  return SCIP_OKAY;
960 }
961 
962 
963 /** separate orbisack and cover inequalities */
964 static
966  SCIP* scip, /**< pointer to scip */
967  SCIP_RESULT* result, /**< pointer to store the result of separation */
968  SCIP_CONS* cons, /**< constraint */
969  int nrows, /**< number of rows of orbisack */
970  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
971  SCIP_VAR*const* vars2, /**< variables of second column */
972  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
973  SCIP_Real* vals2 /**< LP-solution for those variables in second column */
974  )
975 {
976  SCIP_CONSHDLRDATA* conshdlrdata;
977  SCIP_Bool infeasible = FALSE;
978  int ngen1 = 0;
979  int ngen2 = 0;
980 
981  assert( scip != NULL );
982  assert( result != NULL );
983  assert( cons != NULL );
984  assert( vars1 != NULL );
985  assert( vars2 != NULL );
986  assert( vals1 != NULL );
987  assert( vals2 != NULL );
988 
989  conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
990  assert( conshdlrdata != NULL );
991 
992  if ( conshdlrdata->orbiseparation )
993  {
994  SCIP_CALL( separateOrbisack(scip, cons, nrows, vars1, vars2, vals1, vals2, FALSE, conshdlrdata->coeffbound, &ngen1, &infeasible) );
995  }
996 
997  if ( ! infeasible && conshdlrdata->coverseparation )
998  {
999  SCIP_CALL( separateOrbisackCovers(scip, cons, nrows, vars1, vars2, vals1, vals2, &ngen2, &infeasible) );
1000  }
1001 
1002  if ( infeasible )
1003  {
1004  *result = SCIP_CUTOFF;
1005  return SCIP_OKAY;
1006  }
1007 
1008  if ( ngen1 + ngen2 > 0 )
1009  *result = SCIP_SEPARATED;
1010 
1011  return SCIP_OKAY;
1012 }
1013 
1014 
1015 /*--------------------------------------------------------------------------------------------
1016  *--------------------------------- SCIP functions -------------------------------------------
1017  *--------------------------------------------------------------------------------------------*/
1018 
1019 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1020 static
1021 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbisack)
1022 { /*lint --e{715}*/
1023  assert(scip != NULL);
1024  assert(conshdlr != NULL);
1025  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1026 
1027  /* call inclusion method of constraint handler */
1029 
1030  *valid = TRUE;
1031 
1032  return SCIP_OKAY;
1033 }
1034 
1035 /** frees specific constraint data */
1036 static
1037 SCIP_DECL_CONSDELETE(consDeleteOrbisack)
1038 { /*lint --e{715}*/
1039  assert( scip != 0 );
1040  assert( conshdlr != 0 );
1041  assert( consdata != 0 );
1042  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1043 
1044  SCIP_CALL( consdataFree(scip, consdata) );
1045 
1046  return SCIP_OKAY;
1047 }
1048 
1049 
1050 /** frees constraint handler */
1051 static
1052 SCIP_DECL_CONSFREE(consFreeOrbisack)
1053 { /*lint --e{715}*/
1054  SCIP_CONSHDLRDATA* conshdlrdata;
1055 
1056  assert( scip != 0 );
1057  assert( conshdlr != 0 );
1058  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1059 
1060  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1061  assert( conshdlrdata != NULL );
1062 
1063  SCIPfreeBlockMemory(scip, &conshdlrdata);
1064 
1065  return SCIP_OKAY;
1066 }
1067 
1068 
1069 /** transforms constraint data into data belonging to the transformed problem */
1070 static
1071 SCIP_DECL_CONSTRANS(consTransOrbisack)
1073  SCIP_CONSDATA* sourcedata;
1074  SCIP_CONSDATA* consdata = NULL;
1075  int nrows;
1076 
1077  assert( scip != NULL );
1078  assert( conshdlr != NULL );
1079  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1080  assert( sourcecons != NULL );
1081  assert( targetcons != NULL );
1082 
1083  SCIPdebugMsg(scip, "Transforming constraint.\n");
1084 
1085  /* get data of original constraint */
1086  sourcedata = SCIPconsGetData(sourcecons);
1087  assert( sourcedata != NULL );
1088  assert( sourcedata->nrows > 0 );
1089  assert( sourcedata->vars1 != NULL );
1090  assert( sourcedata->vars2 != NULL );
1091 
1092  if ( !sourcedata->ismodelcons )
1093  return SCIP_OKAY;
1094 
1095  /* create transformed constraint data (copy data where necessary) */
1096  nrows = sourcedata->nrows;
1097 
1098  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
1099 
1100  consdata->nrows = nrows;
1101  consdata->ismodelcons = sourcedata->ismodelcons;
1102 
1103  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars1, nrows) );
1104  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars2, nrows) );
1105 
1106  SCIP_CALL( SCIPgetTransformedVars(scip, nrows, sourcedata->vars1, consdata->vars1) );
1107  SCIP_CALL( SCIPgetTransformedVars(scip, nrows, sourcedata->vars2, consdata->vars2) );
1108 
1109  /* create transformed constraint */
1110  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, consdata,
1111  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
1112  SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
1113  SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
1114  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
1115  SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1116 
1117  return SCIP_OKAY;
1118 }
1119 
1120 
1121 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1122 static
1123 SCIP_DECL_CONSINITLP(consInitlpOrbisack)
1125  int c;
1126 
1127  assert( infeasible != NULL );
1128  *infeasible = FALSE;
1129 
1130  assert( scip != 0 );
1131  assert( conshdlr != 0 );
1132  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1133 
1134  /* loop through constraints */
1135  for (c = 0; c < nconss; ++c)
1136  {
1137  assert( conss[c] != 0 );
1138 
1139  SCIPdebugMsg(scip, "Generating initial orbisack cut for constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1140 
1141  SCIP_CALL( initLP(scip, conss[c], infeasible) );
1142  if ( *infeasible )
1143  break;
1144 
1145  SCIPdebugMsg(scip, "Generated initial orbisack cut.\n");
1146  }
1147 
1148  return SCIP_OKAY;
1149 }
1150 
1151 
1152 /** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
1153 static
1154 SCIP_DECL_CONSINITSOL(consInitsolOrbisack)
1156  SCIP_CONSHDLRDATA* conshdlrdata;
1157  int c;
1158 
1159  assert( scip != NULL );
1160  assert( conshdlr != NULL );
1161  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1162 
1163  /* determine maximum number of rows in an orbisack constraint */
1164  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1165  assert( conshdlrdata != NULL );
1166 
1167  conshdlrdata->maxnrows = 0;
1168 
1169  /* loop through constraints */
1170  for (c = 0; c < nconss; ++c)
1171  {
1172  SCIP_CONSDATA* consdata;
1173 
1174  assert( conss[c] != NULL );
1175 
1176  consdata = SCIPconsGetData(conss[c]);
1177  assert( consdata != NULL );
1178 
1179  /* update conshdlrdata if necessary */
1180  if ( consdata->nrows > conshdlrdata->maxnrows )
1181  conshdlrdata->maxnrows = consdata->nrows;
1182  }
1183 
1184  return SCIP_OKAY;
1185 }
1186 
1187 
1188 /** separation method of constraint handler for LP solution */
1189 static
1190 SCIP_DECL_CONSSEPALP(consSepalpOrbisack)
1191 { /*lint --e{715}*/
1192  SCIP_CONSDATA* consdata;
1193  SCIP_Real* vals1;
1194  SCIP_Real* vals2;
1195  int c;
1196 
1197  assert( scip != NULL );
1198  assert( conshdlr != NULL );
1199  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1200  assert( result != NULL );
1201 
1202  SCIPdebugMsg(scip, "Separation method for orbisack constraints.\n");
1203 
1204  *result = SCIP_DIDNOTRUN;
1205 
1206  /* if solution is not integer */
1207  if ( SCIPgetNLPBranchCands(scip) > 0 )
1208  {
1209  SCIP_CONSHDLRDATA* conshdlrdata;
1210  int nvals;
1211 
1212  *result = SCIP_DIDNOTFIND;
1213 
1214  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1215  assert( conshdlrdata != NULL );
1216 
1217  nvals = conshdlrdata->maxnrows;
1218  assert( nvals > 0 );
1219 
1220  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1221  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1222 
1223  /* loop through constraints */
1224  for (c = 0; c < nconss; ++c)
1225  {
1226  /* get data of constraint */
1227  assert( conss[c] != NULL );
1228  consdata = SCIPconsGetData(conss[c]);
1229 
1230  /* get solution */
1231  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars1, vals1) );
1232  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars2, vals2) );
1233 
1234  SCIPdebugMsg(scip, "Separating orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1235 
1236  SCIP_CALL( separateInequalities(scip, result, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2) );
1237 
1238  if ( *result == SCIP_CUTOFF )
1239  break;
1240  }
1241 
1242  SCIPfreeBufferArray(scip, &vals2);
1243  SCIPfreeBufferArray(scip, &vals1);
1244  }
1245 
1246  return SCIP_OKAY;
1247 }
1248 
1249 
1250 /** separation method of constraint handler for arbitrary primal solution */
1251 static
1252 SCIP_DECL_CONSSEPASOL(consSepasolOrbisack)
1253 { /*lint --e{715}*/
1254  SCIP_CONSDATA* consdata;
1255  SCIP_Real* vals1;
1256  SCIP_Real* vals2;
1257  int c;
1258 
1259  assert( scip != NULL );
1260  assert( conshdlr != NULL );
1261  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1262  assert( result != NULL );
1263 
1264  SCIPdebugMsg(scip, "Separation method for orbisack constraints\n");
1265 
1266  *result = SCIP_DIDNOTFIND;
1267 
1268  if ( nconss > 0 )
1269  {
1270  SCIP_CONSHDLRDATA* conshdlrdata;
1271  int nvals;
1272 
1273  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1274  assert( conshdlrdata != NULL );
1275 
1276  nvals = conshdlrdata->maxnrows;
1277  assert( nvals > 0 );
1278 
1279  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1280  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1281 
1282  /* loop through constraints */
1283  for (c = 0; c < nconss; ++c)
1284  {
1285  /* get data of constraint */
1286  assert( conss[c] != NULL );
1287  consdata = SCIPconsGetData(conss[c]);
1288 
1289  /* get solution */
1290  assert( consdata->nrows <= nvals );
1291  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars1, vals1) );
1292  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars2, vals2) );
1293 
1294  SCIPdebugMsg(scip, "Separating orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1295 
1296  SCIP_CALL( separateInequalities(scip, result, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2) );
1297  if ( *result == SCIP_CUTOFF )
1298  break;
1299  }
1300 
1301  SCIPfreeBufferArray(scip, &vals2);
1302  SCIPfreeBufferArray(scip, &vals1);
1303  }
1304 
1305  return SCIP_OKAY;
1306 }
1307 
1308 
1309 /** constraint enforcing method of constraint handler for LP solutions
1310  *
1311  * @pre It is assumed that the solution is integral (this can be ensured by appropriate priorities).
1312  */
1313 static
1314 SCIP_DECL_CONSENFOLP(consEnfolpOrbisack)
1315 { /*lint --e{715}*/
1316  SCIP_CONSDATA* consdata;
1317  SCIP_Bool infeasible = FALSE;
1318  SCIP_Real* vals1;
1319  SCIP_Real* vals2;
1320  int ngen = 0;
1321  int c;
1322 
1323  assert( scip != 0 );
1324  assert( conshdlr != 0 );
1325  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1326  assert( result != 0 );
1327 
1328  SCIPdebugMsg(scip, "Enfolp method for orbisack constraints\n");
1329 
1330  /* we have a negative priority, so we should come after the integrality conshdlr. */
1331  assert( SCIPgetNLPBranchCands(scip) == 0 );
1332 
1333  *result = SCIP_FEASIBLE;
1334 
1335  if ( nconss > 0 )
1336  {
1337  SCIP_CONSHDLRDATA* conshdlrdata;
1338  int nvals;
1339 
1340  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1341  assert( conshdlrdata != NULL );
1342 
1343  nvals = conshdlrdata->maxnrows;
1344  assert( nvals > 0 );
1345 
1346  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1347  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1348 
1349  /* loop through constraints */
1350  for (c = 0; c < nconss; ++c)
1351  {
1352  /* get data of constraint */
1353  assert( conss[c] != 0 );
1354  consdata = SCIPconsGetData(conss[c]);
1355  assert( consdata != NULL );
1356 
1357  /* do not enforce non-model constraints */
1358  if ( !consdata->ismodelcons )
1359  continue;
1360 
1361  /* get solution */
1362  assert( consdata->nrows <= nvals );
1363  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars1, vals1) );
1364  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars2, vals2) );
1365 
1366  SCIPdebugMsg(scip, "Enforcing orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1367 
1368  /* Separate only cover inequalities to ensure that enforcing works correctly. */
1369  /* Otherwise, it may happen that infeasible solutions cannot be detected, since */
1370  /* we bound the size of the coefficients for the orbisack inequalities. */
1371  SCIP_CALL( separateOrbisackCovers(scip, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2, &ngen, &infeasible) );
1372 
1373  if ( infeasible )
1374  {
1375  *result = SCIP_CUTOFF;
1376  break;
1377  }
1378 
1379  SCIPdebugMsg(scip, "Generated orbisack inequalities for <%s>: %d\n", SCIPconsGetName(conss[c]), ngen);
1380 
1381  if ( ngen > 0 )
1382  *result = SCIP_SEPARATED;
1383  }
1384 
1385  SCIPfreeBufferArray(scip, &vals2);
1386  SCIPfreeBufferArray(scip, &vals1);
1387  }
1388 
1389  return SCIP_OKAY;
1390 }
1391 
1392 
1393 /** constraint enforcing method of constraint handler for pseudo solutions */
1394 static
1395 SCIP_DECL_CONSENFOPS(consEnfopsOrbisack)
1396 { /*lint --e{715}*/
1397  SCIP_Bool feasible = TRUE;
1398  SCIP_CONSDATA* consdata;
1399  int c;
1400 
1401  assert( scip != NULL );
1402  assert( conshdlr != NULL );
1403  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1404  assert( result != NULL );
1405 
1406  SCIPdebugMsg(scip, "Enforcing method for orbisack constraints (pseudo solutions) ...\n");
1407 
1408  *result = SCIP_FEASIBLE;
1409 
1410  if ( objinfeasible || solinfeasible )
1411  return SCIP_OKAY;
1412 
1413  /* loop through constraints */
1414  for (c = 0; c < nconss; ++c)
1415  {
1416  /* get data of constraint */
1417  assert( conss[c] != NULL );
1418  consdata = SCIPconsGetData(conss[c]);
1419  assert( consdata != NULL);
1420  assert( consdata->nrows > 0 );
1421  assert( consdata->vars1 != NULL );
1422  assert( consdata->vars2 != NULL );
1423 
1424  /* do not enforce non-model constraints */
1425  if ( !consdata->ismodelcons )
1426  continue;
1427 
1428  SCIP_CALL( SCIPcheckSolutionOrbisack(scip, NULL, consdata->vars1, consdata->vars2, consdata->nrows, FALSE, &feasible) );
1429 
1430  if ( ! feasible )
1431  {
1432  *result = SCIP_INFEASIBLE;
1433  break;
1434  }
1435  }
1436 
1437  return SCIP_OKAY;
1438 }
1439 
1440 
1441 /** constraint enforcing method of constraint handler for relaxation solutions */
1442 static
1443 SCIP_DECL_CONSENFORELAX(consEnforelaxOrbisack)
1444 { /*lint --e{715}*/
1445  SCIP_CONSDATA* consdata;
1446  SCIP_Bool infeasible = FALSE;
1447  SCIP_Real* vals1;
1448  SCIP_Real* vals2;
1449  int ngen = 0;
1450  int c;
1451 
1452  assert( scip != 0 );
1453  assert( conshdlr != 0 );
1454  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1455  assert( result != 0 );
1456 
1457  SCIPdebugMsg(scip, "Enforelax method for orbisack constraints.\n");
1458 
1459  /* we have a negative priority, so we should come after the integrality conshdlr. */
1460  assert( SCIPgetNLPBranchCands(scip) == 0 );
1461 
1462  *result = SCIP_FEASIBLE;
1463 
1464  if ( nconss > 0 )
1465  {
1466  SCIP_CONSHDLRDATA* conshdlrdata;
1467  int nvals;
1468 
1469  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1470  assert( conshdlrdata != NULL );
1471 
1472  nvals = conshdlrdata->maxnrows;
1473  assert( nvals > 0 );
1474 
1475  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1476  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1477 
1478  /* loop through constraints */
1479  for (c = 0; c < nconss; ++c)
1480  {
1481  /* get data of constraint */
1482  assert( conss[c] != 0 );
1483  consdata = SCIPconsGetData(conss[c]);
1484  assert( consdata != NULL );
1485 
1486  /* do not enforce non-model constraints */
1487  if ( !consdata->ismodelcons )
1488  continue;
1489 
1490  /* get solution */
1491  assert( consdata->nrows <= nvals );
1492  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars1, vals1) );
1493  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars2, vals2) );
1494 
1495  SCIPdebugMsg(scip, "Enforcing orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1496 
1497  /* Separate only cover inequalities to ensure that enforcing works correctly. */
1498  /* Otherwise, it may happen that infeasible solutions cannot be detected, since */
1499  /* we bound the size of the coefficients for the orbisack inequalities. */
1500  SCIP_CALL( separateOrbisackCovers(scip, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2, &ngen, &infeasible) );
1501 
1502  if ( infeasible )
1503  {
1504  *result = SCIP_CUTOFF;
1505  break;
1506  }
1507 
1508  SCIPdebugMsg(scip, "Generated orbisack inequalities for <%s>: %d\n", SCIPconsGetName(conss[c]), ngen);
1509 
1510  if ( ngen > 0 )
1511  *result = SCIP_SEPARATED;
1512  }
1513 
1514  SCIPfreeBufferArray(scip, &vals2);
1515  SCIPfreeBufferArray(scip, &vals1);
1516  }
1517 
1518  return SCIP_OKAY;
1519 }
1520 
1521 
1522 /** feasibility check method of constraint handler for integral solutions */
1523 static
1524 SCIP_DECL_CONSCHECK(consCheckOrbisack)
1525 { /*lint --e{715}*/
1526  SCIP_Bool feasible = TRUE;
1527  SCIP_CONSDATA* consdata;
1528  int c;
1529 
1530  assert( scip != NULL );
1531  assert( conshdlr != NULL );
1532  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1533  assert( result != NULL );
1534 
1535  *result = SCIP_FEASIBLE;
1536 
1537  /* loop through constraints */
1538  for (c = 0; c < nconss; ++c)
1539  {
1540  /* get data of constraint */
1541  assert( conss[c] != NULL );
1542  consdata = SCIPconsGetData(conss[c]);
1543  assert( consdata != NULL);
1544  assert( consdata->nrows > 0 );
1545  assert( consdata->vars1 != NULL );
1546  assert( consdata->vars2 != NULL );
1547 
1548  SCIPdebugMsg(scip, "Check method for orbisack constraint <%s> (%d rows) ...\n", SCIPconsGetName(conss[c]), consdata->nrows);
1549 
1550  /* do not check non-model constraints */
1551  if ( !consdata->ismodelcons )
1552  continue;
1553 
1554  SCIP_CALL( SCIPcheckSolutionOrbisack(scip, sol, consdata->vars1, consdata->vars2, consdata->nrows, printreason, &feasible) );
1555 
1556  if ( ! feasible )
1557  {
1558  *result = SCIP_INFEASIBLE;
1559  SCIPdebugMsg(scip, "Solution is feasible.\n");
1560  break;
1561  }
1562  }
1563 
1564  if ( feasible )
1565  SCIPdebugMsg(scip, "Solution is feasible.\n");
1566 
1567  return SCIP_OKAY;
1568 }
1569 
1570 
1571 /** domain propagation method of constraint handler */
1572 static
1573 SCIP_DECL_CONSPROP(consPropOrbisack)
1574 { /*lint --e{715}*/
1575  int c;
1576 
1577  assert( scip != NULL );
1578  assert( conshdlr != NULL );
1579  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1580  assert( result != NULL );
1581 
1582  *result = SCIP_DIDNOTRUN;
1583 
1584  SCIPdebugMsg(scip, "Propagation method of orbisack constraint handler.\n");
1585 
1586  /* loop through constraints */
1587  for (c = 0; c < nconss; ++c)
1588  {
1589  SCIP_Bool infeasible = FALSE;
1590  SCIP_Bool found = FALSE;
1591  int ngen = 0;
1592 
1593  assert( conss[c] != NULL );
1594 
1595  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &found, &ngen) );
1596 
1597  if ( infeasible )
1598  {
1599  *result = SCIP_CUTOFF;
1600  return SCIP_OKAY;
1601  }
1602 
1603  if ( found )
1604  *result = SCIP_REDUCEDDOM;
1605  }
1606 
1607  return SCIP_OKAY;
1608 }
1609 
1610 
1611 /** presolving method of constraint handler */
1612 static
1613 SCIP_DECL_CONSPRESOL(consPresolOrbisack)
1614 { /*lint --e{715}*/
1615  int c;
1616  int ngen = 0;
1617 
1618  assert( scip != NULL );
1619  assert( conshdlr != NULL );
1620  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1621  assert( result != NULL );
1622 
1623  SCIPdebugMsg(scip, "Presolving method of orbisack constraint handler. Propagating orbisack inequalities.\n");
1624 
1625  *result = SCIP_DIDNOTFIND;
1626 
1627  /* loop through constraints */
1628  for (c = 0; c < nconss; ++c)
1629  {
1630  SCIP_Bool infeasible = FALSE;
1631  SCIP_Bool found = FALSE;
1632  int curngen = 0;
1633 
1634  assert( conss[c] != NULL );
1635  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &found, &curngen) );
1636 
1637  if ( infeasible )
1638  {
1639  *result = SCIP_CUTOFF;
1640  break;
1641  }
1642 
1643  ngen += curngen;
1644  }
1645 
1646  if ( ngen > 0 )
1647  {
1648  *nfixedvars += ngen;
1649  *result = SCIP_SUCCESS;
1650  }
1651 
1652  return SCIP_OKAY;
1653 }
1654 
1655 
1656 /** Propagation resolution for conflict analysis */
1657 static
1658 SCIP_DECL_CONSRESPROP(consRespropOrbisack)
1659 { /*lint --e{715}*/
1660  SCIP_CONSDATA* consdata;
1661  SCIP_VAR** vars1;
1662  SCIP_VAR** vars2;
1663  int i;
1664 
1665  assert( scip != NULL );
1666  assert( conshdlr != NULL );
1667  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1668  assert( cons != NULL );
1669  assert( infervar != NULL );
1670  assert( bdchgidx != NULL );
1671  assert( result != NULL );
1672 
1673  SCIPdebugMsg(scip, "Propagation resolution method of orbisack constraint handler.\n");
1674 
1675  *result = SCIP_DIDNOTFIND;
1676 
1677  consdata = SCIPconsGetData(cons);
1678  assert( consdata != NULL);
1679  assert( consdata->nrows > 0 );
1680  assert( consdata->vars1 != NULL );
1681  assert( consdata->vars2 != NULL );
1682 
1683  vars1 = consdata->vars1;
1684  vars2 = consdata->vars2;
1685 
1686  assert( 0 <= inferinfo && inferinfo < consdata->nrows );
1687 
1688  assert( vars2[inferinfo] == infervar );
1689  assert( SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, FALSE) > 0.5 && SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, TRUE) < 0.5 );
1690 
1691  if ( SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, FALSE) > 0.5 && SCIPvarGetUbAtIndex(vars2[inferinfo], bdchgidx, TRUE) < 0.5 )
1692  {
1693  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",
1694  inferinfo, inferinfo);
1695 
1696  for (i = 0; i < inferinfo; ++i)
1697  {
1698  SCIP_CALL( SCIPaddConflictUb(scip, vars1[i], bdchgidx) );
1699  SCIP_CALL( SCIPaddConflictLb(scip, vars1[i], bdchgidx) );
1700  SCIP_CALL( SCIPaddConflictUb(scip, vars2[i], bdchgidx) );
1701  SCIP_CALL( SCIPaddConflictLb(scip, vars2[i], bdchgidx) );
1702  }
1703  SCIP_CALL( SCIPaddConflictUb(scip, vars1[inferinfo], bdchgidx) );
1704 
1705  *result = SCIP_SUCCESS;
1706  }
1707 
1708  return SCIP_OKAY;
1709 }
1710 
1711 
1712 /** Lock variables
1713  *
1714  * We assume we have only one global (void) constraint and lock all variables.
1715  *
1716  * - Orbisack constraints may get violated if the variables of the first column
1717  * are rounded down, we therefor call SCIPaddVarLocksType(..., nlockspos, nlocksneg).
1718  * - Orbisack constraints may get violated if the variables of the second column
1719  * are rounded up , we therefor call SCIPaddVarLocksType(..., nlocksneg, nlockspo ).
1720  */
1721 static
1722 SCIP_DECL_CONSLOCK(consLockOrbisack)
1723 { /*lint --e{715}*/
1724  SCIP_CONSDATA* consdata;
1725  SCIP_VAR** vars1;
1726  SCIP_VAR** vars2;
1727  int nrows;
1728  int i;
1729 
1730  assert( scip != NULL );
1731  assert( conshdlr != NULL );
1732  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1733  assert( cons != NULL );
1734 
1735  SCIPdebugMsg(scip, "Locking method for orbisack constraint handler.\n");
1736 
1737  /* get data of original constraint */
1738  consdata = SCIPconsGetData(cons);
1739  assert( consdata != NULL);
1740  assert( consdata->nrows > 0 );
1741  assert( consdata->vars1 != NULL );
1742  assert( consdata->vars2 != NULL );
1743 
1744  nrows = consdata->nrows;
1745  vars1 = consdata->vars1;
1746  vars2 = consdata->vars2;
1747 
1748  for (i = 0; i < nrows; ++i)
1749  {
1750  SCIP_CALL( SCIPaddVarLocksType(scip, vars1[i], locktype, nlockspos, nlocksneg) );
1751  SCIP_CALL( SCIPaddVarLocksType(scip, vars2[i], locktype, nlocksneg, nlockspos) );
1752  }
1753 
1754  return SCIP_OKAY;
1755 }
1756 
1757 
1758 /** constraint copying method of constraint handler */
1759 static
1760 SCIP_DECL_CONSCOPY(consCopyOrbisack)
1762  SCIP_CONSHDLRDATA* conshdlrdata;
1763  SCIP_CONSDATA* sourcedata;
1764  SCIP_VAR** sourcevars1;
1765  SCIP_VAR** sourcevars2;
1766  SCIP_VAR** vars1;
1767  SCIP_VAR** vars2;
1768  int nrows;
1769  int i;
1770 
1771  assert( scip != NULL );
1772  assert( cons != NULL );
1773  assert( sourcescip != NULL );
1774  assert( sourceconshdlr != NULL );
1775  assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
1776  assert( sourcecons != NULL );
1777  assert( varmap != NULL );
1778  assert( valid != NULL );
1779 
1780  *valid = TRUE;
1781 
1782  SCIPdebugMsg(scip, "Copying method for orbisack constraint handler.\n");
1783 
1784  sourcedata = SCIPconsGetData(sourcecons);
1785  assert( sourcedata != NULL );
1786  assert( sourcedata->vars1 != NULL );
1787  assert( sourcedata->vars2 != NULL );
1788  assert( sourcedata->nrows > 0 );
1789 
1790  conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
1791  assert( conshdlrdata != NULL );
1792 
1793  /* do not copy non-model constraints */
1794  if ( !sourcedata->ismodelcons && !conshdlrdata->forceconscopy )
1795  {
1796  *valid = FALSE;
1797 
1798  return SCIP_OKAY;
1799  }
1800 
1801  sourcevars1 = sourcedata->vars1;
1802  sourcevars2 = sourcedata->vars2;
1803  nrows = sourcedata->nrows;
1804 
1805  SCIP_CALL( SCIPallocBufferArray(scip, &vars1, nrows) );
1806 
1807  for (i = 0; i < nrows && *valid; ++i)
1808  {
1809  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars1[i], &(vars1[i]), varmap, consmap, global, valid) );
1810  assert( !(*valid) || vars1[i] != NULL );
1811  }
1812 
1813  /* only create the target constraint, if all variables could be copied */
1814  if ( !(*valid) )
1815  {
1816  SCIPfreeBufferArray(scip, &vars1);
1817 
1818  return SCIP_OKAY;
1819  }
1820 
1821  SCIP_CALL( SCIPallocBufferArray(scip, &vars2, nrows) );
1822 
1823  for (i = 0; i < nrows && *valid; ++i)
1824  {
1825  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars2[i], &(vars2[i]), varmap, consmap, global, valid) );
1826  assert( !(*valid) || vars2[i] != NULL );
1827  }
1828 
1829  /* only create the target constraint, if all variables could be copied */
1830  if ( *valid )
1831  {
1832  /* create copied constraint */
1833  if ( name == NULL )
1834  name = SCIPconsGetName(sourcecons);
1835 
1836  SCIP_CALL( SCIPcreateConsOrbisack(scip, cons, name, vars1, vars2, nrows, FALSE, FALSE, sourcedata->ismodelcons,
1837  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1838  }
1839 
1840  SCIPfreeBufferArray(scip, &vars2);
1841  SCIPfreeBufferArray(scip, &vars1);
1842 
1843  return SCIP_OKAY;
1844 }
1845 
1846 
1847 /** constraint display method of constraint handler
1848  *
1849  * The constraint handler should output a representation of the constraint into the given text file.
1850  */
1851 static
1852 SCIP_DECL_CONSPRINT(consPrintOrbisack)
1853 { /*lint --e{715}*/
1854  SCIP_CONSDATA* consdata;
1855  SCIP_VAR** vars1;
1856  SCIP_VAR** vars2;
1857  int nrows;
1858  int i;
1859 
1860  assert( scip != NULL );
1861  assert( conshdlr != NULL );
1862  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1863  assert( cons != NULL );
1864 
1865  consdata = SCIPconsGetData(cons);
1866  assert( consdata != NULL );
1867  assert( consdata->vars1 != NULL );
1868  assert( consdata->vars2 != NULL );
1869  assert( consdata->nrows > 0 );
1870 
1871  vars1 = consdata->vars1;
1872  vars2 = consdata->vars2;
1873  nrows = consdata->nrows;
1874 
1875  SCIPdebugMsg(scip, "Printing method for orbisack constraint handler\n");
1876 
1877  SCIPinfoMessage(scip, file, "orbisack(");
1878 
1879  for (i = 0; i < nrows; ++i)
1880  {
1881  SCIPinfoMessage(scip, file, "%s,%s", SCIPvarGetName(vars1[i]), SCIPvarGetName(vars2[i]));
1882  if ( i < nrows-1 )
1883  SCIPinfoMessage(scip, file, ".");
1884  }
1885 
1886  return SCIP_OKAY;
1887 }
1888 
1889 
1890 /** checks given solution for feasibility */
1892  SCIP* scip, /**< SCIP data structure */
1893  SCIP_SOL* sol, /**< solution to check for feasibility */
1894  SCIP_VAR** vars1, /**< variables of first column */
1895  SCIP_VAR** vars2, /**< variables of second column */
1896  int nrows, /**< number of rows */
1897  SCIP_Bool printreason, /**< whether reason for infeasibility should be printed */
1898  SCIP_Bool* feasible /**< memory address to store whether sol is feasible */
1899  )
1900 {
1901  int i;
1902  int val1;
1903  int val2;
1904 
1905  assert( scip != NULL );
1906  assert( vars1 != NULL );
1907  assert( vars2 != NULL );
1908  assert( nrows > 0 );
1909  assert( feasible != NULL );
1910 
1911  *feasible = TRUE;
1912 
1913  /* find first non-constant row and check for feasibility */
1914  for (i = 0; i < nrows; ++i)
1915  {
1916  assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars1[i])) );
1917  assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars2[i])) );
1918 
1919  /* get values of i-th row */
1920  val1 = SCIPgetSolVal(scip, sol, vars1[i]) > 0.5 ? 1 : 0;
1921  val2 = SCIPgetSolVal(scip, sol, vars2[i]) > 0.5 ? 1 : 0;
1922 
1923  /* if row i is constrant */
1924  if ( val1 == val2 )
1925  continue;
1926  /* row i has type (1,0) -> feasible */
1927  else if ( val1 == 1 )
1928  {
1929  assert( val2 == 0 );
1930  break;
1931  }
1932  else /* infeasible */
1933  {
1934  if ( printreason )
1935  SCIPinfoMessage(scip, NULL, "First non-constant row %d is fixed to (0,1).\n", i);
1936  *feasible = FALSE;
1937  break;
1938  }
1939  }
1940 
1941  return SCIP_OKAY;
1942 }
1943 
1944 
1945 /** constraint method of constraint handler which returns the variables (if possible) */
1946 static
1947 SCIP_DECL_CONSGETVARS(consGetVarsOrbisack)
1948 { /*lint --e{715}*/
1949  SCIP_CONSDATA* consdata;
1950 
1951  assert( cons != NULL );
1952  assert( success != NULL );
1953  assert( vars != NULL );
1954 
1955  consdata = SCIPconsGetData(cons);
1956  assert( consdata != NULL );
1957 
1958  if ( varssize < 2 * consdata->nrows )
1959  (*success) = FALSE;
1960  else
1961  {
1962  int cnt = 0;
1963  int i;
1964 
1965  for (i = 0; i < consdata->nrows; ++i)
1966  {
1967  vars[cnt++] = consdata->vars1[i];
1968  vars[cnt++] = consdata->vars2[i];
1969  }
1970  (*success) = TRUE;
1971  }
1972 
1973  return SCIP_OKAY;
1974 }
1975 
1976 
1977 /** constraint method of constraint handler which returns the number of variables (if possible) */
1978 static
1979 SCIP_DECL_CONSGETNVARS(consGetNVarsOrbisack)
1980 { /*lint --e{715}*/
1981  SCIP_CONSDATA* consdata;
1982 
1983  assert( cons != NULL );
1984 
1985  consdata = SCIPconsGetData(cons);
1986  assert( consdata != NULL );
1987 
1988  (*nvars) = 2 * consdata->nrows;
1989  (*success) = TRUE;
1990 
1991  return SCIP_OKAY;
1992 }
1993 
1994 
1995 /** creates the handler for orbisack constraints and includes it in SCIP */
1997  SCIP* scip /**< SCIP data structure */
1998  )
1999 {
2000  SCIP_CONSHDLRDATA* conshdlrdata = NULL;
2001  SCIP_CONSHDLR* conshdlr;
2002 
2003  SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
2004 
2005  /* include constraint handler */
2009  consEnfolpOrbisack, consEnfopsOrbisack, consCheckOrbisack, consLockOrbisack,
2010  conshdlrdata) );
2011  assert( conshdlr != NULL );
2012 
2013  /* set non-fundamental callbacks via specific setter functions */
2014  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOrbisack, consCopyOrbisack) );
2015  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOrbisack) );
2016  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOrbisack) );
2017  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrbisack) );
2018  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOrbisack) );
2019  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOrbisack) );
2020  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolOrbisack, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
2021  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOrbisack) );
2023  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOrbisack) );
2024  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOrbisack, consSepasolOrbisack, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
2025  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOrbisack) );
2026  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpOrbisack) );
2027  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolOrbisack) );
2028 
2029  /* separation methods */
2030  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/coverseparation",
2031  "Separate cover inequalities for orbisacks?",
2032  &conshdlrdata->coverseparation, TRUE, DEFAULT_COVERSEPARATION, NULL, NULL) );
2033 
2034  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/orbiSeparation",
2035  "Separate orbisack inequalities?",
2036  &conshdlrdata->orbiseparation, TRUE, DEFAULT_ORBISEPARATION, NULL, NULL) );
2037 
2038  SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/coeffbound",
2039  "Maximum size of coefficients for orbisack inequalities",
2040  &conshdlrdata->coeffbound, TRUE, DEFAULT_COEFFBOUND, 0.0, DBL_MAX, NULL, NULL) );
2041 
2042  /* whether we allow upgrading to packing/partioning orbisack constraints*/
2043  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/checkpporbisack",
2044  "Upgrade orbisack constraints to packing/partioning orbisacks?",
2045  &conshdlrdata->checkpporbisack, TRUE, DEFAULT_PPORBISACK, NULL, NULL) );
2046 
2047  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/forceconscopy",
2048  "Whether orbisack constraints should be forced to be copied to sub SCIPs.",
2049  &conshdlrdata->forceconscopy, TRUE, DEFAULT_FORCECONSCOPY, NULL, NULL) );
2050 
2051  return SCIP_OKAY;
2052 }
2053 
2054 
2055 /*
2056  * constraint specific interface methods
2057  */
2058 
2059 /** creates and captures a orbisack constraint
2060  *
2061  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2062  */
2064  SCIP* scip, /**< SCIP data structure */
2065  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2066  const char* name, /**< name of constraint */
2067  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
2068  SCIP_VAR*const* vars2, /**< second column of matrix of variables on which the symmetry acts */
2069  int nrows, /**< number of rows in variable matrix */
2070  SCIP_Bool ispporbisack, /**< whether the orbisack is a packing/partitioning orbisack */
2071  SCIP_Bool isparttype, /**< whether the orbisack is a partitioning orbisack */
2072  SCIP_Bool ismodelcons, /**< whether the orbisack is a model constraint */
2073  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2074  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2075  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2076  * Usually set to TRUE. */
2077  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2078  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2079  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2080  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2081  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2082  * Usually set to TRUE. */
2083  SCIP_Bool local, /**< is constraint only valid locally?
2084  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2085  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2086  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2087  * adds coefficients to this constraint. */
2088  SCIP_Bool dynamic, /**< is constraint subject to aging?
2089  * Usually set to FALSE. Set to TRUE for own cuts which
2090  * are separated as constraints. */
2091  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2092  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2093  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2094  * if it may be moved to a more global node?
2095  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2096  )
2097 {
2098  SCIP_CONSHDLR* conshdlr;
2099  SCIP_CONSHDLRDATA* conshdlrdata;
2100  SCIP_CONSDATA* consdata;
2101  SCIP_VAR*** vars;
2102  SCIP_Bool success;
2103  SCIP_ORBITOPETYPE orbitopetype;
2104  int i;
2105 
2106  /* find the orbisack constraint handler */
2107  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2108  if ( conshdlr == NULL )
2109  {
2110  SCIPerrorMessage("orbisack constraint handler not found\n");
2111  return SCIP_PLUGINNOTFOUND;
2112  }
2113 
2114  assert( nrows > 0 );
2115 
2116  /* check for upgrade to packing/partitioning orbisacks*/
2117  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2118  if ( ! ispporbisack && conshdlrdata->checkpporbisack )
2119  {
2120  SCIP_CALL( packingUpgrade(scip, vars1, vars2, nrows, &success, &isparttype) );
2121 
2122  if ( success )
2123  ispporbisack = TRUE;
2124  }
2125 
2126  /* create constraint, if it is a packing/partitioning orbisack, add orbitope constraint
2127  * instead of orbitsack constraint */
2128  if ( ispporbisack )
2129  {
2130  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nrows) );
2131  for (i = 0; i < nrows; ++i)
2132  {
2133  SCIP_CALL( SCIPallocBufferArray(scip, &vars[i], 2) ); /*lint !e866*/
2134  vars[i][0] = vars1[i];
2135  vars[i][1] = vars2[i];
2136  }
2137 
2138  if ( isparttype )
2139  orbitopetype = SCIP_ORBITOPETYPE_PARTITIONING;
2140  else
2141  orbitopetype = SCIP_ORBITOPETYPE_PACKING;
2142 
2143  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, "pporbisack", vars, orbitopetype, nrows, 2, TRUE, ismodelcons,
2144  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2145 
2146  for (i = 0; i < nrows; ++i)
2147  SCIPfreeBufferArray(scip, &vars[i]);
2148  SCIPfreeBufferArray(scip, &vars);
2149  }
2150  else
2151  {
2152  /* create constraint data */
2153  SCIP_CALL( consdataCreate(scip, &consdata, vars1, vars2, nrows, ismodelcons) );
2154 
2155  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2156  local, modifiable, dynamic, removable, stickingatnode) );
2157  }
2158 
2159  return SCIP_OKAY;
2160 }
2161 
2162 
2163 /** creates and captures an orbisack constraint in its most basic variant
2164  *
2165  * All constraint flags set to their default values, which can be set afterwards using SCIPsetConsFLAGNAME() in scip.h.
2166  *
2167  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2168  */
2170  SCIP* scip, /**< SCIP data structure */
2171  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2172  const char* name, /**< name of constraint */
2173  SCIP_VAR** vars1, /**< first column of matrix of variables on which the symmetry acts */
2174  SCIP_VAR** vars2, /**< second column of matrix of variables on which the symmetry acts */
2175  int nrows, /**< number of rows in constraint matrix */
2176  SCIP_Bool ispporbisack, /**< whether the orbisack is a packing/partitioning orbisack */
2177  SCIP_Bool isparttype, /**< whether the orbisack is a partitioning orbisack */
2178  SCIP_Bool ismodelcons /**< whether the orbisack is a model constraint */
2179  )
2180 {
2181  SCIP_CALL( SCIPcreateConsOrbisack(scip, cons, name, vars1, vars2, nrows, ispporbisack, isparttype, ismodelcons,
2183 
2184  return SCIP_OKAY;
2185 }
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:17167
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:8328
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:8288
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:4263
static SCIP_DECL_CONSRESPROP(consRespropOrbisack)
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip_var.c:1484
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:4594
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:5596
SCIP_EXPORT SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17192
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:8258
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:9272
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:8648
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:17012
#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:1443
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:8119
#define CONSHDLR_CHECKPRIORITY
Definition: cons_orbisack.c:70
#define SCIP_CALL(x)
Definition: def.h:364
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:8358
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:4199
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:8268
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8348
SCIP_EXPORT SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17718
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:17728
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:8278
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:4551
public methods for message output
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9249
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8089
#define SCIP_Real
Definition: def.h:163
SCIP_EXPORT SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16422
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8109
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:8368
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4179
static SCIP_DECL_CONSPRESOL(consPresolOrbisack)
static SCIP_DECL_CONSLOCK(consLockOrbisack)
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9295
SCIP_EXPORT int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17355
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:8308
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:8338
static SCIP_DECL_CONSINITLP(consInitlpOrbisack)
memory allocation routines