Scippy

SCIP

Solving Constraint Integer Programs

cons_symresack.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-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_symresack.c
17  * @brief constraint handler for symresack constraints
18  * @author Christopher Hojny
19  *
20  * The type of constraints of this constraint handler is described in cons_symresack.h.
21  *
22  * The details of the method implemented here are described in the following papers:
23  *
24  * Fundamental Domains for Integer Programs with Symmetries@n
25  * Eric J. Friedman,@n
26  * Combinatorial Optimization, volume 4616 of LNCS, 146-153 (2007)
27  *
28  * This paper describes an inequality to handle symmetries of a single permutation. This
29  * so-called FD-inequality is the basic for the propagation routine of our implementation.
30  *
31  * Polytopes Associated with Symmetry Handling@n
32  * Christopher Hojny and Marc E. Pfetsch,@n
33  * (2017), preprint available at http://www.optimization-online.org/DB_HTML/2017/01/5835.html
34  *
35  * This paper describes an almost linear time separation routine for so-called cove
36  * inequalities of symresacks. In our implementation, however, we use a separation routine with
37  * quadratic worst case running time.
38  *
39  * Packing, Partitioning, and Covering Symresacks@n
40  * Christopher Hojny,@n
41  * (2017), preprint available at http://www.optimization-online.org/DB_HTML/2017/05/5990.html
42  *
43  * This paper introduces linearly many inequalities with ternary coefficients that suffice to
44  * characterize the binary points contained in a packing and partitioning symresack completely.
45  */
46 
47 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
48 
49 #include <assert.h>
50 #include <string.h>
51 #include <ctype.h>
52 
53 #include "scip/cons_orbisack.h"
54 #include "scip/cons_setppc.h"
55 #include "scip/cons_symresack.h"
56 
57 /* constraint handler properties */
58 #define CONSHDLR_NAME "symresack"
59 #define CONSHDLR_DESC "symmetry breaking constraint handler relying on symresacks"
60 #define CONSHDLR_SEPAPRIORITY +40100 /**< priority of the constraint handler for separation */
61 #define CONSHDLR_ENFOPRIORITY -1005200 /**< priority of the constraint handler for constraint enforcing */
62 #define CONSHDLR_CHECKPRIORITY -1005200 /**< priority of the constraint handler for checking feasibility */
63 #define CONSHDLR_SEPAFREQ 5 /**< frequency for separating cuts; zero means to separate only in the root node */
64 #define CONSHDLR_PROPFREQ 5 /**< frequency for propagating domains; zero means only preprocessing propagation */
65 #define CONSHDLR_EAGERFREQ -1 /**< frequency for using all instead of only the useful constraints in separation,
66  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
67 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
68 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
69 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
70 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
71 
72 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
73 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_EXHAUSTIVE
74 
75 #define DEFAULT_PPSYMRESACK FALSE /**< whether we allow upgrading to packing/partitioning symresacks */
76 #define DEFAULT_CHECKALWAYSFEAS TRUE /**< whether check routine returns always SCIP_FEASIBLE */
77 
78 /* macros for getting bounds of pseudo solutions in propagation */
79 #define ISFIXED0(x) (SCIPvarGetUbLocal(x) < 0.5 ? TRUE : FALSE)
80 #define ISFIXED1(x) (SCIPvarGetLbLocal(x) > 0.5 ? TRUE : FALSE)
81 
82 
83 /*
84  * Data structures
85  */
86 
87 /** constraint handler data */
88 struct SCIP_ConshdlrData
89 {
90  SCIP_Bool checkppsymresack; /**< whether we allow upgrading to packing/partitioning symresacks */
91  SCIP_Bool checkalwaysfeas; /**< whether check routine returns always SCIP_FEASIBLE */
92 };
93 
94 
95 /** constraint data for symresack constraints */
96 struct SCIP_ConsData
97 {
98  SCIP_VAR** vars; /**< variables */
99  int nvars; /**< number of variables */
100  int* perm; /**< permutation associated to the symresack */
101  int* invperm; /**< inverse permutation */
102  SCIP_Bool ppupgrade; /**< whether constraint is upgraded to packing/partitioning symresack */
103 #ifdef SCIP_DEBUG
104  int debugcnt; /**< counter to store number of added cover inequalities */
105 #endif
106 
107  /* data for upgraded symresack constraints */
108  int ncycles; /**< number of cycles in permutation */
109  int** cycledecomposition; /**< cycle decomposition */
110 };
111 
112 
113 /*
114  * Local methods
115  */
116 
117 /** frees a symresack constraint data */
118 static
120  SCIP* scip, /**< SCIP data structure */
121  SCIP_CONSDATA** consdata /**< pointer to symresack constraint data */
122  )
123 {
124  int nvars;
125  int i;
126 
127  assert( consdata != NULL );
128  assert( *consdata != NULL );
129 
130  nvars = (*consdata)->nvars;
131 
132  if ( nvars == 0 )
133  {
134  SCIPfreeBlockMemory(scip, consdata);
135 
136  return SCIP_OKAY;
137  }
138 
139  if ( (*consdata)->ppupgrade )
140  {
141  for (i = 0; i < (*consdata)->ncycles; ++i)
142  {
143  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->cycledecomposition[i]), nvars + 1);
144  }
145  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->cycledecomposition), (*consdata)->ncycles);
146  }
147 
148  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->invperm), nvars);
149  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->perm), nvars);
150 
151  for (i = 0; i < nvars; ++i)
152  {
153  SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->vars[i]) );
154  }
155  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars), nvars);
156 
157  SCIPfreeBlockMemory(scip, consdata);
158 
159  return SCIP_OKAY;
160 }
161 
162 
163 /** check whether constraint can be upgraded to packing/partitioning symresack */
164 static
166  SCIP* scip, /**< SCIP data structure */
167  SCIP_CONSDATA** consdata, /**< pointer to store constraint data */
168  int* perm, /**< permutation */
169  SCIP_VAR** vars, /**< variables affected by permutation */
170  int nvars, /**< length of permutation */
171  SCIP_Bool* upgrade /**< pointer to store whether upgrade was successful */
172  )
173 {
174  SCIP_Bool* covered;
175  SCIP_Bool descent;
176  SCIP_CONSHDLR* setppcconshdlr;
177  SCIP_CONS** setppcconss;
178  SCIP_VAR* var;
179  SCIP_Bool terminated = FALSE;
180  int** cycledecomposition;
181  int* indicesincycle;
182  int nsetppcconss;
183  int curcycle;
184  int maxcyclelength;
185  int ncycles = 0;
186  int c;
187  int i;
188  int j;
189 
190  assert( scip != NULL );
191  assert( perm != NULL );
192  assert( vars != NULL );
193  assert( nvars > 0 );
194  assert( upgrade != NULL );
195 
196  *upgrade = FALSE;
197 
198  SCIP_CALL( SCIPallocBufferArray(scip, &covered, nvars) );
199 
200  for (i = 0; i < nvars; ++i)
201  covered[i] = FALSE;
202 
203  /* check wether permutation is monotone */
204  for (i = 0; i < nvars; ++i)
205  {
206  /* skip checked indices */
207  if ( covered[i] )
208  continue;
209 
210  ++ncycles;
211  j = i;
212  descent = FALSE;
213 
214  do
215  {
216  covered[j] = TRUE;
217 
218  if ( perm[j] < j )
219  {
220  if ( ! descent )
221  descent = TRUE;
222  else
223  break;
224  }
225 
226  j = perm[j];
227  }
228  while ( j != i );
229 
230  /* if cycle is not monotone */
231  if ( j != i )
232  {
233  SCIPfreeBufferArray(scip, &covered);
234 
235  return SCIP_OKAY;
236  }
237  }
238  assert( ncycles <= nvars / 2 );
239 
240  /* each cycle is monotone; check for packing/partitioning type */
241  for (i = 0; i < nvars; ++i)
242  covered[i] = FALSE;
243 
244  /* compute cycle decomposition: row i stores in entry 0 the length of the cycle,
245  * the remaining entries are the coordinates in the cycle */
246  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &cycledecomposition, ncycles) );
247  for (i = 0; i < ncycles; ++i)
248  {
249  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &cycledecomposition[i], nvars + 1) );
250  }
251 
252  curcycle = 0;
253  maxcyclelength = 0;
254  for (i = 0; i < nvars; ++i)
255  {
256  int cyclelength = 0;
257 
258  /* skip checked indices */
259  if ( covered[i] )
260  continue;
261 
262  j = i;
263  do
264  {
265  covered[j] = TRUE;
266  cycledecomposition[curcycle][++cyclelength] = j;
267  j = perm[j];
268  }
269  while ( j != i );
270 
271  cycledecomposition[curcycle][0] = cyclelength;
272  ++curcycle;
273 
274  if ( maxcyclelength < cyclelength )
275  maxcyclelength = cyclelength;
276  }
277 
278  /* permutation can be upgraded -> check whether the symresack is of packing/partitioning type */
279  setppcconshdlr = SCIPfindConshdlr(scip, "setppc");
280  if ( setppcconshdlr == NULL )
281  {
282  SCIPerrorMessage("Setppc constraint handler not found.\n");
283  return SCIP_PLUGINNOTFOUND;
284  }
285  setppcconss = SCIPconshdlrGetConss(setppcconshdlr);
286  nsetppcconss = SCIPconshdlrGetNConss(setppcconshdlr);
287 
288  /* Check whether each cycle of the symresack is contained in a set packing/partitioning constraint.
289  * To this end, we have to guarantee that all affected variables are not negated since permutations
290  * are given w.r.t. original variables. */
291  *upgrade = TRUE;
292 
293  SCIP_CALL( SCIPallocBufferArray(scip, &indicesincycle, maxcyclelength) );
294 
295  for (i = 0; i < ncycles && *upgrade && ! terminated; ++i)
296  {
297  int cyclelength;
298 
299  /* get indices of variables in current cycle */
300  for (j = 0; j < cycledecomposition[i][0]; ++ j)
301  {
302  var = vars[cycledecomposition[i][j + 1]];
303 
304  if ( SCIPvarIsNegated(var) )
305  {
306  terminated = TRUE;
307  break;
308  }
309 
310  indicesincycle[j] = SCIPvarGetProbindex(var);
311  }
312 
313  cyclelength = cycledecomposition[i][0];
314 
315  /* iterate over constraints
316  *
317  * @todo Improve the check by sorting the constraints in the setppcconss array
318  * by type and number of contained variables. */
319  for (c = 0; c < nsetppcconss; ++c)
320  {
321  int nsetppcvars;
322  SCIP_VAR** setppcvars;
323  int varidx;
324  int nfound = 0;
325  int k;
326 
327  /* check type */
328  if ( SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_COVERING )
329  continue;
330  assert( SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_PARTITIONING || SCIPgetTypeSetppc(scip, setppcconss[c]) == SCIP_SETPPCTYPE_PACKING );
331 
332  /* get set packing/partitioning variables */
333  nsetppcvars = SCIPgetNVarsSetppc(scip, setppcconss[c]);
334  assert( nsetppcvars > 0 );
335 
336  setppcvars = SCIPgetVarsSetppc(scip, setppcconss[c]);
337  assert( setppcvars != NULL );
338 
339  /* check whether all variables of the cycle are contained in setppc constraint */
340  for (j = 0; j < nsetppcvars && nfound < cyclelength; ++j)
341  {
342  var = setppcvars[j];
343 
344  if ( SCIPvarIsNegated(var) )
345  continue;
346 
347  varidx = SCIPvarGetProbindex(var);
348 
349  for (k = 0; k < cyclelength; ++k)
350  {
351  if ( varidx == indicesincycle[k] )
352  {
353  ++nfound;
354  break;
355  }
356  }
357  }
358  assert( nfound <= cyclelength );
359 
360  if ( nfound == cyclelength )
361  break;
362  }
363 
364  /* row is not contained in a set packing/partitioning constraint */
365  if ( c >= nsetppcconss )
366  *upgrade = FALSE;
367  }
368 
369  if ( *upgrade )
370  {
371  (*consdata)->ncycles = ncycles;
372  (*consdata)->cycledecomposition = cycledecomposition;
373 
374  SCIPfreeBufferArray(scip, &indicesincycle);
375  SCIPfreeBufferArray(scip, &covered);
376  }
377  else
378  {
379  SCIPfreeBufferArray(scip, &indicesincycle);
380  SCIPfreeBufferArray(scip, &covered);
381  for (i = 0; i < ncycles; ++i)
382  {
383  SCIPfreeBlockMemoryArray(scip, &cycledecomposition[i], nvars + 1);
384  }
385  SCIPfreeBlockMemoryArray(scip, &cycledecomposition, ncycles);
386  }
387 
388  return SCIP_OKAY;
389 }
390 
391 
392 /** creates symresack constraint data
393  *
394  * If the input data contain non-binary variables of fixed
395  * points, we delete these variables in a preprocessing step.
396  */
397 static
399  SCIP* scip, /**< SCIP data structure */
400  SCIP_CONSDATA** consdata, /**< pointer to store constraint data */
401  SCIP_VAR*const* inputvars, /**< input variables of the constraint handler */
402  int inputnvars, /**< input number of variables of the constraint handler*/
403  int* inputperm /**< input permutation of the constraint handler */
404  )
405 {
406  SCIP_CONSHDLRDATA* conshdlrdata;
407  SCIP_CONSHDLR* conshdlr;
408  SCIP_VAR** vars;
409  SCIP_Bool upgrade;
410  int* indexcorrection;
411  int* invperm;
412  int* perm;
413  int naffectedvariables;
414  int i;
415  int j = 0;
416 
417  assert( consdata != NULL );
418 
419  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
420 
421 #ifdef SCI_DEBUG
422  consdata->debugcnt = 0;
423 #endif
424 
425  /* count the number of binary variables which are affected by the permutation */
426  SCIP_CALL( SCIPallocBufferArray(scip, &indexcorrection, inputnvars) );
427  indexcorrection[0] = -1;
428  for (i = 0; i < inputnvars; ++i)
429  {
430  if ( inputperm[i] != i && SCIPvarIsBinary(inputvars[i]) )
431  {
432  if ( i == 0 )
433  indexcorrection[i] = 0;
434  else
435  indexcorrection[i] = indexcorrection[i - 1] + 1;
436  }
437  else
438  {
439  if ( i > 0 )
440  indexcorrection[i] = indexcorrection[i - 1];
441  }
442  }
443  naffectedvariables = indexcorrection[inputnvars - 1] + 1;
444 
445  (*consdata)->nvars = naffectedvariables;
446 
447  /* Stop if we detect that the permutation fixes each binary point. */
448  if ( naffectedvariables == 0 )
449  {
450  SCIPfreeBufferArrayNull(scip, &indexcorrection);
451  return SCIP_OKAY;
452  }
453 
454  /* remove fixed points from permutation representation */
455  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &vars, naffectedvariables) );
456  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &perm, naffectedvariables) );
457  for (i = 0; i < inputnvars; ++i)
458  {
459  if ( i == 0 )
460  {
461  if ( indexcorrection[i] > -1 )
462  {
463  vars[j] = inputvars[i];
464  perm[j++] = indexcorrection[inputperm[i]];
465  }
466  }
467  else
468  {
469  if ( indexcorrection[i] > indexcorrection[i - 1] )
470  {
471  vars[j] = inputvars[i];
472  perm[j++] = indexcorrection[inputperm[i]];
473  }
474  }
475  }
476  SCIPfreeBufferArrayNull(scip, &indexcorrection);
477 
478  (*consdata)->vars = vars;
479  (*consdata)->perm = perm;
480 
481  for (i = 0; i < naffectedvariables; ++i)
482  {
483  SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[i]) );
484  }
485 
486  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &invperm, naffectedvariables) );
487  for (i = 0; i < naffectedvariables; ++i)
488  invperm[perm[i]] = i;
489  (*consdata)->invperm = invperm;
490 
491  /* check for upgrade to packing/partitioning symresacks*/
492  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
493  if ( conshdlr == NULL )
494  {
495  SCIPerrorMessage("symresack constraint handler not found\n");
496  return SCIP_PLUGINNOTFOUND;
497  }
498  conshdlrdata = SCIPconshdlrGetData(conshdlr);
499 
500  upgrade = FALSE;
501  if ( conshdlrdata->checkppsymresack )
502  {
503  SCIP_CALL( packingUpgrade(scip, consdata, perm, vars, naffectedvariables, &upgrade) );
504  }
505 
506  (*consdata)->ppupgrade = upgrade;
507 
508  /* get transformed variables, if we are in the transformed problem */
509  if ( SCIPisTransformed(scip) )
510  {
511  /* Make sure that all variables cannot be multiaggregated (cannot be handled by cons_symresack, since one cannot
512  * easily eliminate single variables from a symresack constraint. */
513  for (i = 0; i < naffectedvariables; ++i)
514  {
515  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vars[i], &(*consdata)->vars[i]) );
516  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[i]) );
517  }
518  }
519 
520  return SCIP_OKAY;
521 }
522 
523 
524 /** generate initial LP cut
525  *
526  * We generate the ordering inequality for the pair \f$(1, \gamma^{-1}(1))\f$, i.e.,
527  * the inequality \f$-x_{1} + x_{\gamma^{-1}(1)} \leq 0\f$. This inequality is valid,
528  * because we guaranteed in a preprocessing step that all variables are binary.
529  *
530  * Furthermore, we add facet inequalities of packing/partitioning symresacks if
531  * we deal with packing/partitioning symresacks.
532  */
533 static
535  SCIP* scip, /**< SCIP pointer */
536  SCIP_CONS* cons, /**< constraint */
537  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
538  )
539 {
540  SCIP_CONSDATA* consdata;
541  SCIP_VAR** vars;
542  SCIP_ROW* row;
543  int nvars;
544 #ifdef SCIP_DEBUG
545  char name[SCIP_MAXSTRLEN];
546 #endif
547  int i;
548  int j;
549  int k;
550 
551  assert( scip != NULL );
552  assert( cons != NULL );
553  assert( infeasible != NULL );
554 
555  *infeasible = FALSE;
556 
557  consdata = SCIPconsGetData(cons);
558  assert( consdata != NULL );
559 
560  nvars = consdata->nvars;
561 
562  /* avoid stupid problems */
563  if ( nvars <= 1 )
564  return SCIP_OKAY;
565 
566  assert( consdata->vars != NULL );
567  vars = consdata->vars;
568 
569  /* there are no fixed points */
570  assert( consdata->invperm[0] != 0 );
571 
572  /* add ordering inequality */
573 #ifdef SCIP_DEBUG
574  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "symresack_init_%s", SCIPconsGetName(cons));
575  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
576 #else
577  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), "", -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
578 #endif
579  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[0], -1.0) );
580  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[consdata->invperm[0]], 1.0) );
581 
582  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
583 
584  SCIP_CALL( SCIPreleaseRow(scip, &row) );
585 
586  /* check whether we have a packing/partioning symresack */
587  if ( consdata->ppupgrade && ! *infeasible )
588  {
589  SCIP_VAR** varsincons;
590  SCIP_Real* coeffs;
591  int** cycledecomposition;
592  int ncycles;
593  int nvarsincons;
594  int nvarsincycle;
595  int firstelemincycle;
596 
597  ncycles = consdata->ncycles;
598  cycledecomposition = consdata->cycledecomposition;
599 
600  SCIP_CALL( SCIPallocBufferArray(scip, &varsincons, nvars) );
601  SCIP_CALL( SCIPallocBufferArray(scip, &coeffs, nvars) );
602 
603  coeffs[0] = 1.0;
604 
605  /* add packing/partitioning symresack constraints */
606  for (i = 0; i < ncycles; ++i)
607  {
608  assert( cycledecomposition[i][0] > 0 );
609 
610  nvarsincycle = cycledecomposition[i][0];
611  varsincons[0] = vars[cycledecomposition[i][nvarsincycle]];
612  firstelemincycle = cycledecomposition[i][1];
613 
614  assert( firstelemincycle == consdata->perm[cycledecomposition[i][nvarsincycle]] );
615 
616  nvarsincons = 1;
617 
618  /* add variables of other cycles to the constraint */
619  for (j = 0; j < i; ++j)
620  {
621  nvarsincycle = cycledecomposition[j][0];
622  for (k = 1; k <= nvarsincycle; ++k)
623  {
624  if ( cycledecomposition[j][k] < firstelemincycle )
625  {
626  varsincons[nvarsincons] = vars[cycledecomposition[j][k]];
627  coeffs[nvarsincons++] = -1.0;
628  }
629  else
630  continue;
631  }
632  }
633 
634 #ifdef SCIP_DEBUG
635  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "ppSymresack_%d_%s", i, SCIPconsGetName(cons));
636  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
637 #else
638  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), "", -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
639 #endif
640  SCIP_CALL( SCIPaddVarsToRow(scip, row, nvarsincons, varsincons, coeffs) );
641 
642  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
643  SCIP_CALL( SCIPreleaseRow(scip, &row) );
644 
645  if ( *infeasible )
646  break;
647  }
648 
649  SCIPfreeBufferArray(scip, &coeffs);
650  SCIPfreeBufferArray(scip, &varsincons);
651  }
652 
653  return SCIP_OKAY;
654 }
655 
656 
657 /** perform propagation of symresack constraint */
658 static
660  SCIP* scip, /**< SCIP pointer */
661  SCIP_CONS* cons, /**< constraint to be propagated */
662  SCIP_Bool* infeasible, /**< pointer to store whether it was detected that the node is infeasible */
663  int* ngen /**< pointer to store number of generated bound strengthenings */
664  )
665 {
666  SCIP_CONSDATA* consdata;
667  SCIP_VAR** vars;
668  int* invperm;
669  int nvars;
670  int i;
671 
672  assert( scip != NULL );
673  assert( cons != NULL );
674  assert( infeasible != NULL );
675  assert( ngen != NULL );
676 
677  SCIPdebugMsg(scip, "Propagating variables of constraint <%s>.\n", SCIPconsGetName(cons));
678 
679  *ngen = 0;
680  *infeasible = FALSE;
681 
682  /* get data of constraint */
683  consdata = SCIPconsGetData(cons);
684  assert( consdata != NULL );
685  assert( consdata->nvars > 0 );
686  nvars = consdata->nvars;
687 
688  /* avoid trivial problems */
689  if ( nvars < 2 )
690  return SCIP_OKAY;
691 
692  assert( consdata->vars != NULL );
693  assert( consdata->invperm != NULL );
694  vars = consdata->vars;
695  invperm = consdata->invperm;
696 
697  /* loop through all variables */
698  for (i = 0; i < nvars; ++i)
699  {
700  SCIP_VAR* var2;
701  SCIP_VAR* var;
702  int r;
703  SCIP_Bool tightened;
704 
705  /* there are no fixed points */
706  assert( invperm[i] != i );
707 
708  /* get variables of first and second column */
709  var = vars[i];
710  var2 = vars[invperm[i]];
711  assert( var != NULL );
712  assert( var2 != NULL );
713 
714  /* if first part of variable pair fixed to 0 and second part is fixed to 1 */
715  if ( ISFIXED0(var) && ISFIXED1(var2) )
716  {
717  SCIPdebugMsg(scip, "Check variable pair (%d,%d).\n", i, invperm[i]);
718 
719  SCIPdebugMsg(scip, " -> node infeasible (pair was fixed to (0,1) but there was no pair of type (1,0) before) ---> lexicographical order violated, infeasible.\n");
720 
721  /* perform conflict analysis */
723  {
725 
726  for (r = 0; r <= i; ++r)
727  {
728  /* there are no fixed points */
729  assert( invperm[r] != r );
730 
731  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[r]) );
732  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[invperm[r]]) );
733  }
734 
735  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
736  }
737 
738  *infeasible = TRUE;
739  break;
740  }
741  /* if first part of the variable pair is fixed to 0 and the second part is free --> fix second part to 0 */
742  else if ( ISFIXED0(var) && ( ! ISFIXED0(var2) ) )
743  {
744  assert( SCIPvarGetUbLocal(var) < 0.5 );
745  assert( SCIPvarGetLbLocal(var2) < 0.5 );
746  assert( SCIPvarGetUbLocal(var2) > 0.5 );
747 
748  SCIPdebugMsg(scip, "Check variable pair (%d,%d).\n", i, invperm[i]);
749 
750  assert( SCIPvarGetLbLocal(var2) < 0.5 );
751  SCIP_CALL( SCIPinferVarUbCons(scip, var2, 0.0, cons, i, FALSE, infeasible, &tightened) ); /*lint !e713*/
752  assert( ! *infeasible );
753 
754  if ( tightened )
755  ++(*ngen);
756  }
757  /* if second part of the variable pair is fixed to 1 and the first part is free --> fix first part to 1 */
758  else if ( ( ! ISFIXED1(var) ) && ISFIXED1(var2) )
759  {
760  assert( SCIPvarGetLbLocal(var) < 0.5 );
761  assert( SCIPvarGetUbLocal(var) > 0.5 );
762  assert( SCIPvarGetLbLocal(var2) > 0.5 );
763 
764  SCIPdebugMsg(scip, "Check variable pair (%d,%d).\n", i, invperm[i]);
765 
766  assert( SCIPvarGetUbLocal(var) > 0.5 );
767  SCIP_CALL( SCIPinferVarLbCons(scip, var, 1.0, cons, i + nvars, FALSE, infeasible, &tightened) ); /*lint !e713*/
768  assert( ! *infeasible );
769 
770  if ( tightened )
771  ++(*ngen);
772  }
773  /* if solution is lexicographically maximal */
774  else if ( ISFIXED1(var) && ISFIXED0(var2) )
775  {
776  assert( SCIPvarGetLbLocal(var) > 0.5 );
777  assert( SCIPvarGetUbLocal(var2) < 0.5 );
778 
779  SCIPdebugMsg(scip, "Check variable pair (%d,%d).\n", i, invperm[i]);
780  SCIPdebugMsg(scip, " -> node is feasible (pair was fixed to (1,0) and every earlier pair is constant).\n");
781 
782  break;
783  }
784  /* cannot apply propagation */
785  else
786  break;
787  }
788 
789  return SCIP_OKAY;
790 }
791 
792 
793 /** add symresack cover inequality */
794 static
796  SCIP* scip, /**< SCIP pointer */
797  SCIP_CONS* cons, /**< constraint */
798  int nvars, /**< number of variables */
799  SCIP_VAR** vars, /**< variables */
800  int* coeffs, /**< coefficient vector of inequality to be added */
801  SCIP_Real rhs, /**< right-hand side of inequality to be added */
802  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
803  )
804 {
805  SCIP_ROW* row;
806  int i;
807 #ifdef SCIP_DEBUG
808  SCIP_CONSDATA* consdata;
809  char name[SCIP_MAXSTRLEN];
810 #endif
811 
812  assert( scip != NULL );
813  assert( cons != NULL );
814  assert( nvars > 0 );
815  assert( vars != NULL );
816  assert( coeffs != NULL );
817  assert( infeasible != NULL );
818 
819  *infeasible = FALSE;
820 
821 #ifdef SCIP_DEBUG
822  consdata = SCIPconsGetData(cons);
823  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "symresack_cover_%s_%d", SCIPconsGetName(cons), consdata->debugcnt);
824  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), name, -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
825  consdata->debugcnt += 1;
826 #else
827  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, SCIPconsGetHdlr(cons), "", -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
828 #endif
829  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
830 
831  for (i = 0; i < nvars; ++i)
832  {
833  if ( coeffs[i] == 1 || coeffs[i] == -1 )
834  {
835  SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i], (SCIP_Real) coeffs[i]) );
836  }
837  }
838  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
839  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
840  SCIP_CALL( SCIPreleaseRow(scip, &row) );
841 
842  return SCIP_OKAY;
843 }
844 
845 
846 /** separate symresack cover inequalities
847  *
848  * We currently do NOT enter cuts into the pool.
849  */
850 static
852  SCIP* scip, /**< SCIP pointer */
853  SCIP_CONS* cons, /**< constraint */
854  const SCIP_CONSDATA* consdata, /**< constraint data */
855  SCIP_Real* vals, /**< solution values of variables */
856  int* ngen, /**< pointer to store the number of separated covers */
857  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
858  )
859 {
860  SCIP_Real constobjective;
861  SCIP_Real* sepaobjective;
862  SCIP_Real tmpsoluobj = 0.0;
863  SCIP_Real maxsoluobj = 0.0;
864  int* tmpsolu;
865  int* maxsolu;
866  int* invperm;
867  int* perm;
868  int nvars;
869  int crit;
870  int i;
871 
872  *infeasible = FALSE;
873  *ngen = 0;
874 
875  assert( scip != NULL );
876  assert( consdata != NULL );
877 
878  /* we don't have to take care of trivial constraints */
879  if ( consdata->nvars < 2 )
880  return SCIP_OKAY;
881 
882  assert( consdata->vars != NULL );
883  assert( consdata->perm != NULL );
884  assert( consdata->invperm != NULL );
885  assert( infeasible != NULL );
886  assert( ngen != NULL );
887 
888  nvars = consdata->nvars;
889  perm = consdata->perm;
890  invperm = consdata->invperm;
891 
892  /* initialize objective */
893  SCIP_CALL( SCIPallocBufferArray(scip, &sepaobjective, nvars) );
894 
895  constobjective = 1.0; /* constant part of separation objective */
896  for (i = 0; i < nvars; ++i)
897  {
898  if ( i < perm[i] )
899  {
900  sepaobjective[i] = vals[i];
901  constobjective -= vals[i];
902  }
903  else
904  sepaobjective[i] = vals[i] - 1.0;
905  }
906 
907  /* allocate memory for temporary and global solution */
908  SCIP_CALL( SCIPallocBufferArray(scip, &tmpsolu, nvars) );
909  SCIP_CALL( SCIPallocBufferArray(scip, &maxsolu, nvars) );
910 
911  /* start separation procedure by iterating over critical rows */
912  for (crit = 0; crit < nvars; ++crit)
913  {
914  /* there are no fixed points */
915  assert( perm[crit] != crit );
916 
917  /* initialize temporary solution */
918  for (i = 0; i < nvars; ++i)
919  tmpsolu[i] = 2;
920  tmpsoluobj = 0.0;
921 
922  /* perform fixings implied by the critical row */
923  tmpsolu[crit] = 0;
924  assert( invperm[crit] < nvars );
925 
926  tmpsolu[invperm[crit]] = 1;
927  tmpsoluobj += sepaobjective[invperm[crit]];
928 
929  /* perform 1-fixings */
930  i = invperm[crit];
931  while ( i < crit )
932  {
933  i = invperm[i];
934  tmpsolu[i] = 1;
935  tmpsoluobj += sepaobjective[i];
936  }
937 
938  /* row c cannot be critical */
939  if ( i == crit )
940  continue;
941 
942  assert( tmpsolu[crit] == 0 );
943 
944  /* perform 0-fixing */
945  i = perm[crit];
946  while ( i < crit )
947  {
948  tmpsolu[i] = 0;
949  i = perm[i];
950  }
951 
952  /* iterate over rows above the critical row */
953  for (i = 0; i < crit; ++i)
954  {
955  SCIP_Real objimpact = 0.0;
956  int j;
957 
958  /* skip already fixed entries */
959  if ( tmpsolu[i] != 2 )
960  continue;
961 
962  /* Check effect of fixing entry i to 1 and apply all implied fixing to other entries.
963  *
964  * Observe: Experiments indicate that entries are more often fixed to 1 than to 0.
965  * For this reason, we apply the 1-fixings directly. If it turns out that the 1-fixings
966  * have a negative impact on the objective, we undo these fixings afterwards and apply
967  * 0-fixings instead. */
968 
969  /* check fixings in invperm direction */
970  j = i;
971  do
972  {
973  assert( tmpsolu[j] == 2 );
974  tmpsolu[j] = 1;
975  objimpact += sepaobjective[j];
976  j = invperm[j];
977  }
978  while ( j < crit && j != i );
979 
980  /* if we do not detect a cycle */
981  if ( j != i )
982  {
983  /* fix entry j since this is not done in the above do-while loop */
984  assert( tmpsolu[j] == 2 );
985  tmpsolu[j] = 1;
986  objimpact += sepaobjective[j];
987 
988  /* check fixings in perm direction */
989  j = perm[i];
990  while ( j < crit )
991  {
992  assert( j != i );
993  assert( tmpsolu[j] == 2 );
994  tmpsolu[j] = 1;
995  objimpact += sepaobjective[j];
996  j = perm[j];
997  }
998 
999  assert( j != crit );
1000  }
1001 
1002  /* if fixing entry i has a positive impact -> keep above fixings of entries to 1 */
1003  /* otherwise -> reset entries to 0 */
1004  if ( SCIPisEfficacious(scip, objimpact) )
1005  tmpsoluobj += objimpact;
1006  else
1007  {
1008  j = i;
1009  do
1010  {
1011  assert( tmpsolu[j] == 1 );
1012  tmpsolu[j] = 0;
1013  j = invperm[j];
1014  }
1015  while ( j < crit && j != i );
1016 
1017  /* if we do not detect a cycle */
1018  if ( j != i )
1019  {
1020  /* fix entry j since this is not done in the above do-while loop */
1021  assert( tmpsolu[j] == 1 );
1022  tmpsolu[j] = 0;
1023 
1024  /* check fixings in perm direction */
1025  j = perm[i];
1026  while ( j < crit )
1027  {
1028  assert( j != i );
1029  assert( tmpsolu[j] == 1 );
1030  tmpsolu[j] = 0;
1031  j = perm[j];
1032  }
1033 
1034  assert( j != crit );
1035  }
1036  }
1037  }
1038 
1039  /* iterate over unfixed entries below the critical row */
1040  for (i = crit + 1; i < nvars; ++i)
1041  {
1042  /* skip already fixed entries */
1043  if ( tmpsolu[i] != 2 )
1044  continue;
1045 
1046  if ( SCIPisEfficacious(scip, sepaobjective[i]) )
1047  {
1048  assert( tmpsolu[i] == 2 );
1049  tmpsolu[i] = 1;
1050  tmpsoluobj += sepaobjective[i];
1051  }
1052  else
1053  {
1054  assert( tmpsolu[i] == 2 );
1055  tmpsolu[i] = 0;
1056  }
1057  }
1058 
1059  /* check whether we have found a better solution which has positive separation objective*/
1060  if ( SCIPisEfficacious(scip, tmpsoluobj + constobjective - maxsoluobj) )
1061  {
1062  assert( SCIPisEfficacious(scip, tmpsoluobj + constobjective) );
1063  for (i = 0; i < nvars; ++i)
1064  maxsolu[i] = tmpsolu[i];
1065  maxsoluobj = tmpsoluobj + constobjective;
1066  }
1067  }
1068 
1069  /* Check whether the separation objective is positive, i.e., a violated cover was found. */
1070  if ( SCIPisEfficacious(scip, maxsoluobj) )
1071  {
1072  SCIP_Real rhs = -1.0;
1073  SCIP_Real lhs = 0.0;
1074 
1075  for (i = 0; i < nvars; ++i)
1076  {
1077  if ( i < perm[i] )
1078  {
1079  maxsolu[i] = maxsolu[i] - 1;
1080  lhs += vals[i] * maxsolu[i];
1081  }
1082  else
1083  {
1084  lhs += vals[i] * maxsolu[i];
1085  rhs += maxsolu[i];
1086  }
1087  }
1088 
1089  assert( SCIPisGT(scip, lhs, rhs) );
1090 
1091  /* add cover inequality */
1092  SCIP_CALL( addSymresackInequality(scip, cons, nvars, consdata->vars, maxsolu, rhs, infeasible) );
1093 
1094  if ( ! *infeasible )
1095  ++(*ngen);
1096  }
1097 
1098  SCIPfreeBufferArrayNull(scip, &maxsolu);
1099  SCIPfreeBufferArrayNull(scip, &tmpsolu);
1100  SCIPfreeBufferArrayNull(scip, &sepaobjective);
1101 
1102  return SCIP_OKAY;
1103 }
1104 
1105 
1106 static
1108  SCIP* scip, /**< SCIP pointer */
1109  SCIP_CONS* cons, /**< constrained for which we check the solution */
1110  SCIP_SOL* sol, /**< solution to be checked */
1111  SCIP_RESULT* result, /**< pointer to store whether we detected infeasibility */
1112  SCIP_Bool printreason /**< whether reason for infeasibility should be printed */
1113  )
1114 {
1115  SCIP_CONSDATA* consdata;
1116  SCIP_VAR** vars;
1117  int* invperm;
1118  int nvars;
1119  int i;
1120 
1121  assert( cons != NULL );
1122  consdata = SCIPconsGetData(cons);
1123  assert( consdata != NULL);
1124 
1125  /* we don't have to take care of trivial constraints */
1126  if ( consdata->nvars < 2 )
1127  return SCIP_OKAY;
1128 
1129  assert( consdata->vars != NULL );
1130  assert( consdata->invperm != NULL );
1131 
1132  SCIPdebugMsg(scip, "Check method for symresack constraint <%s> (%d rows) ...\n", SCIPconsGetName(cons), consdata->nvars);
1133 
1134  nvars = consdata->nvars;
1135  vars = consdata->vars;
1136  invperm = consdata->invperm;
1137 
1138  /* detect first non-constant pair of variables */
1139  for (i = 0; i < nvars; ++i)
1140  {
1141  SCIP_Real solval;
1142  int val1;
1143  int val2;
1144 
1145  /* there are no fixed points */
1146  assert( invperm[i] != i );
1147 
1148  /* get value of variable i and its inverse */
1149  solval = SCIPgetSolVal(scip, sol, vars[i]);
1150  assert( SCIPisFeasIntegral(scip, solval) );
1151  if ( solval > 0.5 )
1152  val1 = 1;
1153  else
1154  val1 = 0;
1155 
1156  solval = SCIPgetSolVal(scip, sol, vars[invperm[i]]);
1157  assert( SCIPisFeasIntegral(scip, solval) );
1158  if ( solval > 0.5 )
1159  val2 = 1;
1160  else
1161  val2 = 0;
1162 
1163  /* if we detected a constant pair */
1164  if ( val1 == val2 )
1165  continue;
1166  /* pair is (1,0) --> lexicographically maximal */
1167  else if ( val1 > val2 )
1168  break;
1169 
1170  /* pair is (0,1) --> solution is infeasible */
1171  assert( val2 > val1 );
1172  SCIPdebugMsg(scip, "Solution is infeasible.\n");
1173  *result = SCIP_INFEASIBLE;
1174 
1175  if ( printreason )
1176  SCIPinfoMessage(scip, NULL, "First non-constant pair (%d, %d) of variables has pattern (0,1).\n", i, invperm[i]);
1177 
1178  break;
1179  }
1180 
1181  return SCIP_OKAY;
1182 }
1183 
1184 
1185 /** Upgrade symresack constraints to orbisacks */
1186 static
1188  SCIP* scip, /**< SCIP pointer */
1189  SCIP_CONS** cons, /**< pointer to hold the created constraint */
1190  const char* name, /**< name of constraint */
1191  int* perm, /**< permutation */
1192  SCIP_VAR** inputvars, /**< permuted variables array */
1193  int nvars, /**< size of perm array */
1194  SCIP_Bool* upgrade, /**< whether constraint was upgraded */
1195  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
1196  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
1197  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
1198  * Usually set to TRUE. */
1199  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
1200  * TRUE for model constraints, FALSE for additional, redundant constraints. */
1201  SCIP_Bool check, /**< should the constraint be checked for feasibility?
1202  * TRUE for model constraints, FALSE for additional, redundant constraints. */
1203  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
1204  * Usually set to TRUE. */
1205  SCIP_Bool local, /**< is constraint only valid locally?
1206  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
1207  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
1208  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
1209  * adds coefficients to this constraint. */
1210  SCIP_Bool dynamic, /**< is constraint subject to aging?
1211  * Usually set to FALSE. Set to TRUE for own cuts which
1212  * are separated as constraints. */
1213  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
1214  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
1215  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
1216  * if it may be moved to a more global node?
1217  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
1218  )
1219 {
1220  SCIP_CONSHDLR* conshdlr;
1221  SCIP_VAR** vars1;
1222  SCIP_VAR** vars2;
1223  int nrows = 0;
1224  int i;
1225 
1226  assert( scip != NULL );
1227  assert( perm != NULL );
1228  assert( nvars > 0 );
1229  assert( inputvars != NULL );
1230  assert( upgrade != NULL );
1231 
1232  *upgrade = TRUE;
1233 
1234  /* check whether orbisack conshdlr is available */
1235  conshdlr = SCIPfindConshdlr(scip, "orbisack");
1236  if ( conshdlr == NULL )
1237  {
1238  *upgrade = FALSE;
1239  SCIPdebugMsg(scip, "Cannot check whether symresack constraint can be upgraded to orbisack constraint. ");
1240  SCIPdebugMsg(scip, "---> Orbisack constraint handler not found.\n");
1241 
1242  return SCIP_OKAY;
1243  }
1244 
1245  SCIP_CALL( SCIPallocBufferArray(scip, &vars1, nvars) );
1246  SCIP_CALL( SCIPallocBufferArray(scip, &vars2, nvars) );
1247 
1248  /* check whether permutation is a composition of 2-cycles */
1249  for (i = 0; i < nvars; ++i)
1250  {
1251  /* ignore non-binary variables */
1252  if ( ! SCIPvarIsBinary(inputvars[i]) )
1253  continue;
1254 
1255  if ( perm[perm[i]] != i )
1256  {
1257  *upgrade = FALSE;
1258  break;
1259  }
1260 
1261  if ( perm[i] > i )
1262  {
1263  vars1[nrows] = inputvars[i];
1264  vars2[nrows++] = inputvars[perm[i]];
1265 
1266  assert( nrows <= nvars );
1267  }
1268  }
1269 
1270  /* if permutation can be upgraded to an orbisack */
1271  if ( nrows == 0 )
1272  *upgrade = FALSE;
1273  else if ( *upgrade )
1274  {
1275  SCIP_CALL( SCIPcreateConsOrbisack(scip, cons, name, vars1, vars2, nrows, FALSE, FALSE,
1276  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1277  }
1278 
1279  SCIPfreeBufferArray(scip, &vars2);
1280  SCIPfreeBufferArray(scip, &vars1);
1281 
1282  return SCIP_OKAY;
1283 }
1284 
1285 
1286 /** creates a symmetry breaking constraint
1287  *
1288  * Depending on the given permutation, either an orbisack or symresack constraint
1289  * is created.
1290  */
1292  SCIP* scip, /**< SCIP data structure */
1293  SCIP_CONS** cons, /**< pointer to hold the created constraint */
1294  const char* name, /**< name of constraint */
1295  int* perm, /**< permutation */
1296  SCIP_VAR** vars, /**< variables */
1297  int nvars, /**< number of variables in vars array */
1298  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
1299  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
1300  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
1301  * Usually set to TRUE. */
1302  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
1303  * TRUE for model constraints, FALSE for additional, redundant constraints. */
1304  SCIP_Bool check, /**< should the constraint be checked for feasibility?
1305  * TRUE for model constraints, FALSE for additional, redundant constraints. */
1306  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
1307  * Usually set to TRUE. */
1308  SCIP_Bool local, /**< is constraint only valid locally?
1309  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
1310  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
1311  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
1312  * adds coefficients to this constraint. */
1313  SCIP_Bool dynamic, /**< is constraint subject to aging?
1314  * Usually set to FALSE. Set to TRUE for own cuts which
1315  * are separated as constraints. */
1316  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
1317  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
1318  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
1319  * if it may be moved to a more global node?
1320  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
1321  )
1322 {
1323  SCIP_Bool upgrade = FALSE;
1324 
1325  assert( scip != NULL );
1326  assert( cons != NULL );
1327  assert( perm != NULL );
1328  assert( vars != NULL );
1329  assert( nvars > 0 );
1330 
1331  SCIP_CALL( orbisackUpgrade(scip, cons, name, perm, vars, nvars, &upgrade,
1332  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1333 
1334  if ( ! upgrade )
1335  {
1336  SCIP_CALL( SCIPcreateConsSymresack(scip, cons, name, perm, vars, nvars,
1337  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1338  }
1339 
1340 
1341  return SCIP_OKAY;
1342 }
1343 
1344 
1345 /*--------------------------------------------------------------------------------------------
1346  *--------------------------------- SCIP functions -------------------------------------------
1347  *--------------------------------------------------------------------------------------------*/
1348 
1349 /** frees specific constraint data */
1350 static
1351 SCIP_DECL_CONSDELETE(consDeleteSymresack)
1352 { /*lint --e{715}*/
1353  assert( scip != NULL );
1354  assert( conshdlr != NULL );
1355  assert( consdata != NULL );
1356  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1357 
1358  SCIP_CALL( consdataFree(scip, consdata) );
1359 
1360  return SCIP_OKAY;
1361 }
1362 
1363 
1364 /** frees constraint handler */
1365 static
1366 SCIP_DECL_CONSFREE(consFreeSymresack)
1367 { /*lint --e{715}*/
1368  SCIP_CONSHDLRDATA* conshdlrdata;
1369 
1370  assert( scip != NULL );
1371  assert( conshdlr != NULL );
1372  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1373 
1374  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1375  assert( conshdlrdata != NULL );
1376 
1377  SCIPfreeBlockMemory(scip, &conshdlrdata);
1378 
1379  return SCIP_OKAY;
1380 }
1381 
1382 
1383 /** transforms constraint data into data belonging to the transformed problem */
1384 static
1385 SCIP_DECL_CONSTRANS(consTransSymresack)
1387  SCIP_CONSDATA* sourcedata;
1388  SCIP_CONSDATA* consdata = NULL;
1389  int nvars;
1390  int i;
1391 
1392  assert( scip != NULL );
1393  assert( conshdlr != NULL );
1394  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1395  assert( sourcecons != NULL );
1396  assert( targetcons != NULL );
1397 
1398  SCIPdebugMsg(scip, "Transforming constraint.\n");
1399 
1400  /* get data of original constraint */
1401  sourcedata = SCIPconsGetData(sourcecons);
1402  assert( sourcedata != NULL);
1403  assert( sourcedata->nvars != 0 );
1404  assert( sourcedata->vars != NULL );
1405  assert( sourcedata->perm != NULL );
1406  assert( sourcedata->invperm != NULL );
1407 #ifndef NDEBUG
1408  if ( sourcedata->ppupgrade )
1409  {
1410  assert( sourcedata->ncycles != 0 );
1411  assert( sourcedata->cycledecomposition != NULL );
1412  for (i = 0; i < sourcedata->ncycles; ++i)
1413  {
1414  assert( sourcedata->cycledecomposition[i] != NULL );
1415  assert( sourcedata->cycledecomposition[i][0] != 0 );
1416  }
1417  }
1418 #endif
1419 
1420  /* create transformed constraint data (copy data where necessary) */
1421  nvars = sourcedata->nvars;
1422 
1423  SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
1424 
1425 #ifdef SCIP_DEBUG
1426  consdata->debugcnt = sourcedata->debugcnt;
1427 #endif
1428  consdata->nvars = nvars;
1429 
1430  if ( nvars > 0 )
1431  {
1432  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, nvars) );
1433  SCIP_CALL( SCIPgetTransformedVars(scip, nvars, sourcedata->vars, consdata->vars) );
1434  for (i = 0; i < nvars; ++i)
1435  {
1436  SCIP_CALL( SCIPcaptureVar(scip, consdata->vars[i]) );
1437  }
1438 
1439  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->perm, sourcedata->perm, nvars) );
1440  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->invperm, sourcedata->invperm, nvars) );
1441 
1442  consdata->ppupgrade = sourcedata->ppupgrade;
1443 
1444  if ( sourcedata->ppupgrade )
1445  {
1446  consdata->ncycles = sourcedata->ncycles;
1447  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->cycledecomposition, sourcedata->cycledecomposition, sourcedata->ncycles) );
1448  for (i = 0; i < sourcedata->ncycles; ++i)
1449  {
1450  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &consdata->cycledecomposition[i], sourcedata->cycledecomposition[i], nvars + 1) ); /*lint !e866*/
1451  }
1452  }
1453  }
1454 
1455  /* create transformed constraint */
1456  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, consdata,
1457  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
1458  SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
1459  SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
1460  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
1461  SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1462 
1463  return SCIP_OKAY;
1464 }
1465 
1466 
1467 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1468 static
1469 SCIP_DECL_CONSINITLP(consInitlpSymresack)
1471  int c;
1472 
1473  assert( infeasible != NULL );
1474  *infeasible = FALSE;
1475 
1476  assert( scip != NULL );
1477  assert( conshdlr != NULL );
1478  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1479 
1480  /* loop through constraints */
1481  for (c = 0; c < nconss; ++c)
1482  {
1483  assert( conss[c] != NULL );
1484 
1485  SCIPdebugMsg(scip, "Generating initial symresack cut for constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1486 
1487  SCIP_CALL( initLP(scip, conss[c], infeasible) );
1488  if ( *infeasible )
1489  break;
1490  }
1491  SCIPdebugMsg(scip, "Generated initial symresack cuts.\n");
1492 
1493  return SCIP_OKAY;
1494 }
1495 
1496 
1497 /** separation method of constraint handler for LP solution */
1498 static
1499 SCIP_DECL_CONSSEPALP(consSepalpSymresack)
1500 { /*lint --e{715}*/
1501  SCIP_CONSDATA* consdata;
1502  SCIP_Real* vals;
1503  int ntotalvars;
1504  int c;
1505 
1506  assert( scip != NULL );
1507  assert( conshdlr != NULL );
1508  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1509  assert( result != NULL );
1510 
1511  SCIPdebugMsg(scip, "Separation method for symresack constraints\n");
1512 
1513  *result = SCIP_DIDNOTRUN;
1514 
1515  /* if solution is not integer */
1516  if ( SCIPgetNLPBranchCands(scip) == 0 )
1517  return SCIP_OKAY;
1518 
1519  if ( nconss == 0 )
1520  return SCIP_OKAY;
1521 
1522  ntotalvars = SCIPgetNVars(scip);
1523  SCIP_CALL( SCIPallocBufferArray(scip, &vals, ntotalvars) );
1524 
1525  /* loop through constraints */
1526  for (c = 0; c < nconss; ++c)
1527  {
1528  SCIP_Bool infeasible = FALSE;
1529  int ngen = 0;
1530 
1531  SCIPdebugMsg(scip, "Separating symresack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1532 
1533  /* get data of constraint */
1534  assert( conss[c] != NULL );
1535  consdata = SCIPconsGetData(conss[c]);
1536 
1537  /* get solution */
1538  assert( consdata->nvars <= ntotalvars );
1539  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nvars, consdata->vars, vals) );
1540  SCIP_CALL( separateSymresackCovers(scip, conss[c], consdata, vals, &ngen, &infeasible) );
1541 
1542  if ( infeasible )
1543  {
1544  *result = SCIP_CUTOFF;
1545  SCIPfreeBufferArray(scip, &vals);
1546 
1547  return SCIP_OKAY;
1548  }
1549 
1550  if ( ngen > 0 )
1551  *result = SCIP_SEPARATED;
1552 
1553  if ( *result == SCIP_DIDNOTRUN )
1554  *result = SCIP_DIDNOTFIND;
1555  }
1556  SCIPfreeBufferArray(scip, &vals);
1557 
1558  return SCIP_OKAY;
1559 }
1560 
1561 
1562 /** separation method of constraint handler for arbitrary primal solution */
1563 static
1564 SCIP_DECL_CONSSEPASOL(consSepasolSymresack)
1565 { /*lint --e{715}*/
1566  SCIP_CONSDATA* consdata;
1567  SCIP_Real* vals;
1568  int ntotalvars;
1569  int c;
1570 
1571  assert( scip != NULL );
1572  assert( conshdlr != NULL );
1573  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1574  assert( result != NULL );
1575 
1576  SCIPdebugMsg(scip, "Separation method for symresack constraints\n");
1577 
1578  *result = SCIP_DIDNOTRUN;
1579 
1580  if ( nconss == 0 )
1581  return SCIP_OKAY;
1582 
1583  ntotalvars = SCIPgetNVars(scip);
1584  SCIP_CALL( SCIPallocBufferArray(scip, &vals, ntotalvars) );
1585 
1586  /* loop through constraints */
1587  for (c = 0; c < nconss; ++c)
1588  {
1589  SCIP_Bool infeasible = FALSE;
1590  int ngen = 0;
1591 
1592  SCIPdebugMsg(scip, "Separating symresack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1593 
1594  /* get data of constraint */
1595  assert( conss[c] != NULL );
1596  consdata = SCIPconsGetData(conss[c]);
1597 
1598  /* get solution */
1599  assert( consdata->nvars <= ntotalvars );
1600  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nvars, consdata->vars, vals) );
1601  SCIP_CALL( separateSymresackCovers(scip, conss[c], consdata, vals, &ngen, &infeasible) );
1602 
1603 
1604  if ( infeasible )
1605  {
1606  *result = SCIP_CUTOFF;
1607  SCIPfreeBufferArray(scip, &vals);
1608 
1609  return SCIP_OKAY;
1610  }
1611 
1612  if ( ngen > 0 )
1613  *result = SCIP_SEPARATED;
1614 
1615  if ( *result == SCIP_DIDNOTRUN )
1616  *result = SCIP_DIDNOTFIND;
1617  }
1618  SCIPfreeBufferArray(scip, &vals);
1619 
1620  return SCIP_OKAY;
1621 }
1622 
1623 
1624 /** constraint enforcing method of constraint handler for LP solutions.
1625  *
1626  * To check feasibility, we separate cover inequalities.
1627  *
1628  * @pre It is assumed that the solution is integral (this can be ensured by appropriate priorities).
1629  */
1630 static
1631 SCIP_DECL_CONSENFOLP(consEnfolpSymresack)
1632 { /*lint --e{715}*/
1633  SCIP_CONSDATA* consdata;
1634  int c;
1635 
1636  assert( scip != NULL );
1637  assert( conshdlr != NULL );
1638  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1639  assert( result != NULL );
1640 
1641  SCIPdebugMsg(scip, "Enforcing method for symresack constraints (lp solutions) ...\n");
1642 
1643  /* we have a negative priority, so we should come after the integrality conshdlr. */
1644  assert( SCIPgetNLPBranchCands(scip) == 0 );
1645 
1646  *result = SCIP_FEASIBLE;
1647 
1648  if ( nconss > 0 )
1649  {
1650  SCIP_Real* vals;
1651  int ntotalvars;
1652 
1653  ntotalvars = SCIPgetNVars(scip);
1654  SCIP_CALL( SCIPallocBufferArray(scip, &vals, ntotalvars) );
1655 
1656  /* loop through constraints */
1657  for (c = 0; c < nconss; ++c)
1658  {
1659  SCIP_Bool infeasible = FALSE;
1660  int ngen = 0;
1661 
1662  SCIPdebugMsg(scip, "Enforcing symresack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1663 
1664  /* get data of constraint */
1665  assert( conss[c] != NULL );
1666  consdata = SCIPconsGetData(conss[c]);
1667 
1668  /* get solution */
1669  assert( consdata->nvars <= ntotalvars );
1670  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nvars, consdata->vars, vals) );
1671  SCIP_CALL( separateSymresackCovers(scip, conss[c], consdata, vals, &ngen, &infeasible) );
1672 
1673  if ( infeasible )
1674  {
1675  *result = SCIP_CUTOFF;
1676  SCIPfreeBufferArray(scip, &vals);
1677 
1678  return SCIP_OKAY;
1679  }
1680 
1681  /* SCIPdebugMsg(scip, "Generated symresack inequalities for <%s>: %d\n", SCIPconsGetName(conss[c]), ngen); */
1682 
1683  if ( ngen > 0 )
1684  *result = SCIP_SEPARATED;
1685  }
1686  SCIPfreeBufferArray(scip, &vals);
1687  }
1688 
1689  return SCIP_OKAY;
1690 }
1691 
1692 
1693 /** constraint enforcing method of constraint handler for pseudo solutions */
1694 static
1695 SCIP_DECL_CONSENFOPS(consEnfopsSymresack)
1696 { /*lint --e{715}*/
1697  int c;
1698 
1699  assert( scip != NULL );
1700  assert( conshdlr != NULL );
1701  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1702  assert( result != NULL );
1703 
1704  SCIPdebugMsg(scip, "Enforcing method for symresack constraints (pseudo solutions) ...\n");
1705 
1706  *result = SCIP_FEASIBLE;
1707 
1708  if ( objinfeasible || solinfeasible )
1709  return SCIP_OKAY;
1710 
1711  /* loop through constraints */
1712  for (c = 0; c < nconss; ++c)
1713  {
1714  SCIP_CALL( checkSymresackSolution(scip, conss[c], NULL, result, FALSE) );
1715 
1716  if ( *result == SCIP_INFEASIBLE )
1717  break;
1718  }
1719 
1720  return SCIP_OKAY;
1721 }
1722 
1723 
1724 /** constraint enforcing method of constraint handler for relaxation solutions
1725  *
1726  * To check feasibility, we separate cover inequalities.
1727  *
1728  */
1729 static
1730 SCIP_DECL_CONSENFORELAX(consEnforelaxSymresack)
1731 { /*lint --e{715}*/
1732  SCIP_CONSDATA* consdata;
1733  int c;
1734 
1735  assert( scip != NULL );
1736  assert( conshdlr != NULL );
1737  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1738  assert( result != NULL );
1739 
1740  SCIPdebugMsg(scip, "Enforcing method for symresack constraints (relaxation solutions) ...\n");
1741 
1742  /* we have a negative priority, so we should come after the integrality conshdlr. */
1743  assert( SCIPgetNLPBranchCands(scip) == 0 );
1744 
1745  *result = SCIP_FEASIBLE;
1746 
1747  if ( nconss > 0 )
1748  {
1749  SCIP_Real* vals;
1750  int ntotalvars;
1751 
1752  ntotalvars = SCIPgetNVars(scip);
1753  SCIP_CALL( SCIPallocBufferArray(scip, &vals, ntotalvars) );
1754 
1755  /* loop through constraints */
1756  for (c = 0; c < nconss; ++c)
1757  {
1758  SCIP_Bool infeasible = FALSE;
1759  int ngen = 0;
1760 
1761  SCIPdebugMsg(scip, "Enforcing symresack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1762 
1763  /* get data of constraint */
1764  assert( conss[c] != NULL );
1765  consdata = SCIPconsGetData(conss[c]);
1766 
1767  /* get solution */
1768  assert( consdata->nvars <= ntotalvars );
1769  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nvars, consdata->vars, vals) );
1770  SCIP_CALL( separateSymresackCovers(scip, conss[c], consdata, vals, &ngen, &infeasible) );
1771 
1772  if ( infeasible )
1773  {
1774  *result = SCIP_CUTOFF;
1775  SCIPfreeBufferArray(scip, &vals);
1776 
1777  return SCIP_OKAY;
1778  }
1779 
1780  if ( ngen > 0 )
1781  *result = SCIP_SEPARATED;
1782  }
1783  SCIPfreeBufferArray(scip, &vals);
1784  }
1785 
1786  return SCIP_OKAY;
1787 }
1788 
1789 
1790 /** feasibility check method of constraint handler for integral solutions */
1791 static
1792 SCIP_DECL_CONSCHECK(consCheckSymresack)
1793 { /*lint --e{715}*/
1794  int c;
1795  SCIP_CONSHDLRDATA* conshdlrdata;
1796 
1797  assert( scip != NULL );
1798  assert( conshdlr != NULL );
1799  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1800  assert( result != NULL );
1801 
1802  *result = SCIP_FEASIBLE;
1803 
1804  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1805  assert( conshdlrdata != NULL );
1806 
1807  if ( conshdlrdata->checkalwaysfeas )
1808  return SCIP_OKAY;
1809 
1810  /* loop through constraints */
1811  for (c = 0; c < nconss; ++c)
1812  {
1813  SCIP_CALL( checkSymresackSolution(scip, conss[c], sol, result, printreason) );
1814 
1815  if ( *result == SCIP_INFEASIBLE )
1816  break;
1817  }
1818 
1819  if ( *result == SCIP_FEASIBLE )
1820  SCIPdebugMsg(scip, "Solution is feasible.\n");
1821 
1822  return SCIP_OKAY;
1823 }
1824 
1825 
1826 /** domain propagation method of constraint handler */
1827 static
1828 SCIP_DECL_CONSPROP(consPropSymresack)
1829 { /*lint --e{715}*/
1830  int c;
1831  SCIP_Bool success = FALSE;
1832 
1833  assert( scip != NULL );
1834  assert( conshdlr != NULL );
1835  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1836  assert( result != NULL );
1837 
1838  *result = SCIP_DIDNOTRUN;
1839 
1840  SCIPdebugMsg(scip, "Propagation method of symresack constraint handler.\n");
1841 
1842  /* loop through constraints */
1843  for (c = 0; c < nconss; ++c)
1844  {
1845  SCIP_Bool infeasible = FALSE;
1846  int ngen = 0;
1847 
1848  assert( conss[c] != NULL );
1849 
1850  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &ngen) );
1851 
1852  if ( infeasible )
1853  {
1854  *result = SCIP_CUTOFF;
1855  return SCIP_OKAY;
1856  }
1857 
1858  success = success || ( ngen > 0 );
1859 
1860  *result = SCIP_DIDNOTFIND;
1861  }
1862 
1863  if ( success )
1864  {
1865  *result = SCIP_REDUCEDDOM;
1866  return SCIP_OKAY;
1867  }
1868 
1869  return SCIP_OKAY;
1870 }
1871 
1872 
1873 /** presolving method of constraint handler */
1874 static
1875 SCIP_DECL_CONSPRESOL(consPresolSymresack)
1876 { /*lint --e{715}*/
1877  int c;
1878  SCIP_Bool success = FALSE;
1879  int oldndelconss;
1880 
1881  assert( scip != NULL );
1882  assert( conshdlr != NULL );
1883  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1884  assert( result != NULL );
1885 
1886  oldndelconss = *ndelconss;
1887 
1888  SCIPdebugMsg(scip, "Presolving method of symresack constraint handler. Propagating symresack inequalities.\n");
1889  *result = SCIP_DIDNOTRUN;
1890 
1891  /* loop through constraints */
1892  for (c = 0; c < nconss; ++c)
1893  {
1894  SCIP_Bool infeasible = FALSE;
1895  SCIP_CONSDATA* consdata;
1896  int ngen = 0;
1897 
1898  assert( conss[c] != NULL );
1899 
1900  consdata = SCIPconsGetData(conss[c]);
1901  assert( consdata != NULL );
1902 
1903  /* avoid trivial problems */
1904  if ( consdata->nvars == 0 )
1905  {
1906  SCIP_CALL( SCIPdelCons(scip, conss[c]) );
1907  (*ndelconss)++;
1908  }
1909  else
1910  {
1911  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &ngen) );
1912  }
1913 
1914  if ( infeasible )
1915  {
1916  *result = SCIP_CUTOFF;
1917  break;
1918  }
1919 
1920  if ( ngen > 0 )
1921  {
1922  *nfixedvars += ngen;
1923  success = TRUE;
1924  }
1925 
1926  *result = SCIP_DIDNOTFIND;
1927  }
1928 
1929  if ( *ndelconss > oldndelconss || success )
1930  *result = SCIP_SUCCESS;
1931 
1932  return SCIP_OKAY;
1933 }
1934 
1935 
1936 /** Propagation resolution for conflict analysis */
1937 static
1938 SCIP_DECL_CONSRESPROP(consRespropSymresack)
1939 { /*lint --e{715}*/
1940  SCIP_CONSDATA* consdata;
1941  SCIP_VAR** vars;
1942  int* invperm;
1943  int nvars;
1944  int i;
1945 
1946  assert( scip != NULL );
1947  assert( conshdlr != NULL );
1948  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1949  assert( cons != NULL );
1950  assert( infervar != NULL );
1951  assert( bdchgidx != NULL );
1952  assert( result != NULL );
1953 
1954  SCIPdebugMsg(scip, "Propagation resolution method of symresack constraint handler.\n");
1955 
1956  *result = SCIP_DIDNOTFIND;
1957 
1958  consdata = SCIPconsGetData(cons);
1959  assert( consdata != NULL );
1960 
1961  /* we don't have to take care of trivial constraints */
1962  if ( consdata->nvars < 2 )
1963  return SCIP_OKAY;
1964 
1965  assert( consdata->vars != NULL );
1966  assert( consdata->invperm != NULL );
1967 
1968  vars = consdata->vars;
1969  nvars = consdata->nvars;
1970  invperm = consdata->invperm;
1971 
1972  assert( 0 <= inferinfo && inferinfo < (2 * nvars - 1) );
1973 
1974  /* if first part of variable pair was fixed to 0 */
1975  if ( inferinfo < nvars )
1976  {
1977  assert( vars[invperm[inferinfo]] == infervar );
1978  assert( SCIPvarGetUbAtIndex(vars[invperm[inferinfo]], bdchgidx, FALSE) > 0.5
1979  && SCIPvarGetUbAtIndex(vars[invperm[inferinfo]], bdchgidx, TRUE) < 0.5 );
1980 
1981  if ( SCIPvarGetUbAtIndex(vars[invperm[inferinfo]], bdchgidx, FALSE) > 0.5
1982  && SCIPvarGetUbAtIndex(vars[invperm[inferinfo]], bdchgidx, TRUE) < 0.5 )
1983  {
1984  SCIPdebugMsg(scip, " -> reason for setting x[%d] = 0 was fixing x[%d] to 0 ", invperm[inferinfo], inferinfo);
1985  SCIPdebugMsg(scip, "and each pair of binary variables before (%d,%d) which are not fixed points is constant.\n",
1986  inferinfo, invperm[inferinfo]);
1987 
1988  SCIP_CALL( SCIPaddConflictUb(scip, vars[inferinfo], bdchgidx) );
1989 
1990  for (i = 0; i < inferinfo; ++i)
1991  {
1992  /* there are no fixed points */
1993  assert( invperm[i] != i );
1994 
1995  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
1996  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
1997  SCIP_CALL( SCIPaddConflictUb(scip, vars[invperm[i]], bdchgidx) );
1998  SCIP_CALL( SCIPaddConflictLb(scip, vars[invperm[i]], bdchgidx) );
1999  }
2000  }
2001  }
2002  /* if second part of variable pair was fixed to 1 */
2003  else
2004  {
2005  int inferinfo2;
2006 
2007  inferinfo2 = inferinfo - nvars;
2008  assert( vars[inferinfo2] == infervar );
2009  assert( SCIPvarGetLbAtIndex(vars[inferinfo2], bdchgidx, FALSE) < 0.5
2010  && SCIPvarGetLbAtIndex(vars[inferinfo2], bdchgidx, TRUE) > 0.5 );
2011 
2012  if ( SCIPvarGetLbAtIndex(vars[inferinfo2], bdchgidx, FALSE) < 0.5
2013  && SCIPvarGetLbAtIndex(vars[inferinfo2], bdchgidx, TRUE) > 0.5 )
2014  {
2015  SCIPdebugMsg(scip, " -> reason for setting x[%d] = 1 was fixing x[%d] to 1 ", inferinfo2, invperm[inferinfo2]);
2016  SCIPdebugMsg(scip, "and each pair of binary variables before (%d,%d) which are not fixed points is constant.\n",
2017  inferinfo2, invperm[inferinfo2]);
2018 
2019  SCIP_CALL( SCIPaddConflictLb(scip, vars[invperm[inferinfo2]], bdchgidx) );
2020 
2021  for (i = 0; i < inferinfo2; ++i)
2022  {
2023  /* there are no fixed points */
2024  assert( invperm[i] != i );
2025 
2026  SCIP_CALL( SCIPaddConflictUb(scip, vars[i], bdchgidx) );
2027  SCIP_CALL( SCIPaddConflictLb(scip, vars[i], bdchgidx) );
2028  SCIP_CALL( SCIPaddConflictUb(scip, vars[invperm[i]], bdchgidx) );
2029  SCIP_CALL( SCIPaddConflictLb(scip, vars[invperm[i]], bdchgidx) );
2030  }
2031  }
2032  }
2033 
2034  *result = SCIP_SUCCESS;
2035 
2036  return SCIP_OKAY;
2037 }
2038 
2039 
2040 /** lock variables
2041  *
2042  * We assume we have only one global (void) constraint and lock all binary variables
2043  * which do not correspond to fixed points of the permutation.
2044  *
2045  * - Symresack constraints may get violated if the variables with a negative coefficient
2046  * in the FD inequality are rounded down, we therefor call
2047  * SCIPaddVarLocks(..., nlockspos, nlocksneg).
2048  * - Symresack constraints may get violated if the variables with a positive coefficient
2049  * in the FD inequality are rounded up, we therefor call
2050  * SCIPaddVarLocks(..., nlocksneg, nlockspo ).
2051  */
2052 static
2053 SCIP_DECL_CONSLOCK(consLockSymresack)
2054 { /*lint --e{715}*/
2055  SCIP_CONSDATA* consdata;
2056  SCIP_VAR** vars;
2057  int* perm;
2058  int nvars;
2059  int i;
2060 
2061  assert( scip != NULL );
2062  assert( conshdlr != NULL );
2063  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2064  assert( cons != NULL );
2065 
2066  SCIPdebugMsg(scip, "Locking method for symresack constraint handler.\n");
2067 
2068  /* get data of original constraint */
2069  consdata = SCIPconsGetData(cons);
2070  assert( consdata != NULL );
2071 
2072  /* we don't have to take care of trivial constraints */
2073  if ( consdata->nvars < 2 )
2074  return SCIP_OKAY;
2075 
2076  assert( consdata->vars != NULL );
2077  assert( consdata->perm != NULL );
2078 
2079  nvars = consdata->nvars;
2080  vars = consdata->vars;
2081  perm = consdata->perm;
2082 
2083  for (i = 0; i < nvars; ++i)
2084  {
2085  /* due to clean-up in consdataCreate, there are no fixed points */
2086  assert( perm[i] != i );
2087 
2088  if ( perm[i] > i )
2089  {
2090  SCIP_CALL( SCIPaddVarLocks(scip, vars[i], nlockspos, nlocksneg) );
2091  }
2092  else
2093  {
2094  SCIP_CALL( SCIPaddVarLocks(scip, vars[i], nlocksneg, nlockspos) );
2095  }
2096  }
2097 
2098  return SCIP_OKAY;
2099 }
2100 
2101 
2102 /** constraint display method of constraint handler
2103  *
2104  * The constraint handler should output a representation of the constraint into the given text file.
2105  */
2106 static
2107 SCIP_DECL_CONSPRINT(consPrintSymresack)
2108 { /*lint --e{715}*/
2109 
2110  SCIP_CONSDATA* consdata;
2111  SCIP_VAR** vars;
2112  SCIP_Bool* covered;
2113  int* perm;
2114  int nvars;
2115  int i;
2116  int j;
2117 
2118  assert( scip != NULL );
2119  assert( conshdlr != NULL );
2120  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2121  assert( cons != NULL );
2122 
2123  consdata = SCIPconsGetData(cons);
2124  assert( consdata != NULL );
2125 
2126  SCIPdebugMsg(scip, "Printing method for symresack constraint handler\n");
2127 
2128  /* we don't have to take care of trivial constraints */
2129  if ( consdata->nvars < 2 )
2130  {
2131  SCIPinfoMessage(scip, file, "symresack()");
2132  return SCIP_OKAY;
2133  }
2134 
2135  assert( consdata->vars != NULL );
2136  assert( consdata->perm != NULL );
2137 
2138  vars = consdata->vars;
2139  nvars = consdata->nvars;
2140  perm = consdata->perm;
2141 
2142  SCIP_CALL( SCIPallocBufferArray(scip, &covered, nvars) );
2143  for (i = 0; i < nvars; ++i)
2144  covered[i] = FALSE;
2145 
2146  if ( consdata->ppupgrade )
2147  SCIPinfoMessage(scip, file, "ppSymresack(");
2148  else
2149  SCIPinfoMessage(scip, file, "symresack(");
2150 
2151  for (i = 0; i < nvars; ++i)
2152  {
2153  if ( covered[i] )
2154  continue;
2155 
2156  /* print cycle of perm containing i */
2157  SCIPinfoMessage(scip, file, "[%s", SCIPvarGetName(vars[i]));
2158  covered[i] = TRUE;
2159  j = perm[i];
2160  while ( j != i )
2161  {
2162  SCIPinfoMessage(scip, file, ",%s", SCIPvarGetName(vars[j]));
2163  covered[j] = TRUE;
2164  j = perm[j];
2165  }
2166  SCIPinfoMessage(scip, file, "]");
2167  }
2168  SCIPinfoMessage(scip, file, ")");
2169 
2170  SCIPfreeBufferArray(scip, &covered);
2171 
2172  return SCIP_OKAY;
2173 }
2174 
2175 
2176 /** constraint method of constraint handler which returns the variables (if possible) */
2177 static
2178 SCIP_DECL_CONSGETVARS(consGetVarsSymresack)
2179 { /*lint --e{715}*/
2180  SCIP_CONSDATA* consdata;
2181 
2182  assert( cons != NULL );
2183  assert( success != NULL );
2184  assert( vars != NULL );
2185 
2186  consdata = SCIPconsGetData(cons);
2187  assert( consdata != NULL );
2188 
2189  if ( varssize < consdata->nvars )
2190  (*success) = FALSE;
2191  else
2192  {
2193  int cnt = 0;
2194  int i;
2195 
2196  for (i = 0; i < consdata->nvars; ++i)
2197  vars[cnt++] = consdata->vars[i];
2198  (*success) = TRUE;
2199  }
2200 
2201  return SCIP_OKAY;
2202 }
2203 
2204 
2205 /** constraint method of constraint handler which returns the number of variables (if possible) */
2206 static
2207 SCIP_DECL_CONSGETNVARS(consGetNVarsSymresack)
2208 { /*lint --e{715}*/
2209  SCIP_CONSDATA* consdata;
2210 
2211  assert( cons != NULL );
2212  assert( success != NULL );
2213  assert( nvars != NULL );
2214 
2215  consdata = SCIPconsGetData(cons);
2216  assert( consdata != NULL );
2217 
2218  (*nvars) = consdata->nvars;
2219  (*success) = TRUE;
2220 
2221  return SCIP_OKAY;
2222 }
2223 
2224 
2225 /** creates the handler for symresack constraints and includes it in SCIP */
2227  SCIP* scip /**< SCIP data structure */
2228  )
2229 {
2230  SCIP_CONSHDLRDATA* conshdlrdata = NULL;
2231  SCIP_CONSHDLR* conshdlr;
2232 
2233  SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
2234 
2235  /* include constraint handler */
2238  consEnfolpSymresack, consEnfopsSymresack, consCheckSymresack, consLockSymresack,
2239  conshdlrdata) );
2240  assert( conshdlr != NULL );
2241 
2242  /* set non-fundamental callbacks via specific setter functions */
2243  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxSymresack) );
2244  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeSymresack) );
2245  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteSymresack) );
2246  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsSymresack) );
2247  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsSymresack) );
2248  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolSymresack, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
2249  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintSymresack) );
2251  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropSymresack) );
2252  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpSymresack, consSepasolSymresack, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
2253  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransSymresack) );
2254  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpSymresack) );
2255 
2256  /* whether we allow upgrading to packing/partioning symresack constraints*/
2257  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/ppsymresack",
2258  "Upgrade symresack constraints to packing/partioning symresacks?",
2259  &conshdlrdata->checkppsymresack, TRUE, DEFAULT_PPSYMRESACK, NULL, NULL) );
2260 
2261  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/checkalwaysfeas",
2262  "Whether check routine returns always SCIP_FEASIBLE.",
2263  &conshdlrdata->checkalwaysfeas, TRUE, DEFAULT_CHECKALWAYSFEAS, NULL, NULL) );
2264 
2265  return SCIP_OKAY;
2266 }
2267 
2268 
2269 /*
2270  * constraint specific interface methods
2271  */
2272 
2273 /** creates and captures a symresack constraint
2274  *
2275  * In a presolving step, we check whether the permutation acts only on binary points. Otherwise, we eliminate
2276  * the non-binary variables from the permutation.
2277  *
2278  * @note The constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons().
2279  */
2281  SCIP* scip, /**< SCIP data structure */
2282  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2283  const char* name, /**< name of constraint */
2284  int* perm, /**< permutation */
2285  SCIP_VAR** vars, /**< variables */
2286  int nvars, /**< number of variables in vars array */
2287  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2288  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2289  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2290  * Usually set to TRUE. */
2291  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2292  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2293  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2294  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2295  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2296  * Usually set to TRUE. */
2297  SCIP_Bool local, /**< is constraint only valid locally?
2298  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2299  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2300  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2301  * adds coefficients to this constraint. */
2302  SCIP_Bool dynamic, /**< is constraint subject to aging?
2303  * Usually set to FALSE. Set to TRUE for own cuts which
2304  * are separated as constraints. */
2305  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2306  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2307  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2308  * if it may be moved to a more global node?
2309  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2310  )
2311 {
2312  SCIP_CONSHDLR* conshdlr;
2313  SCIP_CONSDATA* consdata;
2314 
2315  assert( cons != NULL );
2316  assert( nvars > 0 );
2317 
2318  /* find the symresack constraint handler */
2319  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2320  if ( conshdlr == NULL )
2321  {
2322  SCIPerrorMessage("Symresack constraint handler not found.\n");
2323  return SCIP_PLUGINNOTFOUND;
2324  }
2325 
2326  /* create constraint data */
2327  SCIP_CALL( consdataCreate(scip, &consdata, vars, nvars, perm) );
2328 
2329  /* create constraint */
2330  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate && (! consdata->ppupgrade), enforce, check, propagate,
2331  local, modifiable, dynamic, removable, stickingatnode) );
2332 
2333  return SCIP_OKAY;
2334 }
2335 
2336 
2337 /** creates and captures a symresack constraint
2338  * in its most basic variant, i.e., with all constraint flags set to their default values
2339  *
2340  * In a presolving step, we remove all fixed points and cycles that act on non-binary variables of the permutation
2341  *
2342  * @note The constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons().
2343  */
2345  SCIP* scip, /**< SCIP data structure */
2346  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2347  const char* name, /**< name of constraint */
2348  int* perm, /**< permutation */
2349  SCIP_VAR** vars, /**< variables */
2350  int nvars /**< number of variables in vars array */
2351  )
2352 {
2353  SCIP_CALL( SCIPcreateConsSymresack(scip, cons, name, perm, vars, nvars,
2355 
2356  return SCIP_OKAY;
2357 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:6291
#define CONSHDLR_ENFOPRIORITY
#define CONSHDLR_PRESOLTIMING
SCIP_RETCODE SCIPcreateConsBasicSymresack(SCIP *scip, SCIP_CONS **cons, const char *name, int *perm, SCIP_VAR **vars, int nvars)
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
static SCIP_DECL_CONSPROP(consPropSymresack)
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30613
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8245
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:6314
SCIP_RETCODE SCIPcreateSymbreakCons(SCIP *scip, SCIP_CONS **cons, const char *name, int *perm, SCIP_VAR **vars, int nvars, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_DECL_CONSFREE(consFreeSymresack)
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip.c:30636
int SCIPgetNVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9230
#define CONSHDLR_NAME
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:6544
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip.c:6036
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12663
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:30668
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
static SCIP_DECL_CONSENFORELAX(consEnforelaxSymresack)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:27388
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip.c:18957
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18766
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
SCIP_CONS ** SCIPconshdlrGetConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4485
#define FALSE
Definition: def.h:64
#define CONSHDLR_PROPFREQ
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5894
constraint handler for orbisack constraints
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27251
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:21660
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8265
static SCIP_RETCODE checkSymresackSolution(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_RESULT *result, SCIP_Bool printreason)
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
#define CONSHDLR_MAXPREROUNDS
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
Definition: scip.c:27155
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5948
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
static SCIP_DECL_CONSPRESOL(consPresolSymresack)
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:37034
#define DEFAULT_CHECKALWAYSFEAS
static SCIP_DECL_CONSGETNVARS(consGetNVarsSymresack)
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8255
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip.c:6337
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:18998
static SCIP_RETCODE separateSymresackCovers(SCIP *scip, SCIP_CONS *cons, const SCIP_CONSDATA *consdata, SCIP_Real *vals, int *ngen, SCIP_Bool *infeasible)
static SCIP_DECL_CONSINITLP(consInitlpSymresack)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:27584
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:27184
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 initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_DECL_CONSPRINT(consPrintSymresack)
#define CONSHDLR_NEEDSCONS
SCIP_RETCODE SCIPcreateConsSymresack(SCIP *scip, SCIP_CONS **cons, const char *name, int *perm, SCIP_VAR **vars, int nvars, 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_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:27133
constraint handler for symresack constraints
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:22599
static SCIP_RETCODE addSymresackInequality(SCIP *scip, SCIP_CONS *cons, int nvars, SCIP_VAR **vars, int *coeffs, SCIP_Real rhs, SCIP_Bool *infeasible)
static SCIP_DECL_CONSSEPALP(consSepalpSymresack)
#define CONSHDLR_EAGERFREQ
SCIP_RETCODE SCIPincludeConshdlrSymresack(SCIP *scip)
#define SCIPerrorMessage
Definition: pub_message.h:45
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4113
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38948
static SCIP_DECL_CONSENFOLP(consEnfolpSymresack)
#define SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip.h:22633
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip.c:34546
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16071
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
static SCIP_DECL_CONSLOCK(consLockSymresack)
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:25932
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8205
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip.c:6085
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4133
static SCIP_DECL_CONSDELETE(consDeleteSymresack)
#define CONSHDLR_SEPAFREQ
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:27535
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8225
static SCIP_DECL_CONSSEPASOL(consSepasolSymresack)
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:34661
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:6360
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
int SCIPconshdlrGetNConss(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4515
static SCIP_RETCODE packingUpgrade(SCIP *scip, SCIP_CONSDATA **consdata, int *perm, SCIP_VAR **vars, int nvars, SCIP_Bool *upgrade)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:30402
SCIP_SETPPCTYPE SCIPgetTypeSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9272
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15947
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8006
static SCIP_DECL_CONSRESPROP(consRespropSymresack)
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8185
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8155
static SCIP_DECL_CONSCHECK(consCheckSymresack)
static SCIP_RETCODE initLP(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:6498
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22819
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR *const *inputvars, int inputnvars, int *inputperm)
SCIP_VAR ** SCIPgetVarsSetppc(SCIP *scip, SCIP_CONS *cons)
Definition: cons_setppc.c:9251
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
#define CONSHDLR_DELAYSEPA
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:30540
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
#define CONSHDLR_PROP_TIMING
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8016
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:22932
static SCIP_RETCODE orbisackUpgrade(SCIP *scip, SCIP_CONS **cons, const char *name, int *perm, SCIP_VAR **inputvars, int nvars, SCIP_Bool *upgrade, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
static SCIP_DECL_CONSGETVARS(consGetVarsSymresack)
#define DEFAULT_PPSYMRESACK
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:6253
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18732
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8235
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:30694
#define CONSHDLR_CHECKPRIORITY
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:6567
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8175
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8165
#define CONSHDLR_DESC
static SCIP_DECL_CONSENFOPS(consEnfopsSymresack)
#define CONSHDLR_SEPAPRIORITY
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:22605
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
#define CONSHDLR_DELAYPROP
static SCIP_RETCODE propVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, int *ngen)
#define ISFIXED0(x)
static SCIP_DECL_CONSTRANS(consTransSymresack)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
#define ISFIXED1(x)
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16817
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5994