Scippy

SCIP

Solving Constraint Integer Programs

cons_orbitope.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-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file cons_orbitope.c
17  * @brief constraint handler for (partitioning/packing) orbitope constraints w.r.t. the full symmetric group
18  * @author Timo Berthold
19  * @author Marc Pfetsch
20  *
21  * The type of constraints of this constraint handler is described in cons_orbitope.h.
22  *
23  * The details of the method implemented here are described in the following papers.
24  *
25  * Packing and Partitioning Orbitopes@n
26  * Volker Kaibel and Marc E. Pfetsch,@n
27  * Math. Program. 114, No. 1, 1-36 (2008)
28  *
29  * Among other things, this paper describes so-called shifted column inequalities of the following
30  * form \f$x(S) \leq x(B)\f$, where \f$S\f$ is a so-called shifted column and \f$B\f$ is a so-called
31  * bar. These inequalities can be used to handle symmetry and they are separated in this constraint
32  * handler. We use the linear time separation algorithm of the paper.@par
33  *
34  * Orbitopal Fixing@n
35  * Volker Kaibel, Matthias Peinhardt, and Marc E. Pfetsch,@n
36  * Discrete Optimization 8, No. 4, 595-610 (2011)
37  * (A preliminary version appears in Proc. IPCO 2007.)
38  *
39  * In this paper a linear time propagation algorithm is described, a variant of which is implemented
40  * here. The implemented variant does not run in linear time, but is very fast in practice.
41  *
42  * <table>
43  * <caption>translation table</caption>
44  * <tr><td>here</td><td>paper</td></tr>
45  * <tr><td></td><td></td></tr>
46  * <tr><td>nspcons </td><td>p </td></tr>
47  * <tr><td>nblocks </td><td>q </td></tr>
48  * <tr><td>vars </td><td>x </td></tr>
49  * <tr><td>vals </td><td>A^\\star</td></tr>
50  * <tr><td>weights </td><td>\\omega </td></tr>
51  * <tr><td>cases </td><td>\\tau </td></tr>
52  * <tr><td>fixtriangle </td><td>-- </td></tr>
53  * <tr><td>resolveprop </td><td>-- </td></tr>
54  * <tr><td>firstnonzeros</td><td>\\mu </td></tr>
55  * <tr><td>lastones </td><td>\\alpha </td></tr>
56  * <tr><td>frontiersteps</td><td>\\Gamma </td></tr>
57  * </table>
58  */
59 
60 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
61 
62 #include <assert.h>
63 #include <string.h>
64 #include <ctype.h>
65 
66 #include "scip/cons_orbitope.h"
67 
68 /* constraint handler properties */
69 #define CONSHDLR_NAME "orbitope"
70 #define CONSHDLR_DESC "symmetry breaking constraint handler relying on (partitioning/packing) orbitopes"
71 #define CONSHDLR_SEPAPRIORITY +40100 /**< priority of the constraint handler for separation */
72 #define CONSHDLR_ENFOPRIORITY -1005200 /**< priority of the constraint handler for constraint enforcing */
73 #define CONSHDLR_CHECKPRIORITY -1005200 /**< priority of the constraint handler for checking feasibility */
74 #define CONSHDLR_SEPAFREQ 5 /**< frequency for separating cuts; zero means to separate only in the root node */
75 #define CONSHDLR_PROPFREQ -1 /**< frequency for propagating domains; zero means only preprocessing propagation */
76 #define CONSHDLR_EAGERFREQ -1 /**< frequency for using all instead of only the useful constraints in separation,
77  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
78 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
79 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
80 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
81 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
82 
83 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
84 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
85 
86 
87 /*
88  * Data structures
89  */
90 
91 /** constraint data for orbitope constraints */
92 struct SCIP_ConsData
93 {
94  SCIP_VAR*** vars; /**< matrix of variables on which the symmetry acts */
95  SCIP_VAR** tmpvars; /**< temporary storage for variables */
96  SCIP_Real** vals; /**< LP-solution for those variables */
97  SCIP_Real* tmpvals; /**< temporary storage for values */
98  SCIP_Real** weights; /**< SC weight table */
99  int** cases; /**< indicator of the SC cases */
100  int nspcons; /**< number of set partitioning/packing constraints <=> p */
101  int nblocks; /**< number of symmetric variable blocks <=> q */
102  SCIP_Bool ispart; /**< whether we deal with the partitioning case (packing otherwise) */
103  SCIP_Bool resolveprop; /**< should propagation be resolved? */
104  SCIP_Bool istrianglefixed; /**< has the upper right triangle already globally been fixed to zero? */
105 };
106 
107 
108 /*
109  * Local methods
110  */
111 
112 /** frees an orbitope constraint data */
113 static
115  SCIP* scip, /**< SCIP data structure */
116  SCIP_CONSDATA** consdata /**< pointer to orbitope constraint data */
117  )
118 {
119  int i;
120  int p;
121  int q;
122 
123  assert( consdata != NULL );
124  assert( *consdata != NULL );
125 
126  p = (*consdata)->nspcons;
127  q = (*consdata)->nblocks;
128  for (i = 0; i < p; ++i)
129  {
130  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->cases[i]), q); /*lint !e866*/
131  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars[i]), q); /*lint !e866*/
132  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->weights[i]), q); /*lint !e866*/
133  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vals[i]), q); /*lint !e866*/
134  }
135 
136  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->cases), p);
137  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars), p);
138  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->weights), p);
139  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vals), p);
140 
141  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->tmpvals), p + q);
142  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->tmpvars), p + q);
143 
144  SCIPfreeBlockMemory(scip, consdata);
145 
146  return SCIP_OKAY;
147 }
148 
149 
150 /** creates orbitope constraint data */
151 static
153  SCIP* scip, /**< SCIP data structure */
154  SCIP_CONSDATA** consdata, /**< pointer to store constraint data */
155  SCIP_VAR*** vars, /**< variables array, must have size nspcons x nblocks */
156  int nspcons, /**< number of set partitioning (packing) constraints <=> p */
157  int nblocks, /**< number of symmetric variable blocks <=> q */
158  SCIP_Bool ispart, /**< deal with the partitioning case (packing otherwise) */
159  SCIP_Bool resolveprop /**< should propagation be resolved? */
160  )
161 {
162  int i;
163 
164  assert(consdata != NULL);
165 
166  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
167 
168  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->vals, nspcons) );
169  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->weights, nspcons) );
170  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->vars, nspcons) );
171  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->cases, nspcons) );
172 
173  for (i = 0; i < nspcons; ++i)
174  {
175  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->vals[i], nblocks) ); /*lint !e866*/
176  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->weights[i], nblocks) ); /*lint !e866*/
177  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars[i], vars[i], nblocks) ); /*lint !e866*/
178  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->cases[i], nblocks) ); /*lint !e866*/
179  }
180 
181  (*consdata)->tmpvals = NULL;
182  (*consdata)->tmpvars = NULL;
183  (*consdata)->nspcons = nspcons;
184  (*consdata)->nblocks = nblocks;
185  (*consdata)->ispart = ispart;
186  (*consdata)->resolveprop = resolveprop;
187  (*consdata)->istrianglefixed = FALSE;
188 
189  /* get transformed variables, if we are in the transformed problem */
190  if ( SCIPisTransformed(scip) )
191  {
192  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->tmpvals, nspcons + nblocks) );
193  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->tmpvars, nspcons + nblocks) );
194 
195  for (i = 0; i < nspcons; ++i)
196  {
197  SCIP_CALL( SCIPgetTransformedVars(scip, (*consdata)->nblocks, (*consdata)->vars[i], (*consdata)->vars[i]) );
198  }
199  }
200 
201  return SCIP_OKAY;
202 }
203 
204 
205 #ifdef PRINT_MATRIX
206 /** debug method, prints variable matrix */
207 static
208 void printMatrix(
209  SCIP* scip, /**< SCIP data structure */
210  SCIP_CONSDATA* consdata /**< the constraint data */
211  )
212 {
213  int i;
214  int j;
215 
216  assert( consdata != NULL );
217  assert( consdata->nspcons > 0 );
218  assert( consdata->nblocks > 0 );
219  assert( consdata->vars != NULL );
220 
221  for (j = 0; j < consdata->nblocks; ++j)
222  SCIPinfoMessage(scip, NULL, "-");
223 
224  SCIPinfoMessage(scip, NULL, "\n");
225  for (i = 0; i < consdata->nspcons; ++i)
226  {
227  for (j = 0; j < consdata->nblocks; ++j)
228  {
229  if ( SCIPvarGetUbLocal(consdata->vars[i][j]) - SCIPvarGetLbLocal(consdata->vars[i][j]) < 0.5 )
230  SCIPinfoMessage(scip, NULL, "%1.0f", REALABS(SCIPvarGetUbLocal(consdata->vars[i][j])));
231  else
232  SCIPinfoMessage(scip, NULL, " ");
233  }
234  SCIPinfoMessage(scip, NULL, "|\n");
235  }
236  for (j = 0; j < consdata->nblocks; ++j)
237  SCIPinfoMessage(scip, NULL, "-");
238  SCIPinfoMessage(scip, NULL, "\n");
239 }
240 #endif
241 
242 
243 #ifdef SHOW_SCI
244 /** Print SCI in nice form for debugging */
245 static
246 SCIP_RETCODE printSCI(
247  SCIP* scip, /**< SCIP pointer */
248  int p, /**< number of rows */
249  int q, /**< number of columns */
250  int** cases, /**< SCI dynamic programming table */
251  int i, /**< row position of bar */
252  int j /**< column position of bar */
253  )
254 {
255  int k;
256  int l;
257  int** M;
258  int p1;
259  int p2;
260 
261  SCIP_CALL( SCIPallocBufferArray(scip, &M, p) );
262  for (k = 0; k < p; ++k)
263  {
264  SCIP_CALL( SCIPallocBufferArray(scip, &M[k], q) ); /*lint !e866*/
265  for (l = 0; l < q; ++l)
266  M[k][l] = 0;
267  }
268 
269  /* first add bar */
270  for (l = j; l < q; ++l)
271  {
272  assert( M[i][l] == 0 );
273  M[i][l] = 1;
274  }
275 
276  /* then add shifted column */
277  p1 = i-1;
278  p2 = j-1;
279  do
280  {
281  assert( cases[p1][p2] != -1 );
282  assert( p1 >= 0 && p1 < i );
283  assert( p2 >= 0 && p2 < j );
284 
285  /* if case 1 */
286  if ( cases[p1][p2] == 1 )
287  --p2; /* decrease column */
288  else
289  {
290  /* case 2 or 3: */
291  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
292  assert( M[p1][p2] == 0 );
293  M[p1][p2] = -1;
294  if ( cases[p1][p2] == 3 )
295  break;
296  }
297  --p1; /* decrease row */
298  }
299  while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
300  assert( cases[p1][p2] == 3 );
301 
302  /* now output matrix M */
303  for (l = 0; l < q; ++l)
304  SCIPinfoMessage(scip, NULL, "-");
305  SCIPinfoMessage(scip, NULL, "\n");
306 
307  for (k = 0; k < p; ++k)
308  {
309  for (l = 0; l < q; ++l)
310  {
311  if ( l > k )
312  SCIPinfoMessage(scip, NULL, "*");
313  else
314  {
315  switch (M[k][l])
316  {
317  case 1:
318  SCIPinfoMessage(scip, NULL, "+");
319  break;
320  case -1:
321  SCIPinfoMessage(scip, NULL, "-");
322  break;
323  case 0:
324  SCIPinfoMessage(scip, NULL, "#");
325  break;
326  default:
327  SCIPerrorMessage("unexpected matrix entry <%d>: should be -1, 0 or +1\n", M[k][l]);
328  SCIPABORT();
329  }
330  }
331  }
332  SCIPinfoMessage(scip, NULL, "\n");
333  }
334 
335  for (l = 0; l < q; ++l)
336  SCIPinfoMessage(scip, NULL, "-");
337  SCIPinfoMessage(scip, NULL, "\n");
338 
339  for (k = 0; k < p; ++k)
340  SCIPfreeBufferArray(scip, &M[k]);
341  SCIPfreeBufferArray(scip, &M);
342 
343  return SCIP_OKAY;
344 }
345 #endif
346 
347 
348 /** copies the variables values from the solution to the constraint data structure */
349 static
350 void copyValues(
351  SCIP* scip, /**< the SCIP data structure */
352  SCIP_CONSDATA* consdata, /**< the constraint data */
353  SCIP_SOL* sol /**< a primal solution or NULL for the current LP optimum */
354  )
355 {
356  int i;
357  int j;
358 
359  assert( scip != NULL );
360  assert( consdata != NULL );
361  assert( consdata->nspcons > 0 );
362  assert( consdata->nblocks > 0 );
363  assert( consdata->vars != NULL );
364  assert( consdata->vals != NULL );
365 
366  for (i = 0; i < consdata->nspcons; ++i)
367  {
368  for (j = 0; j < consdata->nblocks; ++j)
369  consdata->vals[i][j] = SCIPgetSolVal(scip, sol, consdata->vars[i][j]);
370  }
371 }
372 
373 
374 /** compute the dynamic programming table for SC
375  *
376  * Build up dynamic programming table in order to find SCs with minimum weight.
377  *
378  * The values of the minimal SCIs are stored in @a weights.
379  * The array @a cases[i][j] stores which of the cases were applied to get @a weights[i][j].
380  * Here, 3 means that we have reached the upper limit.
381  *
382  * We assume that the upper right triangle is fixed to 0. Hence we can perform the computation a
383  * bit more efficient.
384  */
385 static
386 void computeSCTable(
387  SCIP* scip, /**< SCIP pointer */
388  int nspcons, /**< number of set partitioning (packing) constraints <=> p */
389  int nblocks, /**< number of symmetric variable blocks <=> q */
390  SCIP_Real** weights, /**< SC weight table */
391  int** cases, /**< indicator of the SC cases */
392  SCIP_Real** vals /**< current solution */
393  )
394 {
395  SCIP_Real minvalue;
396  int diagsize;
397  int i;
398  int j;
399 
400  assert( weights != NULL );
401  assert( cases != NULL );
402  assert( vals != NULL );
403 
404 #ifndef NDEBUG
405  /* for debugging */
406  for (i = 0; i < nspcons; ++i)
407  {
408  for (j = 0; j < nblocks; ++j)
409  {
410  if ( i >= j )
411  {
412  weights[i][j] = -1.0;
413  cases[i][j] = -1;
414  }
415  }
416  }
417 #endif
418 
419  /* initialize diagonal */
420  minvalue = vals[0][0];
421  weights[0][0] = minvalue;
422  cases[0][0] = 3;
423 
424  /* get last row of triangle */
425  diagsize = nblocks;
426  if ( nspcons < nblocks )
427  diagsize = nspcons;
428 
429  for (j = 1; j < diagsize; ++j)
430  {
431  /* use LT to move entry as far to the left as possible */
432  if ( SCIPisLT(scip, vals[j][j], minvalue) )
433  {
434  minvalue = vals[j][j];
435  cases[j][j] = 3;
436  }
437  else
438  cases[j][j] = 1;
439  weights[j][j] = minvalue;
440  }
441 
442  /* initialize first column */
443  for (i = 1; i < nspcons; ++i)
444  {
445  weights[i][0] = weights[i-1][0] + vals[i][0];
446  cases[i][0] = 2; /* second case */
447  }
448 
449  /* build the table */
450  for (i = 2; i < nspcons; ++i)
451  {
452  for (j = 1; j < nblocks && j < i; ++j)
453  {
454  SCIP_Real weightleft;
455  SCIP_Real weightright;
456 
457  assert( cases[i-1][j] != -1 );
458  assert( cases[i-1][j-1] != -1 );
459 
460  weightleft = weights[i-1][j-1];
461  weightright = vals[i][j] + weights[i-1][j];
462 
463  /* For first column: cannot take left possibility */
464  if ( SCIPisLT(scip, weightleft, weightright) )
465  {
466  weights[i][j] = weightleft;
467  cases[i][j] = 1;
468  }
469  else
470  {
471  weights[i][j] = weightright;
472  cases[i][j] = 2;
473  }
474  }
475  }
476 }
477 
478 
479 /** fix upper right triangle if necessary */
480 static
482  SCIP* scip, /**< SCIP data structure */
483  SCIP_CONS* cons, /**< constraint to be processed */
484  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the node can be cut off */
485  int* nfixedvars /**< pointer to add up the number of found domain reductions */
486  )
487 {
488  SCIP_CONSDATA* consdata;
489  SCIP_VAR*** vars;
490  SCIP_Bool fixedglobal;
491  SCIP_Bool fixed;
492  int diagsize;
493  int nspcons;
494  int nblocks;
495  int i;
496  int j;
497 
498  assert( scip != NULL );
499  assert( cons != NULL );
500  assert( infeasible != NULL );
501  assert( nfixedvars != NULL );
502 
503  consdata = SCIPconsGetData(cons);
504  assert( consdata != NULL );
505  assert( consdata->nspcons > 0 );
506  assert( consdata->nblocks > 0 );
507  assert( consdata->vars != NULL );
508 
509  *infeasible = FALSE;
510  *nfixedvars = 0;
511 
512  if ( consdata->istrianglefixed )
513  return SCIP_OKAY;
514 
515  nspcons = consdata->nspcons;
516  nblocks = consdata->nblocks;
517  vars = consdata->vars;
518  fixedglobal = TRUE;
519 
520  /* get last row of triangle */
521  diagsize = nblocks;
522  if ( nspcons < nblocks )
523  diagsize = nspcons;
524 
525  /* fix variables to 0 */
526  for (i = 0; i < diagsize; ++i)
527  {
528  for (j = i+1; j < nblocks; ++j)
529  {
530  /* fix variable, if not in the root the fixation is local */
531  SCIP_CALL( SCIPfixVar(scip, vars[i][j], 0.0, infeasible, &fixed) );
532 
533  if ( *infeasible )
534  {
535  SCIPdebugMessage("The problem is infeasible: some variable in the upper right triangle is fixed to 1.\n");
536  return SCIP_OKAY;
537  }
538 
539  if ( fixed )
540  ++(*nfixedvars);
541 
542  if ( SCIPvarGetUbGlobal(vars[i][j]) > 0.5 )
543  fixedglobal = FALSE;
544  }
545  }
546  if ( *nfixedvars > 0 )
547  {
548  SCIPdebugMessage("<%s>: %s fixed upper right triangle to 0 (fixed vars: %d).\n", SCIPconsGetName(cons), fixedglobal ? "globally" : "locally", *nfixedvars);
549  }
550  else
551  {
552  SCIPdebugMessage("<%s>: Upper right triangle already fixed to 0.\n", SCIPconsGetName(cons));
553  }
554 
555  if ( fixedglobal )
556  consdata->istrianglefixed = TRUE;
557 
558  return SCIP_OKAY;
559 }
560 
561 
562 /** separates shifted column inequalities according to the solution stored in consdata->vals */
563 static
565  SCIP* scip, /**< the SCIP data structure */
566  SCIP_CONSHDLR* conshdlr, /**< constraint handler */
567  SCIP_CONS* cons, /**< constraint */
568  SCIP_CONSDATA* consdata, /**< the constraint data */
569  SCIP_Bool* infeasible, /**< whether we detected infeasibility */
570  int* nfixedvars, /**< number of variables fixed */
571  int* ncuts /**< pointer to store number of separated SCIs */
572  )
573 {
574  SCIP_Real** vals;
575  SCIP_Real** weights;
576  SCIP_Real* tmpvals;
577  SCIP_VAR*** vars;
578  SCIP_VAR** tmpvars;
579  int** cases;
580  int nspcons;
581  int nblocks;
582  int i;
583  int j;
584  int l;
585 
586  assert( scip != NULL );
587  assert( conshdlr != NULL );
588  assert( cons != NULL );
589  assert( infeasible != NULL);
590  assert( nfixedvars != NULL );
591  assert( ncuts != NULL );
592 
593  assert( consdata != NULL );
594  assert( consdata->nspcons > 0 );
595  assert( consdata->nblocks > 0 );
596  assert( consdata->vars != NULL );
597  assert( consdata->vals != NULL );
598  assert( consdata->tmpvars != NULL );
599  assert( consdata->tmpvals != NULL );
600  assert( consdata->weights != NULL );
601  assert( consdata->cases != NULL );
602 
603  *infeasible = FALSE;
604  *nfixedvars = 0;
605 
606  nspcons = consdata->nspcons;
607  nblocks = consdata->nblocks;
608  vars = consdata->vars;
609  vals = consdata->vals;
610  tmpvars = consdata->tmpvars;
611  tmpvals = consdata->tmpvals;
612  weights = consdata->weights;
613  cases = consdata->cases;
614 
615  /* check for upper right triangle */
616  if ( ! consdata->istrianglefixed )
617  {
618  SCIP_CALL( fixTriangle(scip, cons, infeasible, nfixedvars) );
619  if ( *infeasible )
620  return SCIP_OKAY;
621  if ( *nfixedvars > 0 )
622  return SCIP_OKAY;
623  }
624 
625  /* compute table if necessary (i.e., not computed before) */
626  computeSCTable(scip, nspcons, nblocks, weights, cases, vals);
627 
628  /* loop through rows */
629  for (i = 1; i < nspcons && ! (*infeasible); ++i)
630  {
631  SCIP_Real bar; /* value of bar: */
632  int lastcolumn; /* last column considered as part of the bar */
633 
634  bar = 0.0;
635  lastcolumn = nblocks - 1;
636  if ( lastcolumn > i )
637  lastcolumn = i;
638 
639  /* traverse row from right to left: */
640  /* j >= 2, since for j = 1 we look at column 0, which is uninteresting due to the one at position (0,0) */
641  for (j = lastcolumn; j > 1; --j)
642  {
643  bar += vals[i][j];
644 
645  /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
646  if ( SCIPisEfficacious(scip, bar - weights[i-1][j-1]) )
647  {
648  SCIP_Real weight;
649  SCIP_ROW* row;
650 #ifdef SCIP_DEBUG
651  char name[SCIP_MAXSTRLEN];
652 #endif
653  int nvars;
654  int p1;
655  int p2;
656 
657  nvars = 0;
658  p1 = i-1;
659  p2 = j-1;
660  weight = 0.0;
661 
662  /* first add bar */
663  for (l = j; l <= lastcolumn; ++l)
664  {
665  tmpvars[nvars] = vars[i][l];
666  tmpvals[nvars] = 1.0;
667  nvars++;
668  }
669 
670  /* then add shifted column */
671  do
672  {
673  assert( cases[p1][p2] != -1 );
674  assert( p1 >= 0 && p1 < i );
675  assert( p2 >= 0 && p2 < j );
676 
677  /* if case 1 */
678  if (cases[p1][p2] == 1)
679  p2--; /* decrease column */
680  else
681  {
682  /* case 2 or 3: */
683  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
684  tmpvars[nvars] = vars[p1][p2];
685  tmpvals[nvars] = -1.0;
686  nvars++;
687  weight += vals[p1][p2];
688  if ( cases[p1][p2] == 3 )
689  break;
690  }
691  p1--; /* decrease row */
692  }
693  while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
694  assert( cases[p1][p2] == 3 );
695 
696  /* generate cut */
697 #ifdef SCIP_DEBUG
698  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "sci_%d_%d", i, j);
699  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, name, -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
700 #else
701  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, conshdlr, "", -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
702 #endif
703  SCIP_CALL( SCIPaddVarsToRow(scip, row, nvars, tmpvars, tmpvals) );
704  /*SCIP_CALL( SCIPprintRow(scip, row, NULL) ); */
705  SCIP_CALL( SCIPaddCut(scip, NULL, row, FALSE, infeasible) );
706  SCIP_CALL( SCIPreleaseRow(scip, &row) );
707  ++(*ncuts);
708 
709 #ifdef SHOW_SCI
710  SCIP_CALL( printSCI(scip, nspcons, nblocks, cases, i, j) );
711 #endif
712 
713  assert( SCIPisSumEQ(scip, weights[i-1][j-1], weight) );
714  }
715  }
716  }
717  return SCIP_OKAY;
718 }
719 
720 
721 /** propagation method for a single orbitope constraint */
722 static
724  SCIP* scip, /**< SCIP data structure */
725  SCIP_CONS* cons, /**< constraint to be processed */
726  SCIP_Bool* infeasible, /**< pointer to store TRUE, if the node can be cut off */
727  int* nfixedvars /**< pointer to add up the number of found domain reductions */
728  )
729 {
730  SCIP_CONSDATA* consdata;
731  SCIP_VAR*** vars;
732  SCIP_Bool ispart;
733  int* firstnonzeros;
734  int* lastones;
735  int* frontiersteps;
736  int lastoneprevrow;
737  int nspcons;
738  int nblocks;
739  int nsteps;
740  int i;
741  int j;
742 
743  assert( scip != NULL );
744  assert( cons != NULL );
745  assert( infeasible != NULL );
746  assert( nfixedvars != NULL );
747 
748  *nfixedvars = 0;
749 
750  if( !SCIPallowDualReds(scip) )
751  return SCIP_OKAY;
752 
753  consdata = SCIPconsGetData(cons);
754  assert( consdata != NULL );
755  assert( consdata->nspcons > 0 );
756  assert( consdata->nblocks > 0 );
757  assert( consdata->vars != NULL );
758 
759  nspcons = consdata->nspcons;
760  nblocks = consdata->nblocks;
761  vars = consdata->vars;
762  ispart = consdata->ispart;
763 
764  /* fix upper right triangle if still necessary */
765  if ( ! consdata->istrianglefixed )
766  {
767  int nfixed = 0;
768  SCIP_CALL( fixTriangle(scip, cons, infeasible, &nfixed) );
769  *nfixedvars += nfixed;
770  }
771 
772  /* prepare further propagation */
773  SCIP_CALL( SCIPallocBufferArray(scip, &firstnonzeros, nspcons) );
774  SCIP_CALL( SCIPallocBufferArray(scip, &lastones, nspcons) );
775  SCIP_CALL( SCIPallocBufferArray(scip, &frontiersteps, nblocks) );
776 
777 #ifdef PRINT_MATRIX
778  SCIPdebugMessage("Matrix:\n");
779  printMatrix(scip, consdata);
780 #endif
781 
782  /* propagate */
783  lastoneprevrow = 0;
784  lastones[0] = 0;
785 
786  if ( ! ispart )
787  {
788  /* packing case: if entry (0,0) is fixed to 0 */
789  if ( SCIPvarGetUbLocal(vars[0][0]) < 0.5 )
790  {
791  lastoneprevrow = -1;
792  lastones[0] = -1;
793  }
794  }
795  nsteps = 0;
796 
797  for (i = 1; i < nspcons; ++i)
798  {
799  int lastcolumn;
800  int firstnonzeroinrow;
801  int lastoneinrow;
802  SCIP_Bool infrontier;
803 
804  /* last column considered as part of the bar: */
805  lastcolumn = nblocks - 1;
806  if ( lastcolumn > i )
807  lastcolumn = i;
808 
809  /* find first position not fixed to 0 (partitioning) or fixed to 1 (packing) */
810  firstnonzeroinrow = -1;
811  for (j = 0; j <= lastcolumn; ++j)
812  {
813  if ( ispart )
814  {
815  /* partitioning case: if variable is not fixed to 0 */
816  if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
817  {
818  firstnonzeroinrow = j;
819  break;
820  }
821  }
822  else
823  {
824  /* packing case: if variable is fixed to 1 */
825  if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
826  {
827  firstnonzeroinrow = j;
828  break;
829  }
830  }
831  }
832  /* if all variables are fixed to 0 in the partitioning case - should not happen */
833  if ( firstnonzeroinrow == -1 && ispart )
834  {
835  SCIPdebugMessage(" -> Infeasible node: all variables in row %d are fixed to 0.\n", i);
836  *infeasible = TRUE;
837  /* conflict should be analyzed by setppc constraint handler */
838  goto TERMINATE;
839  }
840  firstnonzeros[i] = firstnonzeroinrow;
841  assert( !ispart || firstnonzeroinrow >= 0 );
842  assert( -1 <= firstnonzeroinrow && firstnonzeroinrow <= lastcolumn );
843 
844  /* compute rightmost possible position for a 1 */
845  lastoneinrow = -1;
846  assert( !ispart || 0 <= lastoneprevrow );
847  assert( lastoneprevrow <= lastcolumn );
848 
849  /* if we are at right border or if entry in column lastoneprevrow+1 is fixed to 0 */
850  infrontier = FALSE;
851  assert( lastoneprevrow + 1 >= 0 );
852  if ( lastoneprevrow == nblocks-1 || SCIPvarGetUbLocal(vars[i][lastoneprevrow+1]) < 0.5 ) /*lint !e679*/
853  lastoneinrow = lastoneprevrow;
854  else
855  {
856  lastoneinrow = lastoneprevrow + 1;
857  frontiersteps[nsteps++] = i;
858  infrontier = TRUE;
859  }
860 
861  /* store lastoneinrow */
862  assert( !ispart || 0 <= lastoneinrow );
863  assert( lastoneinrow <= lastcolumn );
864  lastones[i] = lastoneinrow;
865 
866  /* check whether we are infeasible */
867  if ( firstnonzeroinrow > lastoneinrow )
868  {
869  int k;
870 
871 #ifdef SCIP_DEBUG
872  if ( ispart )
873  {
874  SCIPdebugMessage(" -> Infeasible node: row %d, leftmost nonzero at %d, rightmost 1 at %d\n",
875  i, firstnonzeroinrow, lastoneinrow);
876  }
877  else
878  {
879  SCIPdebugMessage(" -> Infeasible node: row %d, 1 at %d, rightmost position for 1 at %d\n",
880  i, firstnonzeroinrow, lastoneinrow);
881  }
882 #endif
883  /* check if conflict analysis is applicable */
885  {
886  /* conflict analysis only applicable in SOLVING stage */
887  assert( SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPinProbing(scip) );
888 
889  /* perform conflict analysis */
891 
892  if ( ispart )
893  {
894  /* add bounds (variables fixed to 0) that result in the first nonzero entry */
895  for (j = 0; j <= lastcolumn; ++j)
896  {
897  /* add varaibles in row up to the first variable fixed to 0 */
898  if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
899  break;
900 
901  assert( SCIPvarGetUbLocal(vars[i][j]) < 0.5 );
902  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
903  }
904  }
905  else
906  {
907  /* add bounds that result in the last one - check top left entry for packing case */
908  if ( lastones[0] == -1 )
909  {
910  assert( SCIPvarGetUbLocal(vars[0][0]) < 0.5 );
911  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[0][0]) );
912  }
913 
914  /* mark variable fixed to 1 */
915  assert( SCIPvarGetLbLocal(vars[i][firstnonzeroinrow]) > 0.5 );
916  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][firstnonzeroinrow]) );
917  }
918 
919  /* add bounds that result in the last one - pass through rows */
920  for (k = 1; k < i; ++k)
921  {
922  int l;
923  l = lastones[k] + 1;
924 
925  /* if the frontier has not moved and we are not beyond the matrix boundaries */
926  if ( l <= nblocks-1 && l <= k && lastones[k-1] == lastones[k] )
927  {
928  assert( SCIPvarGetUbLocal(vars[k][l]) < 0.5 );
929  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][l]) );
930  }
931  }
932  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
933  }
934 
935  *infeasible = TRUE;
936  goto TERMINATE;
937  }
938 
939  /* fix entries beyond the last possible position for a 1 in the row to 0 (see Lemma 1 in the paper) */
940  for (j = lastoneinrow+1; j <= lastcolumn; ++j)
941  {
942  /* if the entry is not yet fixed to 0 */
943  if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
944  {
945  SCIP_Bool tightened;
946  int inferInfo;
947 
948  SCIPdebugMessage(" -> Fixing entry (%d,%d) to 0.\n", i, j);
949 
950  tightened = FALSE;
951 
952  /* fix variable to 0 and store position of (i,lastoneinrow+1) for conflict resolution */
953  inferInfo = i * nblocks + lastoneinrow + 1;
954  /* correction according to Lemma 1 in the paper (second part): store (i,lastoneinrow+2) */
955  if ( !infrontier )
956  ++inferInfo;
957  SCIP_CALL( SCIPinferBinvarCons(scip, vars[i][j], FALSE, cons, inferInfo, infeasible, &tightened) );
958 
959  /* if entry is fixed to one -> infeasible node */
960  if ( *infeasible )
961  {
962  SCIPdebugMessage(" -> Infeasible node: row %d, 1 in column %d beyond rightmost position %d\n", i, j, lastoneinrow);
963  /* check if conflict analysis is applicable */
965  {
966  int k;
967 
968  /* conflict analysis only applicable in SOLVING stage */
969  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPinProbing(scip));
970 
971  /* perform conflict analysis */
973 
974  /* add current bound */
975  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
976 
977  /* add bounds that result in the last one - check top left entry for packing case */
978  if ( ! ispart && lastones[0] == -1 )
979  {
980  assert( SCIPvarGetUbLocal(vars[0][0]) < 0.5 );
981  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[0][0]) );
982  }
983 
984  /* add bounds that result in the last one - pass through rows */
985  for (k = 1; k < i; ++k)
986  {
987  int l;
988  l = lastones[k] + 1;
989 
990  /* if the frontier has not moved and we are not beyond the matrix boundaries */
991  if ( l <= nblocks-1 && l <= k && lastones[k-1] == lastones[k] )
992  {
993  assert( SCIPvarGetUbLocal(vars[k][l]) < 0.5 );
994  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][l]) );
995  }
996  }
997  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
998  }
999 
1000  goto TERMINATE;
1001  }
1002  if ( tightened )
1003  ++(*nfixedvars);
1004  }
1005  }
1006 
1007  lastoneprevrow = lastoneinrow;
1008  }
1009 
1010  /* check whether fixing any entry to 0 results in a contradiction -> loop through rows in frontiersteps (a.k.a. gamma) */
1011  for (j = 0; j < nsteps; ++j)
1012  {
1013  int s;
1014  int lastoneinrow;
1015 
1016  s = frontiersteps[j];
1017  lastoneinrow = lastones[s];
1018  /* note for packing case: if we are in a frontier step then lastoneinrow >= 0 */
1019  assert( 0 <= lastoneinrow && lastoneinrow < nblocks );
1020 
1021  /* if entry is not fixed */
1022  if ( SCIPvarGetLbLocal(vars[s][lastoneinrow]) < 0.5 && SCIPvarGetUbLocal(vars[s][lastoneinrow]) > 0.5 )
1023  {
1024  int betaprev;
1025  betaprev = lastoneinrow - 1;
1026 
1027  /* loop through rows below s */
1028  for (i = s+1; i < nspcons; ++i)
1029  {
1030  int beta;
1031  beta = -2;
1032 
1033  assert( betaprev + 1 >= 0 );
1034  if ( betaprev == nblocks-1 || SCIPvarGetUbLocal(vars[i][betaprev+1]) < 0.5 ) /*lint !e679*/
1035  beta = betaprev;
1036  else
1037  beta = betaprev + 1;
1038  assert( -1 <= beta && beta < nblocks );
1039 
1040  if ( firstnonzeros[i] > beta )
1041  {
1042  SCIP_Bool tightened;
1043  int inferInfo;
1044 
1045  /* can fix (s,lastoneinrow) (a.k.a (s,alpha)) to 1
1046  * (do not need to fix other entries to 0, since they will be
1047  * automatically fixed by SCIPtightenVarLb.)
1048  */
1049  assert( SCIPvarGetLbLocal(vars[s][lastoneinrow]) < 0.5 );
1050  SCIPdebugMessage(" -> Fixing entry (%d,%d) to 1.\n", s, lastoneinrow);
1051 
1052  tightened = FALSE;
1053 
1054  /* store position (i,firstnonzeros[i]) */
1055  inferInfo = nblocks * nspcons + i * nblocks + firstnonzeros[i];
1056  SCIP_CALL( SCIPinferBinvarCons(scip, vars[s][lastoneinrow], TRUE, cons, inferInfo, infeasible, &tightened) );
1057 
1058  assert( !(*infeasible) );
1059  if ( tightened )
1060  ++(*nfixedvars);
1061  break;
1062  }
1063  betaprev = beta;
1064  }
1065  }
1066  }
1067 
1068  TERMINATE:
1069  SCIPfreeBufferArray(scip, &frontiersteps);
1070  SCIPfreeBufferArray(scip, &lastones);
1071  SCIPfreeBufferArray(scip, &firstnonzeros);
1072 
1073  return SCIP_OKAY;
1074 }
1075 
1076 
1077 /** Propagation conflict resolving method of propagator
1078  *
1079  * In this function we use that the propagation method above implicitly propagates SCIs, i.e., every
1080  * fixing can also be gotten via an SCI-fixing.
1081  *
1082  * Since the storage of an integer is not enough to store the complete information about the fixing
1083  * nor a complete shifted column, we have to use the linear time algorithm for SCIs.
1084  *
1085  * The inferinfo integer is set as follows:
1086  *
1087  * - If a shifted column is fixed to 0 and the corresponding bar does not necessarily has value 1
1088  * then we fix these entries to 0 and inferinfo is i * nblocks + j, where (i,j) is the leader of the
1089  * bar. The SCI depends on whether i is in Gamma or not (see Lemma 1 in the paper and the comments
1090  * above).
1091  *
1092  * - If a bar has value 1 and the shifted column has one entry that is not fixed, it can be fixed to
1093  * 1 and inferinfo is (nspcons*nblocks) + i * nblocks + j, where (i,j) is the leader of the bar; see
1094  * Proposition 1 (2c).
1095  */
1096 static
1098  SCIP* scip, /**< SCIP data structure */
1099  SCIP_CONS* cons, /**< constraint that inferred the bound change */
1100  SCIP_VAR* infervar, /**< variable that was deduced */
1101  int inferinfo, /**< inference information */
1102  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
1103  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1104  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1105  )
1106 { /*lint --e{715}*/
1107  SCIP_CONSDATA* consdata;
1108  SCIP_Real** vals;
1109  SCIP_Real** weights;
1110  SCIP_VAR*** vars;
1111  SCIP_Bool ispart;
1112  int** cases;
1113 
1114  int i;
1115  int j;
1116  int nspcons;
1117  int nblocks;
1118 
1119  assert( scip != NULL );
1120  assert( cons != NULL );
1121  assert( result != NULL );
1122 
1123  consdata = SCIPconsGetData(cons);
1124  assert( consdata != NULL );
1125  assert( consdata->nspcons > 0 );
1126  assert( consdata->nblocks > 0 );
1127  assert( consdata->vars != NULL );
1128  assert( consdata->vals != NULL );
1129  assert( consdata->weights != NULL );
1130  assert( consdata->cases != NULL );
1131  assert( consdata->istrianglefixed );
1132 
1133  *result = SCIP_DIDNOTFIND;
1134  if ( ! consdata->resolveprop )
1135  return SCIP_OKAY;
1136 
1137  nspcons = consdata->nspcons;
1138  nblocks = consdata->nblocks;
1139  vars = consdata->vars;
1140  vals = consdata->vals;
1141  weights = consdata->weights;
1142  ispart = consdata->ispart;
1143  cases = consdata->cases;
1144 
1145  SCIPdebugMessage("Propagation resolution method of orbitope constraint using orbitopal fixing\n");
1146 
1147  /* fill table */
1148  for (i = 0; i < nspcons; ++i)
1149  {
1150  int lastcolumn;
1151 
1152  /* last column considered as part of the bar: */
1153  lastcolumn = nblocks - 1;
1154  if ( lastcolumn > i )
1155  lastcolumn = i;
1156  for (j = 0; j <= lastcolumn; ++j)
1157  {
1158  /* if the variable was fixed to zero at conflict time */
1159  if ( SCIPvarGetUbAtIndex(vars[i][j], bdchgidx, FALSE) < 0.5 )
1160  vals[i][j] = 0.0;
1161  else
1162  {
1163  /* if the variable was fixed to one at conflict time */
1164  if ( SCIPvarGetLbAtIndex(vars[i][j], bdchgidx, FALSE) > 0.5 )
1165  vals[i][j] = 2.0;
1166  else
1167  vals[i][j] = 1.0;
1168  }
1169  }
1170  }
1171 
1172 #ifdef PRINT_MATRIX
1173  SCIPdebugMessage("Matrix:\n");
1174  printMatrix(scip, consdata);
1175 #endif
1176 
1177  /* computation of table: this now minimizes the value of the shifted column */
1178  assert( consdata->istrianglefixed );
1179  computeSCTable(scip, nspcons, nblocks, weights, cases, vals);
1180 
1181  /* if we fixed variables in the bar to zero */
1182  assert( inferinfo >= 0 && inferinfo < 2 * nspcons * nblocks );
1183  if ( inferinfo < nspcons * nblocks )
1184  {
1185  int p1;
1186  int p2;
1187 #ifdef SCIP_DEBUG
1188  char str[SCIP_MAXSTRLEN];
1189  char tmpstr[SCIP_MAXSTRLEN];
1190 #endif
1191 
1192  i = (int) (inferinfo / nblocks);
1193  j = inferinfo % nblocks;
1194  assert( 0 <= i && i < nspcons );
1195  assert( 0 <= j && j < nblocks );
1196 
1197  /* find SCI with value 0 */
1198  assert( weights[i-1][j-1] < 0.5 );
1199 
1200  SCIPdebugMessage(" -> reason for x[%d][%d] = ... = x[%d][%d] = 0 was the following SC:\n", i, j, i, MIN(i,nblocks));
1201 #ifdef SCIP_DEBUG
1202  str[0] = '\0';
1203 #endif
1204 
1205  p1 = i-1;
1206  p2 = j-1;
1207  do
1208  {
1209  assert( cases[p1][p2] != -1 );
1210  assert( p1 >= 0 && p1 < i );
1211  assert( p2 >= 0 && p2 < j );
1212 
1213  /* if case 1 */
1214  if ( cases[p1][p2] == 1 )
1215  --p2; /* decrease column */
1216  else
1217  {
1218  /* case 2 or 3: */
1219  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
1220  assert( SCIPvarGetUbAtIndex(vars[p1][p2], bdchgidx, FALSE) < 0.5 );
1221  SCIP_CALL( SCIPaddConflictUb(scip, vars[p1][p2], bdchgidx) );
1222  *result = SCIP_SUCCESS;
1223 
1224 #ifdef SCIP_DEBUG
1225  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", p1, p2);
1226  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1227 #endif
1228 
1229  if ( cases[p1][p2] == 3 )
1230  break;
1231  }
1232  --p1; /* decrease row */
1233  }
1234  while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
1235  assert( cases[p1][p2] == 3 );
1236 
1237 #ifdef SCIP_DEBUG
1238  SCIPdebugMessage("%s\n", str);
1239 #endif
1240  }
1241  else
1242  {
1243  int k;
1244  int p1;
1245  int p2;
1246 #ifndef NDEBUG
1247  int pos1;
1248  int pos2;
1249 #endif
1250 #ifdef SCIP_DEBUG
1251  char str[SCIP_MAXSTRLEN];
1252  char tmpstr[SCIP_MAXSTRLEN];
1253 #endif
1254 
1255  /* if we fixed a variable in the SC to 1 */
1256  inferinfo -= nspcons * nblocks;
1257  i = (int) inferinfo / nblocks;
1258  j = inferinfo % nblocks;
1259  assert( 0 <= i && i < nspcons );
1260  assert( 0 <= j && j < nblocks );
1261 
1262  /* In rare cases it might happen that we fixed a variable to 1, but the node later becomes infeasible by globally
1263  * fixing variables to 0. In this case, it might happen that we find a SC with value 0 instead of 1. We then
1264  * cannot use this SC to repropagate (and do not know how to reconstruct the original reasoning). */
1265  if ( weights[i-1][j-1] > 0.5 && weights[i-1][j-1] < 1.5 )
1266  {
1267  SCIPdebugMessage(" -> reason for x[%d][%d] = 1 was the following SC:\n", i, j);
1268 #ifdef SCIP_DEBUG
1269  (void) SCIPsnprintf(str, SCIP_MAXSTRLEN, "SC:");
1270 #endif
1271 
1272  p1 = i-1;
1273  p2 = j-1;
1274 #ifndef NDEBUG
1275  pos1 = -1;
1276  pos2 = -1;
1277 #endif
1278  do
1279  {
1280  assert( cases[p1][p2] != -1 );
1281  assert( p1 >= 0 && p1 < i );
1282  assert( p2 >= 0 && p2 < j );
1283 
1284  /* if case 1 */
1285  if ( cases[p1][p2] == 1 )
1286  --p2; /* decrease column */
1287  else
1288  {
1289  /* case 2 or 3: reason are formed by variables in SC fixed to 0 */
1290  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
1291  if ( SCIPvarGetUbAtIndex(vars[p1][p2], bdchgidx, FALSE) < 0.5 )
1292  {
1293  SCIP_CALL( SCIPaddConflictUb(scip, vars[p1][p2], bdchgidx) );
1294  *result = SCIP_SUCCESS;
1295 
1296 #ifdef SCIP_DEBUG
1297  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", p1, p2);
1298  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1299 #endif
1300  }
1301 #ifndef NDEBUG
1302  else
1303  {
1304  assert( SCIPvarGetLbAtIndex(vars[p1][p2], bdchgidx, FALSE) < 0.5 );
1305  assert( pos1 == -1 && pos2 == -1 );
1306  pos1 = p1;
1307  pos2 = p2;
1308  }
1309 #endif
1310  if ( cases[p1][p2] == 3 )
1311  break;
1312  }
1313  --p1; /* decrease row */
1314  }
1315  while ( p1 >= 0 ); /* should always be true, i.e., the break should end the loop */
1316  assert( cases[p1][p2] == 3 );
1317  assert( pos1 >= 0 && pos2 >= 0 );
1318 
1319  /* distinguish partitioning/packing */
1320  if ( ispart )
1321  {
1322  /* partitioning case */
1323 #ifdef SCIP_DEBUG
1324  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " before bar: ");
1325  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1326 #endif
1327  /* add variables before the bar in the partitioning case */
1328  for (k = 0; k < j; ++k)
1329  {
1330  assert( SCIPvarGetUbAtIndex(vars[i][k], bdchgidx, FALSE) < 0.5 );
1331  SCIP_CALL( SCIPaddConflictUb(scip, vars[i][k], bdchgidx) );
1332  *result = SCIP_SUCCESS;
1333 #ifdef SCIP_DEBUG
1334  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", i, k);
1335  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1336 #endif
1337  }
1338 
1339 #ifdef SCIP_DEBUG
1340  SCIPdebugMessage("%s\n", str);
1341 #endif
1342  }
1343  else
1344  {
1345  /* packing case */
1346  int lastcolumn;
1347 
1348  /* last column considered as part of the bar: */
1349  lastcolumn = nblocks - 1;
1350  if ( lastcolumn > i )
1351  lastcolumn = i;
1352 
1353  /* search for variable in the bar that is fixed to 1 in the packing case */
1354  for (k = j; k <= lastcolumn; ++k)
1355  {
1356  if ( SCIPvarGetLbAtIndex(vars[i][k], bdchgidx, FALSE) > 0.5 )
1357  {
1358  SCIP_CALL( SCIPaddConflictLb(scip, vars[i][k], bdchgidx) );
1359  *result = SCIP_SUCCESS;
1360  SCIPdebugMessage(" and variable x[%d][%d] fixed to 1.\n", i, k);
1361  break;
1362  }
1363  }
1364  }
1365  }
1366  }
1367 
1368  return SCIP_OKAY;
1369 }
1370 
1371 
1372 /*
1373  * Callback methods of constraint handler
1374  */
1375 
1376 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1377 static
1378 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbitope)
1379 { /*lint --e{715}*/
1380  assert(scip != NULL);
1381  assert(conshdlr != NULL);
1382  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1383 
1384  /* call inclusion method of constraint handler */
1386 
1387  *valid = TRUE;
1388 
1389  return SCIP_OKAY;
1390 }
1391 
1392 /** frees specific constraint data */
1393 static
1394 SCIP_DECL_CONSDELETE(consDeleteOrbitope)
1395 { /*lint --e{715}*/
1396  assert(conshdlr != NULL);
1397  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1398 
1399  SCIP_CALL( consdataFree(scip, consdata) );
1400 
1401  return SCIP_OKAY;
1402 }
1403 
1404 /** transforms constraint data into data belonging to the transformed problem */
1405 static
1406 SCIP_DECL_CONSTRANS(consTransOrbitope)
1407 { /*lint --e{715}*/
1408  SCIP_CONSDATA* sourcedata;
1409  SCIP_CONSDATA* targetdata;
1410 
1411  assert(conshdlr != NULL);
1412  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1413  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
1414  assert(sourcecons != NULL);
1415  assert(targetcons != NULL);
1416 
1417  sourcedata = SCIPconsGetData(sourcecons);
1418  assert(sourcedata != NULL);
1419 
1420  /* create linear constraint data for target constraint */
1421  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->vars, sourcedata->nspcons, sourcedata->nblocks,
1422  sourcedata->ispart, sourcedata->resolveprop) );
1423 
1424  /* create target constraint */
1425  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
1426  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1427  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
1428  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
1429  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1430 
1431  return SCIP_OKAY;
1432 }
1433 
1434 /** separation method of constraint handler for LP solutions */
1435 static
1436 SCIP_DECL_CONSSEPALP(consSepalpOrbitope)
1437 { /*lint --e{715}*/
1438  assert( scip != NULL );
1439  assert( conshdlr != NULL );
1440  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1441  assert( result != NULL );
1442 
1443  *result = SCIP_DIDNOTRUN;
1444 
1445  /* if solution is not integer */
1446  if ( SCIPgetNLPBranchCands(scip) > 0 )
1447  {
1448  SCIP_Bool infeasible;
1449  int nfixedvars = 0;
1450  int ncuts = 0;
1451  int c;
1452 
1453  *result = SCIP_DIDNOTFIND;
1454  infeasible = FALSE;
1455 
1456  /* loop through constraints */
1457  for (c = 0; c < nusefulconss && ! infeasible; c++)
1458  {
1459  SCIP_CONSDATA* consdata;
1460 
1461  assert( conss[c] != NULL );
1462 
1463  /* get data of constraint */
1464  consdata = SCIPconsGetData(conss[c]);
1465  assert( consdata != NULL );
1466 
1467  /* get solution */
1468  copyValues(scip, consdata, NULL);
1469  SCIPdebugMessage("Separating SCIs for orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1470 
1471  /* separate */
1472  SCIP_CALL( separateSCIs(scip, conshdlr, conss[c], consdata, &infeasible, &nfixedvars, &ncuts) );
1473  }
1474  if ( infeasible )
1475  {
1476  SCIPdebugMessage("Infeasible node.\n");
1477  *result = SCIP_CUTOFF;
1478  }
1479  else if ( nfixedvars > 0 )
1480  {
1481  SCIPdebugMessage("Fixed %d variables.\n", nfixedvars);
1482  *result = SCIP_REDUCEDDOM;
1483  }
1484  else if ( ncuts > 0 )
1485  {
1486  SCIPdebugMessage("Separated %d SCIs.\n", ncuts);
1487  *result = SCIP_SEPARATED;
1488  }
1489  else
1490  {
1491  SCIPdebugMessage("No violated SCI found.\n");
1492  }
1493  }
1494 
1495  return SCIP_OKAY;
1496 }
1497 
1498 /** separation method of constraint handler for arbitrary primal solutions */
1499 static
1500 SCIP_DECL_CONSSEPASOL(consSepasolOrbitope)
1501 { /*lint --e{715}*/
1502  SCIP_Bool infeasible = FALSE;
1503  int nfixedvars = 0;
1504  int ncuts = 0;
1505  int c;
1506 
1507  assert( scip != NULL );
1508  assert( conshdlr != NULL );
1509  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1510  assert( result != NULL );
1511 
1512  *result = SCIP_DIDNOTFIND;
1513 
1514  /* loop through constraints */
1515  for (c = 0; c < nusefulconss && ! infeasible; c++)
1516  {
1517  SCIP_CONSDATA* consdata;
1518 
1519  /* get data of constraint */
1520  assert( conss[c] != NULL );
1521  consdata = SCIPconsGetData(conss[c]);
1522  assert( consdata != NULL );
1523 
1524  /* get solution */
1525  copyValues(scip, consdata, sol);
1526  SCIPdebugMessage("Separating SCIs (solution) for orbitope constraint <%s> \n", SCIPconsGetName(conss[c]));
1527 
1528  /* separate */
1529  SCIP_CALL( separateSCIs(scip, conshdlr, conss[c], consdata, &infeasible, &nfixedvars, &ncuts) );
1530  }
1531 
1532  if ( infeasible )
1533  {
1534  SCIPdebugMessage("Infeasible node.\n");
1535  *result = SCIP_CUTOFF;
1536  }
1537  else if ( nfixedvars > 0 )
1538  {
1539  SCIPdebugMessage("Fixed %d variables.\n", nfixedvars);
1540  *result = SCIP_REDUCEDDOM;
1541  }
1542  else if ( ncuts > 0 )
1543  {
1544  SCIPdebugMessage("Separated %d SCIs.\n", ncuts);
1545  *result = SCIP_SEPARATED;
1546  }
1547  else
1548  {
1549  SCIPdebugMessage("No violated SCI found.\n");
1550  }
1551 
1552  return SCIP_OKAY;
1553 }
1554 
1555 
1556 /** constraint enforcing method of constraint handler for LP solutions */
1557 static
1558 SCIP_DECL_CONSENFOLP(consEnfolpOrbitope)
1559 { /*lint --e{715}*/
1560  SCIP_Bool infeasible = FALSE;
1561  int nfixedvars = 0;
1562  int ncuts = 0;
1563  int c;
1564 
1565  assert( scip != NULL );
1566  assert( conshdlr != NULL );
1567  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1568  assert( result != NULL );
1569 
1570  *result = SCIP_FEASIBLE;
1571 
1572  /* we have a negative priority, so we should come after the integrality conshdlr */
1573  assert( SCIPgetNLPBranchCands(scip) == 0 );
1574 
1575  /* loop through constraints */
1576  for (c = 0; c < nusefulconss && ! infeasible; c++)
1577  {
1578  SCIP_CONSDATA* consdata;
1579 
1580  assert( conss[c] != NULL );
1581 
1582  /* get data of constraint */
1583  consdata = SCIPconsGetData(conss[c]);
1584  assert( consdata != NULL );
1585 
1586  /* get solution */
1587  copyValues(scip, consdata, NULL);
1588  SCIPdebugMessage("Enforcing for orbitope constraint <%s>\n", SCIPconsGetName(conss[c]));
1589 
1590  /* separate */
1591  SCIP_CALL( separateSCIs(scip, conshdlr, conss[c], consdata, &infeasible, &nfixedvars, &ncuts) );
1592  }
1593 
1594  if ( infeasible )
1595  {
1596  SCIPdebugMessage("Infeasible node.\n");
1597  *result = SCIP_CUTOFF;
1598  }
1599  else if ( nfixedvars > 0 )
1600  {
1601  SCIPdebugMessage("Fixed %d variables.\n", nfixedvars);
1602  *result = SCIP_REDUCEDDOM;
1603  }
1604  else if ( ncuts > 0 )
1605  {
1606  SCIPdebugMessage("Separated %d SCIs during enforcement.\n", ncuts);
1607  *result = SCIP_SEPARATED;
1608  }
1609  else
1610  {
1611  SCIPdebugMessage("No violated SCI found during enforcement.\n");
1612  }
1613 
1614  return SCIP_OKAY;
1615 }
1616 
1617 
1618 /** constraint enforcing method of constraint handler for pseudo solutions */
1619 static
1620 SCIP_DECL_CONSENFOPS(consEnfopsOrbitope)
1621 { /*lint --e{715}*/
1622  int c;
1623 
1624  assert( scip != NULL );
1625  assert( conshdlr != NULL );
1626  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1627  assert( result != NULL );
1628 
1629  *result = SCIP_FEASIBLE;
1630  if ( objinfeasible || solinfeasible )
1631  return SCIP_OKAY;
1632 
1633  /* loop through constraints */
1634  for (c = 0; c < nconss; ++c)
1635  {
1636  SCIP_CONSDATA* consdata;
1637  SCIP_Real** weights;
1638  SCIP_Real** vals;
1639  SCIP_CONS* cons;
1640  int** cases;
1641  int nspcons;
1642  int nblocks;
1643  int i;
1644  int j;
1645 
1646  /* get data of constraint */
1647  cons = conss[c];
1648  assert( cons != 0 );
1649  consdata = SCIPconsGetData(cons);
1650 
1651  assert( consdata != NULL );
1652  assert( consdata->nspcons > 0 );
1653  assert( consdata->nblocks > 0 );
1654  assert( consdata->vals != NULL );
1655  assert( consdata->weights != NULL );
1656  assert( consdata->cases != NULL );
1657 
1658  /* check for upper right triangle */
1659  if ( ! consdata->istrianglefixed )
1660  {
1661  SCIP_Bool infeasible = FALSE;
1662  int nfixedvars = 0;
1663 
1664  SCIP_CALL( fixTriangle(scip, cons, &infeasible, &nfixedvars) );
1665  if ( infeasible )
1666  {
1667  *result = SCIP_CUTOFF;
1668  return SCIP_OKAY;
1669  }
1670  if ( nfixedvars > 0 )
1671  {
1672  *result = SCIP_REDUCEDDOM;
1673  return SCIP_OKAY;
1674  }
1675  }
1676 
1677  nspcons = consdata->nspcons;
1678  nblocks = consdata->nblocks;
1679  vals = consdata->vals;
1680  weights = consdata->weights;
1681  cases = consdata->cases;
1682 
1683  /* get solution */
1684  copyValues(scip, consdata, NULL);
1685  SCIPdebugMessage("Enforcing (pseudo solutions) for orbitope constraint <%s>\n", SCIPconsGetName(conss[c]));
1686 
1687  /* compute table */
1688  assert( consdata->istrianglefixed );
1689  computeSCTable(scip, nspcons, nblocks, weights, cases, vals);
1690 
1691  /* loop through rows */
1692  for (i = 1; i < nspcons; ++i)
1693  {
1694  SCIP_Real bar = 0.0;
1695  int lastcolumn;
1696 
1697  lastcolumn = nblocks - 1;
1698 
1699  /* last column considered as part of the bar: */
1700  if ( lastcolumn > i )
1701  lastcolumn = i;
1702 
1703  /* traverse row from right to left */
1704  for (j = lastcolumn; j > 1; --j)
1705  {
1706  bar += vals[i][j];
1707  assert( SCIPisIntegral(scip, vals[i][j]) );
1708 
1709  /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
1710  if ( SCIPisGT(scip, bar - weights[i-1][j-1], 0.0) )
1711  {
1712  SCIPdebugMessage("Solution is infeasible.\n");
1713  *result = SCIP_INFEASIBLE;
1714  return SCIP_OKAY;
1715  }
1716  }
1717  }
1718  }
1719 
1720  return SCIP_OKAY;
1721 }
1722 
1723 
1724 /** feasibility check method of constraint handler for integral solutions */
1725 static
1726 SCIP_DECL_CONSCHECK(consCheckOrbitope)
1727 { /*lint --e{715}*/
1728  int c;
1729 
1730  assert( scip != NULL );
1731  assert( conshdlr != NULL );
1732  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1733  assert( result != NULL );
1734 
1735  *result = SCIP_FEASIBLE;
1736 
1737  /* loop through constraints */
1738  for (c = 0; c < nconss; ++c)
1739  {
1740  SCIP_CONSDATA* consdata;
1741  SCIP_VAR*** vars;
1742  SCIP_Real** vals;
1743  SCIP_Real** weights;
1744  int** cases;
1745  int nspcons;
1746  int nblocks;
1747  int i;
1748  int j;
1749 
1750  /* get data of constraint */
1751  assert( conss[c] != 0 );
1752  consdata = SCIPconsGetData(conss[c]);
1753 
1754  assert( consdata != NULL );
1755  assert( consdata->nspcons > 0 );
1756  assert( consdata->nblocks > 0 );
1757  assert( consdata->vars != NULL );
1758  assert( consdata->vals != NULL );
1759  assert( consdata->weights != NULL );
1760  assert( consdata->cases != NULL );
1761 
1762  nspcons = consdata->nspcons;
1763  nblocks = consdata->nblocks;
1764  vars = consdata->vars;
1765  vals = consdata->vals;
1766  weights = consdata->weights;
1767  cases = consdata->cases;
1768 
1769  /* get solution */
1770  copyValues(scip, consdata, sol);
1771  SCIPdebugMessage("Checking orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1772 
1773  /* check upper right triangle (if not yet fixed to zero or in debug mode */
1774 #ifdef NDEBUG
1775  if ( ! consdata->istrianglefixed )
1776 #endif
1777  {
1778  int diagsize;
1779 
1780  /* get last row of triangle */
1781  diagsize = nblocks;
1782  if ( nspcons < nblocks )
1783  diagsize = nspcons;
1784 
1785  /* check variables */
1786  for (i = 0; i < diagsize; ++i)
1787  {
1788  for (j = i+1; j < nblocks; ++j)
1789  {
1790  if ( ! SCIPisFeasZero(scip, vals[i][j]) )
1791  {
1792  if ( printreason )
1793  SCIPinfoMessage(scip, NULL, "variable x[%d][%d] = %f on upper right nonzero.\n", i, j, vals[i][j]);
1794  *result = SCIP_INFEASIBLE;
1795  return SCIP_OKAY;
1796  }
1797  }
1798  }
1799  }
1800 
1801  /* compute table */
1802  computeSCTable(scip, nspcons, nblocks, weights, cases, vals);
1803 
1804  /* loop through rows */
1805  for (i = 1; i < nspcons; ++i)
1806  {
1807  SCIP_Real bar;
1808  int lastcolumn;
1809 
1810  lastcolumn = nblocks - 1;
1811  bar = 0.0;
1812  /* last column considered as part of the bar: */
1813  if ( lastcolumn > i )
1814  lastcolumn = i;
1815 
1816  /* traverse row from right to left */
1817  for (j = lastcolumn; j > 1; --j)
1818  {
1819  bar += vals[i][j];
1820  assert( SCIPisFeasIntegral(scip, vals[i][j]) );
1821 
1822  /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
1823  if ( SCIPisGT(scip, bar - weights[i-1][j-1], 0.0) )
1824  {
1825  SCIPdebugMessage("Solution is infeasible.\n");
1826  *result = SCIP_INFEASIBLE;
1827 
1828  if ( printreason )
1829  {
1830  int l;
1831  int p1;
1832  int p2;
1833 
1834  SCIPinfoMessage(scip, NULL, "violated SCI: bar(");
1835 
1836  /* first output bar */
1837  for (l = j; l < nblocks; ++l)
1838  SCIPinfoMessage(scip, NULL, "<%s> (%f)", SCIPvarGetName(vars[i][l]), consdata->vals[i][l]);
1839 
1840  SCIPinfoMessage(scip, NULL, ") SC(");
1841 
1842  /* output shifted column */
1843  p1 = i-1;
1844  p2 = j-1;
1845  do
1846  {
1847  assert( cases[p1][p2] != -1 );
1848  assert( p1 >= 0 && p1 < i );
1849  assert( p2 >= 0 && p2 < j );
1850 
1851  /* if case 1 */
1852  if (cases[p1][p2] == 1)
1853  --p2; /* decrease column */
1854  else
1855  {
1856  /* case 2 or 3: */
1857  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
1858  SCIPinfoMessage(scip, NULL, "<%s> (%f)", SCIPvarGetName(vars[p1][p2]), consdata->vals[p1][p2]);
1859  if ( cases[p1][p2] == 3 )
1860  break;
1861  }
1862  --p1; /* decrease row */
1863  }
1864  while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
1865  assert( cases[p1][p2] == 3 );
1866 
1867  SCIPinfoMessage(scip, NULL, ")");
1868  }
1869 
1870  return SCIP_OKAY;
1871  }
1872  }
1873  }
1874  }
1875  SCIPdebugMessage("Solution is feasible.\n");
1876 
1877  return SCIP_OKAY;
1878 }
1879 
1880 
1881 /** domain propagation method of constraint handler */
1882 static
1883 SCIP_DECL_CONSPROP(consPropOrbitope)
1884 { /*lint --e{715}*/
1885  SCIP_Bool infeasible = FALSE;
1886  int nfixedvars = 0;
1887  int c;
1888 
1889  assert( scip != NULL );
1890  assert( conshdlr != NULL );
1891  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1892  assert( result != NULL );
1893 
1894  *result = SCIP_DIDNOTRUN;
1895 
1896  /* propagate all useful constraints */
1897  for (c = 0; c < nusefulconss && !infeasible; ++c)
1898  {
1899  assert( conss[c] != 0 );
1900 
1901  SCIPdebugMessage("Propagation of orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1902 
1903  SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixedvars) );
1904  }
1905 
1906  /* return the correct result */
1907  if ( infeasible )
1908  {
1909  *result = SCIP_CUTOFF;
1910  SCIPdebugMessage("Propagation via orbitopal fixing proved node to be infeasible.\n");
1911  }
1912  else if ( nfixedvars > 0 )
1913  {
1914  *result = SCIP_REDUCEDDOM;
1915  SCIPdebugMessage("Propagated %d variables via orbitopal fixing.\n", nfixedvars);
1916  }
1917  else if ( nusefulconss > 0 )
1918  {
1919  *result = SCIP_DIDNOTFIND;
1920  SCIPdebugMessage("Propagation via orbitopal fixing did not find anything.\n");
1921  }
1922 
1923  return SCIP_OKAY;
1924 }
1925 
1926 
1927 /** presolving method of constraint handler */
1928 static
1929 SCIP_DECL_CONSPRESOL(consPresolOrbitope)
1930 { /*lint --e{715}*/
1931  SCIP_Bool infeasible = FALSE;
1932  int noldfixedvars;
1933  int c;
1934 
1935  assert( scip != NULL );
1936  assert( conshdlr != NULL );
1937  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1938  assert( result != NULL );
1939 
1940  *result = SCIP_DIDNOTRUN;
1941  noldfixedvars = *nfixedvars;
1942 
1943  /* propagate all useful constraints */
1944  for (c = 0; c < nconss && !infeasible; ++c)
1945  {
1946  int nfixed = 0;
1947 
1948  assert( conss[c] != 0 );
1949 
1950  SCIPdebugMessage("Presolving of orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1951 
1952  SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixed) );
1953  *nfixedvars += nfixed;
1954  }
1955 
1956  if ( infeasible )
1957  {
1958  *result = SCIP_CUTOFF;
1959  SCIPdebugMessage("Presolving detected infeasibility.\n");
1960  }
1961  else if ( *nfixedvars > noldfixedvars )
1962  {
1963  *result = SCIP_SUCCESS;
1964  }
1965  else if ( nconss > 0 )
1966  {
1967  *result = SCIP_DIDNOTFIND;
1968  SCIPdebugMessage("Presolving via orbitopal fixing did not find anything.\n");
1969  }
1970 
1971  return SCIP_OKAY;
1972 }
1973 
1974 
1975 /** propagation conflict resolving method of constraint handler */
1976 static
1977 SCIP_DECL_CONSRESPROP(consRespropOrbitope)
1978 { /*lint --e{715}*/
1979  assert( scip != NULL );
1980  assert( cons != NULL );
1981  assert( infervar != NULL );
1982  assert( bdchgidx != NULL );
1983  assert( result != NULL );
1984 
1985  SCIP_CALL( resolvePropagation(scip, cons, infervar, inferinfo, boundtype, bdchgidx, result) );
1986 
1987  return SCIP_OKAY;
1988 }
1989 
1990 
1991 /** variable rounding lock method of constraint handler */
1992 static
1993 SCIP_DECL_CONSLOCK(consLockOrbitope)
1994 { /*lint --e{715}*/
1995  SCIP_CONSDATA* consdata;
1996  SCIP_VAR*** vars;
1997  int i;
1998  int j;
1999  int nspcons;
2000  int nblocks;
2001 
2002  assert( scip != NULL );
2003  assert( conshdlr != NULL );
2004  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2005  assert( cons != NULL );
2006 
2007  consdata = SCIPconsGetData(cons);
2008  assert( consdata != NULL );
2009  assert( consdata->nspcons > 0 );
2010  assert( consdata->nblocks > 0 );
2011  assert( consdata->vars != NULL );
2012 
2013  SCIPdebugMessage("Locking method for orbitope constraint handler\n");
2014 
2015  nspcons = consdata->nspcons;
2016  nblocks = consdata->nblocks;
2017  vars = consdata->vars;
2018 
2019  /* add up locks and down locks on each variable */
2020  for (i = 0; i < nspcons; ++i)
2021  {
2022  for (j = 0; j < nblocks; ++j)
2023  SCIP_CALL( SCIPaddVarLocks(scip, vars[i][j], nlockspos + nlocksneg, nlockspos + nlocksneg) );
2024  }
2025 
2026  return SCIP_OKAY;
2027 }
2028 
2029 
2030 /** constraint display method of constraint handler */
2031 static
2032 SCIP_DECL_CONSPRINT(consPrintOrbitope)
2034  SCIP_CONSDATA* consdata;
2035  SCIP_VAR*** vars;
2036  int i;
2037  int j;
2038  int nspcons;
2039  int nblocks;
2040 
2041  assert( scip != NULL );
2042  assert( conshdlr != NULL );
2043  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2044  assert( cons != NULL );
2045 
2046  consdata = SCIPconsGetData(cons);
2047  assert( consdata != NULL );
2048  assert( consdata->nspcons > 0 );
2049  assert( consdata->nblocks > 0 );
2050  assert( consdata->vars != NULL );
2051 
2052  nspcons = consdata->nspcons;
2053  nblocks = consdata->nblocks;
2054  vars = consdata->vars;
2055 
2056  SCIPdebugMessage("Printing method for orbitope constraint handler\n");
2057 
2058  if ( consdata->ispart )
2059  SCIPinfoMessage(scip, file, "partOrbitope(");
2060  else
2061  SCIPinfoMessage(scip, file, "packOrbitope(");
2062 
2063  for (i = 0; i < nspcons; ++i)
2064  {
2065  for (j = 0; j < nblocks; ++j)
2066  {
2067  if ( j > 0 )
2068  SCIPinfoMessage(scip, file, ",");
2069  SCIPinfoMessage(scip, file, "%s", SCIPvarGetName(vars[i][j]));
2070  }
2071  if ( i < nspcons-1 )
2072  SCIPinfoMessage(scip, file, ".");
2073  }
2074  SCIPinfoMessage(scip, file, ")");
2075 
2076  return SCIP_OKAY;
2077 }
2078 
2079 
2080 /** constraint copying method of constraint handler */
2081 static
2082 SCIP_DECL_CONSCOPY(consCopyOrbitope)
2084  SCIP_CONSDATA* sourcedata;
2085  SCIP_VAR*** sourcevars;
2086  SCIP_VAR*** vars;
2087  int nspcons;
2088  int nblocks;
2089  int i;
2090  int k;
2091  int j;
2092 
2093  assert( scip != NULL );
2094  assert( cons != NULL );
2095  assert( sourcescip != NULL );
2096  assert( sourceconshdlr != NULL );
2097  assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
2098  assert( sourcecons != NULL );
2099  assert( varmap != NULL );
2100  assert( valid != NULL );
2101 
2102  *valid = TRUE;
2103 
2104  SCIPdebugMessage("Copying method for orbitope constraint handler.\n");
2105 
2106  sourcedata = SCIPconsGetData(sourcecons);
2107  assert( sourcedata != NULL );
2108  assert( sourcedata->nspcons > 0 );
2109  assert( sourcedata->nblocks > 0 );
2110  assert( sourcedata->vars != NULL );
2111 
2112  nspcons = sourcedata->nspcons;
2113  nblocks = sourcedata->nblocks;
2114  sourcevars = sourcedata->vars;
2115 
2116  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nspcons) );
2117  for (i = 0; i < nspcons && *valid; ++i)
2118  {
2119  SCIP_CALL( SCIPallocBufferArray(scip, &(vars[i]), nblocks) ); /*lint !e866*/
2120 
2121  for (j = 0; j < nblocks && *valid; ++j)
2122  {
2123  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[i][j], &(vars[i][j]), varmap, consmap, global, valid) );
2124  assert( !(*valid) || vars[i][j] != NULL );
2125  }
2126  }
2127 
2128  /* only create the target constraint, if all variables could be copied */
2129  if ( *valid )
2130  {
2131  /* create copied constraint */
2132  if ( name == NULL )
2133  name = SCIPconsGetName(sourcecons);
2134 
2135  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, name,
2136  vars, sourcedata->ispart, nspcons, nblocks, sourcedata->resolveprop,
2137  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2138  }
2139 
2140  /* free space; only up to row i if copying failed */
2141  assert( 0 <= i && i <= nspcons );
2142  for (k = 0; k < i; ++k)
2143  SCIPfreeBufferArray(scip, &vars[k]);
2144  SCIPfreeBufferArray(scip, &vars);
2145 
2146  return SCIP_OKAY;
2147 }
2148 
2149 
2150 /** constraint parsing method of constraint handler */
2151 static
2152 SCIP_DECL_CONSPARSE(consParseOrbitope)
2153 { /*lint --e{715}*/
2154  const char* s;
2155  SCIP_Bool ispart;
2156  char varname[SCIP_MAXSTRLEN];
2157  SCIP_VAR*** vars;
2158  SCIP_VAR* var;
2159  int nspcons;
2160  int maxnspcons;
2161  int nblocks;
2162  int maxnblocks;
2163  int k;
2164  int j;
2165 
2166  assert( success != NULL );
2167 
2168  *success = TRUE;
2169  s = str;
2170 
2171  /* skip white space */
2172  while ( *s != '\0' && isspace((unsigned char)*s) )
2173  ++s;
2174 
2175  ispart = FALSE;
2176  if ( strncmp(s, "partOrbitope(", 13) == 0 )
2177  ispart = TRUE;
2178  else
2179  {
2180  if ( strncmp(s, "packOrbitope(", 13) != 0 )
2181  {
2182  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error - expected \"partOrbitope\" or \"packOrbitope\": %s\n", s);
2183  *success = FALSE;
2184  return SCIP_OKAY;
2185  }
2186  }
2187  s += 13;
2188 
2189  /* loop through string */
2190  nspcons = 0;
2191  nblocks = 0;
2192  maxnspcons = 10;
2193  maxnblocks = 10;
2194 
2195  SCIP_CALL( SCIPallocBufferArray(scip, &vars, maxnspcons) );
2196  SCIP_CALL( SCIPallocBufferArray(scip, &(vars[0]), maxnblocks) );
2197 
2198  j = 0;
2199  do
2200  {
2201  /* find variable name */
2202  k = 0;
2203  while ( *s != '\0' && ! isspace((unsigned char)*s) && *s != ',' && *s != '.' && *s != ')' )
2204  varname[k++] = *s++;
2205  varname[k] = '\0';
2206 
2207  /* get variable */
2208  var = SCIPfindVar(scip, varname);
2209  if ( var == NULL )
2210  {
2211  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable <%s>\n", varname);
2212  *success = FALSE;
2213  return SCIP_OKAY;
2214  }
2215  vars[nspcons][j++] = var;
2216 
2217  if ( j > nblocks )
2218  {
2219  int newsize;
2220 
2221  if ( nspcons > 0 )
2222  {
2223  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "variables per row do not match.\n");
2224  *success = FALSE;
2225  return SCIP_OKAY;
2226  }
2227 
2228  nblocks = j;
2229  newsize = SCIPcalcMemGrowSize(scip, nblocks);
2230  SCIP_CALL( SCIPreallocBufferArray(scip, &(vars[nspcons]), newsize) ); /*lint !e866*/
2231  maxnblocks = newsize;
2232  assert( nblocks <= maxnblocks );
2233  }
2234 
2235  /* skip white space and ',' */
2236  while ( *s != '\0' && ( isspace((unsigned char)*s) || *s == ',' ) )
2237  ++s;
2238 
2239  /* begin new row if required */
2240  if ( *s == '.' )
2241  {
2242  ++nspcons;
2243  ++s;
2244 
2245  if ( nspcons >= maxnspcons )
2246  {
2247  int newsize;
2248 
2249  newsize = SCIPcalcMemGrowSize(scip, nspcons+1);
2250  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, newsize) );
2251  maxnspcons = newsize;
2252  }
2253  assert(nspcons < maxnspcons);
2254 
2255  SCIP_CALL( SCIPallocBufferArray(scip, &(vars[nspcons]), nblocks) ); /*lint !e866*/
2256  j = 0;
2257  }
2258  }
2259  while ( *s != ')' );
2260  ++nspcons;
2261 
2262  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, name, vars, ispart, nspcons, nblocks, TRUE,
2263  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2264 
2265  for (k = 0; k < nspcons; ++k)
2266  SCIPfreeBufferArray(scip, &vars[k]);
2267  SCIPfreeBufferArray(scip, &vars);
2268 
2269  return SCIP_OKAY;
2270 }
2271 
2272 
2273 /** constraint method of constraint handler which returns the variables (if possible) */
2274 static
2275 SCIP_DECL_CONSGETVARS(consGetVarsOrbitope)
2276 { /*lint --e{715}*/
2277  SCIP_CONSDATA* consdata;
2278 
2279  assert( cons != NULL );
2280  assert( success != NULL );
2281  assert( vars != NULL );
2282 
2283  consdata = SCIPconsGetData(cons);
2284  assert( consdata != NULL );
2285 
2286  if ( varssize < consdata->nblocks * consdata->nspcons )
2287  (*success) = FALSE;
2288  else
2289  {
2290  int cnt = 0;
2291  int i;
2292  int j;
2293 
2294  for (i = 0; i < consdata->nspcons; ++i)
2295  {
2296  for (j = 0; j < consdata->nblocks; ++j)
2297  vars[cnt++] = consdata->vars[i][j];
2298  }
2299  (*success) = TRUE;
2300  }
2301 
2302  return SCIP_OKAY;
2303 }
2304 
2305 
2306 /** constraint method of constraint handler which returns the number of variables (if possible) */
2307 static
2308 SCIP_DECL_CONSGETNVARS(consGetNVarsOrbitope)
2309 { /*lint --e{715}*/
2310  SCIP_CONSDATA* consdata;
2311 
2312  assert( cons != NULL );
2313 
2314  consdata = SCIPconsGetData(cons);
2315  assert( consdata != NULL );
2316 
2317  (*nvars) = consdata->nblocks * consdata->nspcons;
2318  (*success) = TRUE;
2319 
2320  return SCIP_OKAY;
2321 }
2322 
2323 
2324 /*
2325  * constraint specific interface methods
2326  */
2327 
2328 /** creates the handler for orbitope constraints and includes it in SCIP */
2330  SCIP* scip /**< SCIP data structure */
2331  )
2332 {
2333  SCIP_CONSHDLRDATA* conshdlrdata;
2334  SCIP_CONSHDLR* conshdlr;
2335 
2336  /* create orbitope constraint handler data */
2337  conshdlrdata = NULL;
2338 
2339  /* include constraint handler */
2343  consEnfolpOrbitope, consEnfopsOrbitope, consCheckOrbitope, consLockOrbitope,
2344  conshdlrdata) );
2345  assert(conshdlr != NULL);
2346 
2347  /* set non-fundamental callbacks via specific setter functions */
2348  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOrbitope, consCopyOrbitope) );
2349  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrbitope) );
2350  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOrbitope) );
2351  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOrbitope) );
2352  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOrbitope) );
2353  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolOrbitope, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
2354  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOrbitope) );
2355  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropOrbitope, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
2357  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOrbitope) );
2358  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOrbitope, consSepasolOrbitope, CONSHDLR_SEPAFREQ,
2360  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOrbitope) );
2361 
2362  return SCIP_OKAY;
2363 }
2364 
2365 
2366 /** creates and captures a orbitope constraint
2367  *
2368  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2369  */
2371  SCIP* scip, /**< SCIP data structure */
2372  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2373  const char* name, /**< name of constraint */
2374  SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
2375  SCIP_Bool ispart, /**< whether we deal with the partitioning case (packing otherwise) */
2376  int nspcons, /**< number of set partitioning/packing constraints <=> p */
2377  int nblocks, /**< number of symmetric variable blocks <=> q */
2378  SCIP_Bool resolveprop, /**< should propagation be resolved? */
2379  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2380  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2381  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2382  * Usually set to TRUE. */
2383  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2384  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2385  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2386  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2387  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2388  * Usually set to TRUE. */
2389  SCIP_Bool local, /**< is constraint only valid locally?
2390  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2391  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2392  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2393  * adds coefficients to this constraint. */
2394  SCIP_Bool dynamic, /**< is constraint subject to aging?
2395  * Usually set to FALSE. Set to TRUE for own cuts which
2396  * are separated as constraints. */
2397  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2398  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2399  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2400  * if it may be moved to a more global node?
2401  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2402  )
2403 {
2404  SCIP_CONSHDLR* conshdlr;
2405  SCIP_CONSDATA* consdata;
2406 
2407  /* find the orbitope constraint handler */
2408  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2409  if ( conshdlr == NULL )
2410  {
2411  SCIPerrorMessage("orbitope constraint handler not found\n");
2412  return SCIP_PLUGINNOTFOUND;
2413  }
2414 
2415  assert( nspcons > 0 );
2416  assert( nblocks > 0 );
2417 
2418  /* run some checks */
2419 #ifndef NDEBUG
2420  {
2421  SCIP_Real obj;
2422  int i;
2423  int j;
2424  for (i = 0; i < nspcons; ++i)
2425  {
2426  /* initialize obj to infinity */
2427  obj = SCIPinfinity(scip);
2428  for (j = 0; j < nblocks; ++j)
2429  {
2430  SCIP_Bool fixedZero;
2431  SCIP_VAR* var;
2432 
2433  var = vars[i][j];
2434  assert(var != NULL);
2435 
2436  /* all variables need to be binary */
2437  assert( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY );
2438 
2439  /* fixed variables have obj = 0; for variables fixed to 0, we assume that there is no
2440  problem (but we cannot always check it, e.g., when in the original problem
2441  variables were fixed and this problem was copied.) */
2442  fixedZero = ( SCIPisZero(scip, SCIPvarGetLbGlobal(var)) && SCIPisZero(scip, SCIPvarGetUbGlobal(var)) );
2443 
2444  /* check whether all variables in a row have the same objective */
2445  if ( ! fixedZero && SCIPisInfinity(scip, obj) )
2446  obj = SCIPvarGetObj(var);
2447  else
2448  {
2449  assert( fixedZero || SCIPisEQ(scip, obj, SCIPvarGetObj(var)) );
2450  }
2451  }
2452  }
2453  }
2454 #endif
2455 
2456  /* create constraint data */
2457  SCIP_CALL( consdataCreate(scip, &consdata, vars, nspcons, nblocks, ispart, resolveprop) );
2458 
2459  /* create constraint */
2460  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2461  local, modifiable, dynamic, removable, stickingatnode) );
2462 
2463  return SCIP_OKAY;
2464 }
2465 
2466 /** creates and captures an orbitope constraint
2467  * in its most basic variant, i. e., with all constraint flags set to their default values
2468  *
2469  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2470  */
2472  SCIP* scip, /**< SCIP data structure */
2473  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2474  const char* name, /**< name of constraint */
2475  SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
2476  SCIP_Bool ispart, /**< whether we deal with the partitioning case (packing otherwise) */
2477  int nspcons, /**< number of set partitioning/packing constraints <=> p */
2478  int nblocks, /**< number of symmetric variable blocks <=> q */
2479  SCIP_Bool resolveprop /**< should propagation be resolved? */
2480  )
2481 {
2482  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, name, vars, ispart, nspcons, nblocks, resolveprop,
2483  TRUE, TRUE, TRUE, TRUE, TRUE,
2484  FALSE, FALSE, FALSE, FALSE, FALSE) );
2485 
2486  return SCIP_OKAY;
2487 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:33158
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:22777
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41572
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41685
static SCIP_DECL_CONSPARSE(consParseOrbitope)
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:5588
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
static SCIP_RETCODE fixTriangle(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, int *nfixedvars)
#define CONSHDLR_SEPAFREQ
Definition: cons_orbitope.c:74
SCIP_RETCODE SCIPcreateConsOrbitope(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, SCIP_Bool ispart, int nspcons, int nblocks, SCIP_Bool resolveprop, 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 CONSHDLR_DELAYPROP
Definition: cons_orbitope.c:81
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:20589
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
#define SCIP_MAXSTRLEN
Definition: def.h:201
static void copyValues(SCIP *scip, SCIP_CONSDATA *consdata, SCIP_SOL *sol)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip.c:5634
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip.c:30877
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip.c:5246
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:7849
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5334
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:24320
#define CONSHDLR_SEPAPRIORITY
Definition: cons_orbitope.c:71
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5818
#define FALSE
Definition: def.h:56
static SCIP_DECL_CONSPRESOL(consPresolOrbitope)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define TRUE
Definition: def.h:55
static SCIP_DECL_CONSENFOPS(consEnfopsOrbitope)
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
static SCIP_DECL_CONSGETVARS(consGetVarsOrbitope)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip.c:5795
#define SCIP_CALL(x)
Definition: def.h:266
SCIP_RETCODE SCIPcreateConsBasicOrbitope(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, SCIP_Bool ispart, int nspcons, int nblocks, SCIP_Bool resolveprop)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:41972
#define CONSHDLR_DESC
Definition: cons_orbitope.c:70
SCIP_Bool SCIPallowDualReds(SCIP *scip)
Definition: scip.c:23083
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:42008
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:27888
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20556
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15737
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
#define CONSHDLR_NAME
Definition: cons_orbitope.c:69
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
#define CONSHDLR_PROPFREQ
Definition: cons_orbitope.c:75
#define CONSHDLR_PROP_TIMING
Definition: cons_orbitope.c:84
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7839
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7779
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:30967
static SCIP_DECL_CONSPRINT(consPrintOrbitope)
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:20554
#define CONSHDLR_ENFOPRIORITY
Definition: cons_orbitope.c:72
static SCIP_DECL_CONSENFOLP(consEnfolpOrbitope)
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:7769
static void computeSCTable(SCIP *scip, int nspcons, int nblocks, SCIP_Real **weights, int **cases, SCIP_Real **vals)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_orbitope.c:73
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
Definition: scip.c:24720
constraint handler for (partitioning/packing) orbitope constraints w.r.t. the full symmetric group ...
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:24342
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41585
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip.c:1781
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:7879
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:20574
static SCIP_RETCODE resolvePropagation(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *infervar, int inferinfo, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
#define CONSHDLR_NEEDSCONS
Definition: cons_orbitope.c:82
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3897
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15859
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip.c:5527
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7620
SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip.c:20669
static SCIP_RETCODE separateSCIs(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, SCIP_CONSDATA *consdata, SCIP_Bool *infeasible, int *nfixedvars, int *ncuts)
static SCIP_DECL_CONSCOPY(consCopyOrbitope)
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
static SCIP_DECL_CONSPROP(consPropOrbitope)
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip.c:5292
SCIP_RETCODE SCIPincludeConshdlrOrbitope(SCIP *scip)
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip.c:5192
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:32131
static SCIP_DECL_CONSSEPASOL(consSepasolOrbitope)
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:50
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7650
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:17116
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41611
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:997
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip.c:24772
#define SCIP_Bool
Definition: def.h:53
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbitope)
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:801
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7859
static SCIP_DECL_CONSDELETE(consDeleteOrbitope)
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:24369
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:7869
#define CONSHDLR_PRESOLTIMING
Definition: cons_orbitope.c:85
static SCIP_DECL_CONSLOCK(consLockOrbitope)
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1298
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, int *nfixedvars)
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip.c:5565
static SCIP_DECL_CONSTRANS(consTransOrbitope)
static SCIP_DECL_CONSCHECK(consCheckOrbitope)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
SCIP_Bool SCIPisSumEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:41806
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:5772
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1281
#define REALABS(x)
Definition: def.h:151
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:41721
#define CONSHDLR_MAXPREROUNDS
Definition: cons_orbitope.c:79
#define SCIP_Real
Definition: def.h:127
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7799
#define MIN(x, y)
Definition: memory.c:67
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip.c:27600
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip.c:11392
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:20568
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:27738
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:20571
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:19399
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:49
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
static SCIP_DECL_CONSRESPROP(consRespropOrbitope)
static SCIP_DECL_CONSGETNVARS(consGetNVarsOrbitope)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:24573
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:24436
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:41422
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5841
#define SCIPABORT()
Definition: def.h:238
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7789
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7819
#define CONSHDLR_EAGERFREQ
Definition: cons_orbitope.c:76
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR ***vars, int nspcons, int nblocks, SCIP_Bool ispart, SCIP_Bool resolveprop)
#define CONSHDLR_DELAYSEPA
Definition: cons_orbitope.c:80
static SCIP_DECL_CONSSEPALP(consSepalpOrbitope)