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