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-2014 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_DELAYPRESOL FALSE /**< should presolving method be delayed, if other presolvers found reductions? */
82 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
83 
84 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
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  consdata = SCIPconsGetData(cons);
749  assert( consdata != NULL );
750  assert( consdata->nspcons > 0 );
751  assert( consdata->nblocks > 0 );
752  assert( consdata->vars != NULL );
753 
754  *nfixedvars = 0;
755 
756  nspcons = consdata->nspcons;
757  nblocks = consdata->nblocks;
758  vars = consdata->vars;
759  ispart = consdata->ispart;
760 
761  /* fix upper right triangle if still necessary */
762  if ( ! consdata->istrianglefixed )
763  {
764  int nfixed = 0;
765  SCIP_CALL( fixTriangle(scip, cons, infeasible, &nfixed) );
766  *nfixedvars += nfixed;
767  }
768 
769  /* prepare further propagation */
770  SCIP_CALL( SCIPallocBufferArray(scip, &firstnonzeros, nspcons) );
771  SCIP_CALL( SCIPallocBufferArray(scip, &lastones, nspcons) );
772  SCIP_CALL( SCIPallocBufferArray(scip, &frontiersteps, nblocks) );
773 
774 #ifdef PRINT_MATRIX
775  SCIPdebugMessage("Matrix:\n");
776  printMatrix(scip, consdata);
777 #endif
778 
779  /* propagate */
780  lastoneprevrow = 0;
781  lastones[0] = 0;
782 
783  if ( ! ispart )
784  {
785  /* packing case: if entry (0,0) is fixed to 0 */
786  if ( SCIPvarGetUbLocal(vars[0][0]) < 0.5 )
787  {
788  lastoneprevrow = -1;
789  lastones[0] = -1;
790  }
791  }
792  nsteps = 0;
793 
794  for (i = 1; i < nspcons; ++i)
795  {
796  int lastcolumn;
797  int firstnonzeroinrow;
798  int lastoneinrow;
799  SCIP_Bool infrontier;
800 
801  /* last column considered as part of the bar: */
802  lastcolumn = nblocks - 1;
803  if ( lastcolumn > i )
804  lastcolumn = i;
805 
806  /* find first position not fixed to 0 (partitioning) or fixed to 1 (packing) */
807  firstnonzeroinrow = -1;
808  for (j = 0; j <= lastcolumn; ++j)
809  {
810  if ( ispart )
811  {
812  /* partitioning case: if variable is not fixed to 0 */
813  if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
814  {
815  firstnonzeroinrow = j;
816  break;
817  }
818  }
819  else
820  {
821  /* packing case: if variable is fixed to 1 */
822  if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
823  {
824  firstnonzeroinrow = j;
825  break;
826  }
827  }
828  }
829  /* if all variables are fixed to 0 in the partitioning case - should not happen */
830  if ( firstnonzeroinrow == -1 && ispart )
831  {
832  SCIPdebugMessage(" -> Infeasible node: all variables in row %d are fixed to 0.\n", i);
833  *infeasible = TRUE;
834  /* conflict should be analyzed by setppc constraint handler */
835  goto TERMINATE;
836  }
837  firstnonzeros[i] = firstnonzeroinrow;
838  assert( !ispart || firstnonzeroinrow >= 0 );
839  assert( -1 <= firstnonzeroinrow && firstnonzeroinrow <= lastcolumn );
840 
841  /* compute rightmost possible position for a 1 */
842  lastoneinrow = -1;
843  assert( !ispart || 0 <= lastoneprevrow );
844  assert( lastoneprevrow <= lastcolumn );
845 
846  /* if we are at right border or if entry in column lastoneprevrow+1 is fixed to 0 */
847  infrontier = FALSE;
848  assert( lastoneprevrow + 1 >= 0 );
849  if ( lastoneprevrow == nblocks-1 || SCIPvarGetUbLocal(vars[i][lastoneprevrow+1]) < 0.5 ) /*lint !e679*/
850  lastoneinrow = lastoneprevrow;
851  else
852  {
853  lastoneinrow = lastoneprevrow + 1;
854  frontiersteps[nsteps++] = i;
855  infrontier = TRUE;
856  }
857 
858  /* store lastoneinrow */
859  assert( !ispart || 0 <= lastoneinrow );
860  assert( lastoneinrow <= lastcolumn );
861  lastones[i] = lastoneinrow;
862 
863  /* check whether we are infeasible */
864  if ( firstnonzeroinrow > lastoneinrow )
865  {
866  int k;
867 
868 #ifdef SCIP_DEBUG
869  if ( ispart )
870  {
871  SCIPdebugMessage(" -> Infeasible node: row %d, leftmost nonzero at %d, rightmost 1 at %d\n",
872  i, firstnonzeroinrow, lastoneinrow);
873  }
874  else
875  {
876  SCIPdebugMessage(" -> Infeasible node: row %d, 1 at %d, rightmost position for 1 at %d\n",
877  i, firstnonzeroinrow, lastoneinrow);
878  }
879 #endif
880  /* check if conflict analysis is applicable */
882  {
883  /* conflict analysis only applicable in SOLVING stage */
884  assert( SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPinProbing(scip) );
885 
886  /* perform conflict analysis */
888 
889  if ( ispart )
890  {
891  /* add bounds (variables fixed to 0) that result in the first nonzero entry */
892  for (j = 0; j <= lastcolumn; ++j)
893  {
894  /* add varaibles in row up to the first variable fixed to 0 */
895  if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
896  break;
897 
898  assert( SCIPvarGetUbLocal(vars[i][j]) < 0.5 );
899  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
900  }
901  }
902  else
903  {
904  /* add bounds that result in the last one - check top left entry for packing case */
905  if ( lastones[0] == -1 )
906  {
907  assert( SCIPvarGetUbLocal(vars[0][0]) < 0.5 );
908  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[0][0]) );
909  }
910 
911  /* mark variable fixed to 1 */
912  assert( SCIPvarGetLbLocal(vars[i][firstnonzeroinrow]) > 0.5 );
913  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][firstnonzeroinrow]) );
914  }
915 
916  /* add bounds that result in the last one - pass through rows */
917  for (k = 1; k < i; ++k)
918  {
919  int l;
920  l = lastones[k] + 1;
921 
922  /* if the frontier has not moved and we are not beyond the matrix boundaries */
923  if ( l <= nblocks-1 && l <= k && lastones[k-1] == lastones[k] )
924  {
925  assert( SCIPvarGetUbLocal(vars[k][l]) < 0.5 );
926  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][l]) );
927  }
928  }
929  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
930  }
931 
932  *infeasible = TRUE;
933  goto TERMINATE;
934  }
935 
936  /* fix entries beyond the last possible position for a 1 in the row to 0 (see Lemma 1 in the paper) */
937  for (j = lastoneinrow+1; j <= lastcolumn; ++j)
938  {
939  /* if the entry is not yet fixed to 0 */
940  if ( SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
941  {
942  SCIP_Bool tightened;
943  int inferInfo;
944 
945  SCIPdebugMessage(" -> Fixing entry (%d,%d) to 0.\n", i, j);
946 
947  tightened = FALSE;
948 
949  /* fix variable to 0 and store position of (i,lastoneinrow+1) for conflict resolution */
950  inferInfo = i * nblocks + lastoneinrow + 1;
951  /* correction according to Lemma 1 in the paper (second part): store (i,lastoneinrow+2) */
952  if ( !infrontier )
953  ++inferInfo;
954  SCIP_CALL( SCIPinferBinvarCons(scip, vars[i][j], FALSE, cons, inferInfo, infeasible, &tightened) );
955 
956  /* if entry is fixed to one -> infeasible node */
957  if ( *infeasible )
958  {
959  SCIPdebugMessage(" -> Infeasible node: row %d, 1 in column %d beyond rightmost position %d\n", i, j, lastoneinrow);
960  /* check if conflict analysis is applicable */
962  {
963  int k;
964 
965  /* conflict analysis only applicable in SOLVING stage */
966  assert(SCIPgetStage(scip) == SCIP_STAGE_SOLVING || SCIPinProbing(scip));
967 
968  /* perform conflict analysis */
970 
971  /* add current bound */
972  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
973 
974  /* add bounds that result in the last one - check top left entry for packing case */
975  if ( ! ispart && lastones[0] == -1 )
976  {
977  assert( SCIPvarGetUbLocal(vars[0][0]) < 0.5 );
978  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[0][0]) );
979  }
980 
981  /* add bounds that result in the last one - pass through rows */
982  for (k = 1; k < i; ++k)
983  {
984  int l;
985  l = lastones[k] + 1;
986 
987  /* if the frontier has not moved and we are not beyond the matrix boundaries */
988  if ( l <= nblocks-1 && l <= k && lastones[k-1] == lastones[k] )
989  {
990  assert( SCIPvarGetUbLocal(vars[k][l]) < 0.5 );
991  SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][l]) );
992  }
993  }
994  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
995  }
996 
997  goto TERMINATE;
998  }
999  if ( tightened )
1000  ++(*nfixedvars);
1001  }
1002  }
1003 
1004  lastoneprevrow = lastoneinrow;
1005  }
1006 
1007  /* check whether fixing any entry to 0 results in a contradiction -> loop through rows in frontiersteps (a.k.a. gamma) */
1008  for (j = 0; j < nsteps; ++j)
1009  {
1010  int s;
1011  int lastoneinrow;
1012 
1013  s = frontiersteps[j];
1014  lastoneinrow = lastones[s];
1015  /* note for packing case: if we are in a frontier step then lastoneinrow >= 0 */
1016  assert( 0 <= lastoneinrow && lastoneinrow < nblocks );
1017 
1018  /* if entry is not fixed */
1019  if ( SCIPvarGetLbLocal(vars[s][lastoneinrow]) < 0.5 && SCIPvarGetUbLocal(vars[s][lastoneinrow]) > 0.5 )
1020  {
1021  int betaprev;
1022  betaprev = lastoneinrow - 1;
1023 
1024  /* loop through rows below s */
1025  for (i = s+1; i < nspcons; ++i)
1026  {
1027  int beta;
1028  beta = -2;
1029 
1030  assert( betaprev + 1 >= 0 );
1031  if ( betaprev == nblocks-1 || SCIPvarGetUbLocal(vars[i][betaprev+1]) < 0.5 ) /*lint !e679*/
1032  beta = betaprev;
1033  else
1034  beta = betaprev + 1;
1035  assert( -1 <= beta && beta < nblocks );
1036 
1037  if ( firstnonzeros[i] > beta )
1038  {
1039  SCIP_Bool tightened;
1040  int inferInfo;
1041 
1042  /* can fix (s,lastoneinrow) (a.k.a (s,alpha)) to 1
1043  * (do not need to fix other entries to 0, since they will be
1044  * automatically fixed by SCIPtightenVarLb.)
1045  */
1046  assert( SCIPvarGetLbLocal(vars[s][lastoneinrow]) < 0.5 );
1047  SCIPdebugMessage(" -> Fixing entry (%d,%d) to 1.\n", s, lastoneinrow);
1048 
1049  tightened = FALSE;
1050 
1051  /* store position (i,firstnonzeros[i]) */
1052  inferInfo = nblocks * nspcons + i * nblocks + firstnonzeros[i];
1053  SCIP_CALL( SCIPinferBinvarCons(scip, vars[s][lastoneinrow], TRUE, cons, inferInfo, infeasible, &tightened) );
1054 
1055  assert( !(*infeasible) );
1056  if ( tightened )
1057  ++(*nfixedvars);
1058  break;
1059  }
1060  betaprev = beta;
1061  }
1062  }
1063  }
1064 
1065  TERMINATE:
1066  SCIPfreeBufferArray(scip, &frontiersteps);
1067  SCIPfreeBufferArray(scip, &lastones);
1068  SCIPfreeBufferArray(scip, &firstnonzeros);
1069 
1070  return SCIP_OKAY;
1071 }
1072 
1073 
1074 /** Propagation conflict resolving method of propagator
1075  *
1076  * In this function we use that the propagation method above implicitly propagates SCIs, i.e., every
1077  * fixing can also be gotten via an SCI-fixing.
1078  *
1079  * Since the storage of an integer is not enough to store the complete information about the fixing
1080  * nor a complete shifted column, we have to use the linear time algorithm for SCIs.
1081  *
1082  * The inferinfo integer is set as follows:
1083  *
1084  * - If a shifted column is fixed to 0 and the corresponding bar does not necessarily has value 1
1085  * then we fix these entries to 0 and inferinfo is i * nblocks + j, where (i,j) is the leader of the
1086  * bar. The SCI depends on whether i is in Gamma or not (see Lemma 1 in the paper and the comments
1087  * above).
1088  *
1089  * - If a bar has value 1 and the shifted column has one entry that is not fixed, it can be fixed to
1090  * 1 and inferinfo is (nspcons*nblocks) + i * nblocks + j, where (i,j) is the leader of the bar; see
1091  * Proposition 1 (2c).
1092  */
1093 static
1095  SCIP* scip, /**< SCIP data structure */
1096  SCIP_CONS* cons, /**< constraint that inferred the bound change */
1097  SCIP_VAR* infervar, /**< variable that was deduced */
1098  int inferinfo, /**< inference information */
1099  SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */
1100  SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
1101  SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
1102  )
1103 { /*lint --e{715}*/
1104  SCIP_CONSDATA* consdata;
1105  SCIP_Real** vals;
1106  SCIP_Real** weights;
1107  SCIP_VAR*** vars;
1108  SCIP_Bool ispart;
1109  int** cases;
1110 
1111  int i;
1112  int j;
1113  int nspcons;
1114  int nblocks;
1115 
1116  assert( scip != NULL );
1117  assert( cons != NULL );
1118  assert( result != NULL );
1119 
1120  consdata = SCIPconsGetData(cons);
1121  assert( consdata != NULL );
1122  assert( consdata->nspcons > 0 );
1123  assert( consdata->nblocks > 0 );
1124  assert( consdata->vars != NULL );
1125  assert( consdata->vals != NULL );
1126  assert( consdata->weights != NULL );
1127  assert( consdata->cases != NULL );
1128  assert( consdata->istrianglefixed );
1129 
1130  *result = SCIP_DIDNOTFIND;
1131  if ( ! consdata->resolveprop )
1132  return SCIP_OKAY;
1133 
1134  nspcons = consdata->nspcons;
1135  nblocks = consdata->nblocks;
1136  vars = consdata->vars;
1137  vals = consdata->vals;
1138  weights = consdata->weights;
1139  ispart = consdata->ispart;
1140  cases = consdata->cases;
1141 
1142  SCIPdebugMessage("Propagation resolution method of orbitope constraint using orbitopal fixing\n");
1143 
1144  /* fill table */
1145  for (i = 0; i < nspcons; ++i)
1146  {
1147  int lastcolumn;
1148 
1149  /* last column considered as part of the bar: */
1150  lastcolumn = nblocks - 1;
1151  if ( lastcolumn > i )
1152  lastcolumn = i;
1153  for (j = 0; j <= lastcolumn; ++j)
1154  {
1155  /* if the variable was fixed to zero at conflict time */
1156  if ( SCIPvarGetUbAtIndex(vars[i][j], bdchgidx, FALSE) < 0.5 )
1157  vals[i][j] = 0.0;
1158  else
1159  {
1160  /* if the variable was fixed to one at conflict time */
1161  if ( SCIPvarGetLbAtIndex(vars[i][j], bdchgidx, FALSE) > 0.5 )
1162  vals[i][j] = 2.0;
1163  else
1164  vals[i][j] = 1.0;
1165  }
1166  }
1167  }
1168 
1169 #ifdef PRINT_MATRIX
1170  SCIPdebugMessage("Matrix:\n");
1171  printMatrix(scip, consdata);
1172 #endif
1173 
1174  /* computation of table: this now minimizes the value of the shifted column */
1175  assert( consdata->istrianglefixed );
1176  computeSCTable(scip, nspcons, nblocks, weights, cases, vals);
1177 
1178  /* if we fixed variables in the bar to zero */
1179  assert( inferinfo >= 0 && inferinfo < 2 * nspcons * nblocks );
1180  if ( inferinfo < nspcons * nblocks )
1181  {
1182  int p1;
1183  int p2;
1184 #ifdef SCIP_DEBUG
1185  char str[SCIP_MAXSTRLEN];
1186  char tmpstr[SCIP_MAXSTRLEN];
1187 #endif
1188 
1189  i = (int) (inferinfo / nblocks);
1190  j = inferinfo % nblocks;
1191  assert( 0 <= i && i < nspcons );
1192  assert( 0 <= j && j < nblocks );
1193 
1194  /* find SCI with value 0 */
1195  assert( weights[i-1][j-1] < 0.5 );
1196 
1197  SCIPdebugMessage(" -> reason for x[%d][%d] = ... = x[%d][%d] = 0 was the following SC:\n", i, j, i, MIN(i,nblocks));
1198 #ifdef SCIP_DEBUG
1199  str[0] = '\0';
1200 #endif
1201 
1202  p1 = i-1;
1203  p2 = j-1;
1204  do
1205  {
1206  assert( cases[p1][p2] != -1 );
1207  assert( p1 >= 0 && p1 < i );
1208  assert( p2 >= 0 && p2 < j );
1209 
1210  /* if case 1 */
1211  if ( cases[p1][p2] == 1 )
1212  --p2; /* decrease column */
1213  else
1214  {
1215  /* case 2 or 3: */
1216  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
1217  assert( SCIPvarGetUbAtIndex(vars[p1][p2], bdchgidx, FALSE) < 0.5 );
1218  SCIP_CALL( SCIPaddConflictUb(scip, vars[p1][p2], bdchgidx) );
1219  *result = SCIP_SUCCESS;
1220 
1221 #ifdef SCIP_DEBUG
1222  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", p1, p2);
1223  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1224 #endif
1225 
1226  if ( cases[p1][p2] == 3 )
1227  break;
1228  }
1229  --p1; /* decrease row */
1230  }
1231  while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
1232  assert( cases[p1][p2] == 3 );
1233 
1234 #ifdef SCIP_DEBUG
1235  SCIPdebugMessage("%s\n", str);
1236 #endif
1237  }
1238  else
1239  {
1240  int k;
1241  int p1;
1242  int p2;
1243 #ifndef NDEBUG
1244  int pos1;
1245  int pos2;
1246 #endif
1247 #ifdef SCIP_DEBUG
1248  char str[SCIP_MAXSTRLEN];
1249  char tmpstr[SCIP_MAXSTRLEN];
1250 #endif
1251 
1252  /* if we fixed a variable in the SC to 1 */
1253  inferinfo -= nspcons * nblocks;
1254  i = (int) inferinfo / nblocks;
1255  j = inferinfo % nblocks;
1256  assert( 0 <= i && i < nspcons );
1257  assert( 0 <= j && j < nblocks );
1258 
1259  /* In rare cases it might happen that we fixed a variable to 1, but the node later becomes infeasible by globally
1260  * fixing variables to 0. In this case, it might happen that we find a SC with value 0 instead of 1. We then
1261  * cannot use this SC to repropagate (and do not know how to reconstruct the original reasoning). */
1262  if ( weights[i-1][j-1] > 0.5 && weights[i-1][j-1] < 1.5 )
1263  {
1264  SCIPdebugMessage(" -> reason for x[%d][%d] = 1 was the following SC:\n", i, j);
1265 #ifdef SCIP_DEBUG
1266  (void) SCIPsnprintf(str, SCIP_MAXSTRLEN, "SC:");
1267 #endif
1268 
1269  p1 = i-1;
1270  p2 = j-1;
1271 #ifndef NDEBUG
1272  pos1 = -1;
1273  pos2 = -1;
1274 #endif
1275  do
1276  {
1277  assert( cases[p1][p2] != -1 );
1278  assert( p1 >= 0 && p1 < i );
1279  assert( p2 >= 0 && p2 < j );
1280 
1281  /* if case 1 */
1282  if ( cases[p1][p2] == 1 )
1283  --p2; /* decrease column */
1284  else
1285  {
1286  /* case 2 or 3: reason are formed by variables in SC fixed to 0 */
1287  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
1288  if ( SCIPvarGetUbAtIndex(vars[p1][p2], bdchgidx, FALSE) < 0.5 )
1289  {
1290  SCIP_CALL( SCIPaddConflictUb(scip, vars[p1][p2], bdchgidx) );
1291  *result = SCIP_SUCCESS;
1292 
1293 #ifdef SCIP_DEBUG
1294  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", p1, p2);
1295  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1296 #endif
1297  }
1298 #ifndef NDEBUG
1299  else
1300  {
1301  assert( SCIPvarGetLbAtIndex(vars[p1][p2], bdchgidx, FALSE) < 0.5 );
1302  assert( pos1 == -1 && pos2 == -1 );
1303  pos1 = p1;
1304  pos2 = p2;
1305  }
1306 #endif
1307  if ( cases[p1][p2] == 3 )
1308  break;
1309  }
1310  --p1; /* decrease row */
1311  }
1312  while ( p1 >= 0 ); /* should always be true, i.e., the break should end the loop */
1313  assert( cases[p1][p2] == 3 );
1314  assert( pos1 >= 0 && pos2 >= 0 );
1315 
1316  /* distinguish partitioning/packing */
1317  if ( ispart )
1318  {
1319  /* partitioning case */
1320 #ifdef SCIP_DEBUG
1321  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " before bar: ");
1322  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1323 #endif
1324  /* add variables before the bar in the partitioning case */
1325  for (k = 0; k < j; ++k)
1326  {
1327  assert( SCIPvarGetUbAtIndex(vars[i][k], bdchgidx, FALSE) < 0.5 );
1328  SCIP_CALL( SCIPaddConflictUb(scip, vars[i][k], bdchgidx) );
1329  *result = SCIP_SUCCESS;
1330 #ifdef SCIP_DEBUG
1331  (void) SCIPsnprintf(tmpstr, SCIP_MAXSTRLEN, " (%d,%d)", i, k);
1332  (void) strncat(str, tmpstr, SCIP_MAXSTRLEN);
1333 #endif
1334  }
1335 
1336 #ifdef SCIP_DEBUG
1337  SCIPdebugMessage("%s\n", str);
1338 #endif
1339  }
1340  else
1341  {
1342  /* packing case */
1343  int lastcolumn;
1344 
1345  /* last column considered as part of the bar: */
1346  lastcolumn = nblocks - 1;
1347  if ( lastcolumn > i )
1348  lastcolumn = i;
1349 
1350  /* search for variable in the bar that is fixed to 1 in the packing case */
1351  for (k = j; k <= lastcolumn; ++k)
1352  {
1353  if ( SCIPvarGetLbAtIndex(vars[i][k], bdchgidx, FALSE) > 0.5 )
1354  {
1355  SCIP_CALL( SCIPaddConflictLb(scip, vars[i][k], bdchgidx) );
1356  *result = SCIP_SUCCESS;
1357  SCIPdebugMessage(" and variable x[%d][%d] fixed to 1.\n", i, k);
1358  break;
1359  }
1360  }
1361  }
1362  }
1363  }
1364 
1365  return SCIP_OKAY;
1366 }
1367 
1368 
1369 /*
1370  * Callback methods of constraint handler
1371  */
1372 
1373 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1374 static
1375 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbitope)
1376 { /*lint --e{715}*/
1377  assert(scip != NULL);
1378  assert(conshdlr != NULL);
1379  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1380 
1381  /* call inclusion method of constraint handler */
1383 
1384  *valid = TRUE;
1385 
1386  return SCIP_OKAY;
1387 }
1388 
1389 /** frees specific constraint data */
1390 static
1391 SCIP_DECL_CONSDELETE(consDeleteOrbitope)
1392 { /*lint --e{715}*/
1393  assert(conshdlr != NULL);
1394  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1395 
1396  SCIP_CALL( consdataFree(scip, consdata) );
1397 
1398  return SCIP_OKAY;
1399 }
1400 
1401 /** transforms constraint data into data belonging to the transformed problem */
1402 static
1403 SCIP_DECL_CONSTRANS(consTransOrbitope)
1404 { /*lint --e{715}*/
1405  SCIP_CONSDATA* sourcedata;
1406  SCIP_CONSDATA* targetdata;
1407 
1408  assert(conshdlr != NULL);
1409  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1410  assert(SCIPgetStage(scip) == SCIP_STAGE_TRANSFORMING);
1411  assert(sourcecons != NULL);
1412  assert(targetcons != NULL);
1413 
1414  sourcedata = SCIPconsGetData(sourcecons);
1415  assert(sourcedata != NULL);
1416 
1417  /* create linear constraint data for target constraint */
1418  SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->vars, sourcedata->nspcons, sourcedata->nblocks,
1419  sourcedata->ispart, sourcedata->resolveprop) );
1420 
1421  /* create target constraint */
1422  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
1423  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1424  SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
1425  SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
1426  SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1427 
1428  return SCIP_OKAY;
1429 }
1430 
1431 /** separation method of constraint handler for LP solutions */
1432 static
1433 SCIP_DECL_CONSSEPALP(consSepalpOrbitope)
1434 { /*lint --e{715}*/
1435  assert( scip != NULL );
1436  assert( conshdlr != NULL );
1437  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1438  assert( result != NULL );
1439 
1440  *result = SCIP_DIDNOTRUN;
1441 
1442  /* if solution is not integer */
1443  if ( SCIPgetNLPBranchCands(scip) > 0 )
1444  {
1445  SCIP_Bool infeasible;
1446  int nfixedvars = 0;
1447  int ncuts = 0;
1448  int c;
1449 
1450  *result = SCIP_DIDNOTFIND;
1451  infeasible = FALSE;
1452 
1453  /* loop through constraints */
1454  for (c = 0; c < nusefulconss && ! infeasible; c++)
1455  {
1456  SCIP_CONSDATA* consdata;
1457 
1458  assert( conss[c] != NULL );
1459 
1460  /* get data of constraint */
1461  consdata = SCIPconsGetData(conss[c]);
1462  assert( consdata != NULL );
1463 
1464  /* get solution */
1465  copyValues(scip, consdata, NULL);
1466  SCIPdebugMessage("Separating SCIs for orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1467 
1468  /* separate */
1469  SCIP_CALL( separateSCIs(scip, conshdlr, conss[c], consdata, &infeasible, &nfixedvars, &ncuts) );
1470  }
1471  if ( infeasible )
1472  {
1473  SCIPdebugMessage("Infeasible node.\n");
1474  *result = SCIP_CUTOFF;
1475  }
1476  else if ( nfixedvars > 0 )
1477  {
1478  SCIPdebugMessage("Fixed %d variables.\n", nfixedvars);
1479  *result = SCIP_REDUCEDDOM;
1480  }
1481  else if ( ncuts > 0 )
1482  {
1483  SCIPdebugMessage("Separated %d SCIs.\n", ncuts);
1484  *result = SCIP_SEPARATED;
1485  }
1486  else
1487  {
1488  SCIPdebugMessage("No violated SCI found.\n");
1489  }
1490  }
1491 
1492  return SCIP_OKAY;
1493 }
1494 
1495 /** separation method of constraint handler for arbitrary primal solutions */
1496 static
1497 SCIP_DECL_CONSSEPASOL(consSepasolOrbitope)
1498 { /*lint --e{715}*/
1499  SCIP_Bool infeasible = FALSE;
1500  int nfixedvars = 0;
1501  int ncuts = 0;
1502  int c;
1503 
1504  assert( scip != NULL );
1505  assert( conshdlr != NULL );
1506  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1507  assert( result != NULL );
1508 
1509  *result = SCIP_DIDNOTFIND;
1510 
1511  /* loop through constraints */
1512  for (c = 0; c < nusefulconss && ! infeasible; c++)
1513  {
1514  SCIP_CONSDATA* consdata;
1515 
1516  /* get data of constraint */
1517  assert( conss[c] != NULL );
1518  consdata = SCIPconsGetData(conss[c]);
1519  assert( consdata != NULL );
1520 
1521  /* get solution */
1522  copyValues(scip, consdata, sol);
1523  SCIPdebugMessage("Separating SCIs (solution) for orbitope constraint <%s> \n", SCIPconsGetName(conss[c]));
1524 
1525  /* separate */
1526  SCIP_CALL( separateSCIs(scip, conshdlr, conss[c], consdata, &infeasible, &nfixedvars, &ncuts) );
1527  }
1528 
1529  if ( infeasible )
1530  {
1531  SCIPdebugMessage("Infeasible node.\n");
1532  *result = SCIP_CUTOFF;
1533  }
1534  else if ( nfixedvars > 0 )
1535  {
1536  SCIPdebugMessage("Fixed %d variables.\n", nfixedvars);
1537  *result = SCIP_REDUCEDDOM;
1538  }
1539  else if ( ncuts > 0 )
1540  {
1541  SCIPdebugMessage("Separated %d SCIs.\n", ncuts);
1542  *result = SCIP_SEPARATED;
1543  }
1544  else
1545  {
1546  SCIPdebugMessage("No violated SCI found.\n");
1547  }
1548 
1549  return SCIP_OKAY;
1550 }
1551 
1552 
1553 /** constraint enforcing method of constraint handler for LP solutions */
1554 static
1555 SCIP_DECL_CONSENFOLP(consEnfolpOrbitope)
1556 { /*lint --e{715}*/
1557  SCIP_Bool infeasible = FALSE;
1558  int nfixedvars = 0;
1559  int ncuts = 0;
1560  int c;
1561 
1562  assert( scip != NULL );
1563  assert( conshdlr != NULL );
1564  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1565  assert( result != NULL );
1566 
1567  *result = SCIP_FEASIBLE;
1568 
1569  /* we have a negative priority, so we should come after the integrality conshdlr */
1570  assert( SCIPgetNLPBranchCands(scip) == 0 );
1571 
1572  /* loop through constraints */
1573  for (c = 0; c < nusefulconss && ! infeasible; c++)
1574  {
1575  SCIP_CONSDATA* consdata;
1576 
1577  assert( conss[c] != NULL );
1578 
1579  /* get data of constraint */
1580  consdata = SCIPconsGetData(conss[c]);
1581  assert( consdata != NULL );
1582 
1583  /* get solution */
1584  copyValues(scip, consdata, NULL);
1585  SCIPdebugMessage("Enforcing for orbitope constraint <%s>\n", SCIPconsGetName(conss[c]));
1586 
1587  /* separate */
1588  SCIP_CALL( separateSCIs(scip, conshdlr, conss[c], consdata, &infeasible, &nfixedvars, &ncuts) );
1589  }
1590 
1591  if ( infeasible )
1592  {
1593  SCIPdebugMessage("Infeasible node.\n");
1594  *result = SCIP_CUTOFF;
1595  }
1596  else if ( nfixedvars > 0 )
1597  {
1598  SCIPdebugMessage("Fixed %d variables.\n", nfixedvars);
1599  *result = SCIP_REDUCEDDOM;
1600  }
1601  else if ( ncuts > 0 )
1602  {
1603  SCIPdebugMessage("Separated %d SCIs during enforcement.\n", ncuts);
1604  *result = SCIP_SEPARATED;
1605  }
1606  else
1607  {
1608  SCIPdebugMessage("No violated SCI found during enforcement.\n");
1609  }
1610 
1611  return SCIP_OKAY;
1612 }
1613 
1614 
1615 /** constraint enforcing method of constraint handler for pseudo solutions */
1616 static
1617 SCIP_DECL_CONSENFOPS(consEnfopsOrbitope)
1618 { /*lint --e{715}*/
1619  int c;
1620 
1621  assert( scip != NULL );
1622  assert( conshdlr != NULL );
1623  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1624  assert( result != NULL );
1625 
1626  *result = SCIP_FEASIBLE;
1627  if ( objinfeasible || solinfeasible )
1628  return SCIP_OKAY;
1629 
1630  /* loop through constraints */
1631  for (c = 0; c < nconss; ++c)
1632  {
1633  SCIP_CONSDATA* consdata;
1634  SCIP_Real** weights;
1635  SCIP_Real** vals;
1636  SCIP_CONS* cons;
1637  int** cases;
1638  int nspcons;
1639  int nblocks;
1640  int i;
1641  int j;
1642 
1643  /* get data of constraint */
1644  cons = conss[c];
1645  assert( cons != 0 );
1646  consdata = SCIPconsGetData(cons);
1647 
1648  assert( consdata != NULL );
1649  assert( consdata->nspcons > 0 );
1650  assert( consdata->nblocks > 0 );
1651  assert( consdata->vals != NULL );
1652  assert( consdata->weights != NULL );
1653  assert( consdata->cases != NULL );
1654 
1655  /* check for upper right triangle */
1656  if ( ! consdata->istrianglefixed )
1657  {
1658  SCIP_Bool infeasible = FALSE;
1659  int nfixedvars = 0;
1660 
1661  SCIP_CALL( fixTriangle(scip, cons, &infeasible, &nfixedvars) );
1662  if ( infeasible )
1663  {
1664  *result = SCIP_CUTOFF;
1665  return SCIP_OKAY;
1666  }
1667  if ( nfixedvars > 0 )
1668  {
1669  *result = SCIP_REDUCEDDOM;
1670  return SCIP_OKAY;
1671  }
1672  }
1673 
1674  nspcons = consdata->nspcons;
1675  nblocks = consdata->nblocks;
1676  vals = consdata->vals;
1677  weights = consdata->weights;
1678  cases = consdata->cases;
1679 
1680  /* get solution */
1681  copyValues(scip, consdata, NULL);
1682  SCIPdebugMessage("Enforcing (pseudo solutions) for orbitope constraint <%s>\n", SCIPconsGetName(conss[c]));
1683 
1684  /* compute table */
1685  assert( consdata->istrianglefixed );
1686  computeSCTable(scip, nspcons, nblocks, weights, cases, vals);
1687 
1688  /* loop through rows */
1689  for (i = 1; i < nspcons; ++i)
1690  {
1691  SCIP_Real bar = 0.0;
1692  int lastcolumn;
1693 
1694  lastcolumn = nblocks - 1;
1695 
1696  /* last column considered as part of the bar: */
1697  if ( lastcolumn > i )
1698  lastcolumn = i;
1699 
1700  /* traverse row from right to left */
1701  for (j = lastcolumn; j > 1; --j)
1702  {
1703  bar += vals[i][j];
1704  assert( SCIPisIntegral(scip, vals[i][j]) );
1705 
1706  /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
1707  if ( SCIPisGT(scip, bar - weights[i-1][j-1], 0.0) )
1708  {
1709  SCIPdebugMessage("Solution is infeasible.\n");
1710  *result = SCIP_INFEASIBLE;
1711  return SCIP_OKAY;
1712  }
1713  }
1714  }
1715  }
1716 
1717  return SCIP_OKAY;
1718 }
1719 
1720 
1721 /** feasibility check method of constraint handler for integral solutions */
1722 static
1723 SCIP_DECL_CONSCHECK(consCheckOrbitope)
1724 { /*lint --e{715}*/
1725  int c;
1726 
1727  assert( scip != NULL );
1728  assert( conshdlr != NULL );
1729  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1730  assert( result != NULL );
1731 
1732  *result = SCIP_FEASIBLE;
1733 
1734  /* loop through constraints */
1735  for (c = 0; c < nconss; ++c)
1736  {
1737  SCIP_CONSDATA* consdata;
1738  SCIP_VAR*** vars;
1739  SCIP_Real** vals;
1740  SCIP_Real** weights;
1741  int** cases;
1742  int nspcons;
1743  int nblocks;
1744  int i;
1745  int j;
1746 
1747  /* get data of constraint */
1748  assert( conss[c] != 0 );
1749  consdata = SCIPconsGetData(conss[c]);
1750 
1751  assert( consdata != NULL );
1752  assert( consdata->nspcons > 0 );
1753  assert( consdata->nblocks > 0 );
1754  assert( consdata->vars != NULL );
1755  assert( consdata->vals != NULL );
1756  assert( consdata->weights != NULL );
1757  assert( consdata->cases != NULL );
1758 
1759  nspcons = consdata->nspcons;
1760  nblocks = consdata->nblocks;
1761  vars = consdata->vars;
1762  vals = consdata->vals;
1763  weights = consdata->weights;
1764  cases = consdata->cases;
1765 
1766  /* get solution */
1767  copyValues(scip, consdata, sol);
1768  SCIPdebugMessage("Checking orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1769 
1770  /* check upper right triangle (if not yet fixed to zero or in debug mode */
1771 #ifdef NDEBUG
1772  if ( ! consdata->istrianglefixed )
1773 #endif
1774  {
1775  int diagsize;
1776 
1777  /* get last row of triangle */
1778  diagsize = nblocks;
1779  if ( nspcons < nblocks )
1780  diagsize = nspcons;
1781 
1782  /* check variables */
1783  for (i = 0; i < diagsize; ++i)
1784  {
1785  for (j = i+1; j < nblocks; ++j)
1786  {
1787  if ( ! SCIPisFeasZero(scip, vals[i][j]) )
1788  {
1789  if ( printreason )
1790  SCIPinfoMessage(scip, NULL, "variable x[%d][%d] = %f on upper right nonzero.\n", i, j, vals[i][j]);
1791  *result = SCIP_INFEASIBLE;
1792  return SCIP_OKAY;
1793  }
1794  }
1795  }
1796  }
1797 
1798  /* compute table */
1799  computeSCTable(scip, nspcons, nblocks, weights, cases, vals);
1800 
1801  /* loop through rows */
1802  for (i = 1; i < nspcons; ++i)
1803  {
1804  SCIP_Real bar;
1805  int lastcolumn;
1806 
1807  lastcolumn = nblocks - 1;
1808  bar = 0.0;
1809  /* last column considered as part of the bar: */
1810  if ( lastcolumn > i )
1811  lastcolumn = i;
1812 
1813  /* traverse row from right to left */
1814  for (j = lastcolumn; j > 1; --j)
1815  {
1816  bar += vals[i][j];
1817  assert( SCIPisFeasIntegral(scip, vals[i][j]) );
1818 
1819  /* check whether weights[i-1][j-1] < bar (<=> bar - weights[i-1][j-1] > 0), i.e. cut is violated) */
1820  if ( SCIPisGT(scip, bar - weights[i-1][j-1], 0.0) )
1821  {
1822  SCIPdebugMessage("Solution is infeasible.\n");
1823  *result = SCIP_INFEASIBLE;
1824 
1825  if ( printreason )
1826  {
1827  int l;
1828  int p1;
1829  int p2;
1830 
1831  SCIPinfoMessage(scip, NULL, "violated SCI: bar(");
1832 
1833  /* first output bar */
1834  for (l = j; l < nblocks; ++l)
1835  SCIPinfoMessage(scip, NULL, "<%s> (%f)", SCIPvarGetName(vars[i][l]), consdata->vals[i][l]);
1836 
1837  SCIPinfoMessage(scip, NULL, ") SC(");
1838 
1839  /* output shifted column */
1840  p1 = i-1;
1841  p2 = j-1;
1842  do
1843  {
1844  assert( cases[p1][p2] != -1 );
1845  assert( p1 >= 0 && p1 < i );
1846  assert( p2 >= 0 && p2 < j );
1847 
1848  /* if case 1 */
1849  if (cases[p1][p2] == 1)
1850  --p2; /* decrease column */
1851  else
1852  {
1853  /* case 2 or 3: */
1854  assert( cases[p1][p2] == 2 || cases[p1][p2] == 3 );
1855  SCIPinfoMessage(scip, NULL, "<%s> (%f)", SCIPvarGetName(vars[p1][p2]), consdata->vals[p1][p2]);
1856  if ( cases[p1][p2] == 3 )
1857  break;
1858  }
1859  --p1; /* decrease row */
1860  }
1861  while ( p1 >= 0 ); /* should always be true, i.e. the break should end the loop */
1862  assert( cases[p1][p2] == 3 );
1863 
1864  SCIPinfoMessage(scip, NULL, ")");
1865  }
1866 
1867  return SCIP_OKAY;
1868  }
1869  }
1870  }
1871  }
1872  SCIPdebugMessage("Solution is feasible.\n");
1873 
1874  return SCIP_OKAY;
1875 }
1876 
1877 
1878 /** domain propagation method of constraint handler */
1879 static
1880 SCIP_DECL_CONSPROP(consPropOrbitope)
1881 { /*lint --e{715}*/
1882  SCIP_Bool infeasible = FALSE;
1883  int nfixedvars = 0;
1884  int c;
1885 
1886  assert( scip != NULL );
1887  assert( conshdlr != NULL );
1888  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1889  assert( result != NULL );
1890 
1891  *result = SCIP_DIDNOTRUN;
1892 
1893  /* propagate all useful constraints */
1894  for (c = 0; c < nusefulconss && !infeasible; ++c)
1895  {
1896  assert( conss[c] != 0 );
1897 
1898  SCIPdebugMessage("Propagation of orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1899 
1900  SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixedvars) );
1901  }
1902 
1903  /* return the correct result */
1904  if ( infeasible )
1905  {
1906  *result = SCIP_CUTOFF;
1907  SCIPdebugMessage("Propagation via orbitopal fixing proved node to be infeasible.\n");
1908  }
1909  else if ( nfixedvars > 0 )
1910  {
1911  *result = SCIP_REDUCEDDOM;
1912  SCIPdebugMessage("Propagated %d variables via orbitopal fixing.\n", nfixedvars);
1913  }
1914  else if ( nusefulconss > 0 )
1915  {
1916  *result = SCIP_DIDNOTFIND;
1917  SCIPdebugMessage("Propagation via orbitopal fixing did not find anything.\n");
1918  }
1919 
1920  return SCIP_OKAY;
1921 }
1922 
1923 
1924 /** presolving method of constraint handler */
1925 static
1926 SCIP_DECL_CONSPRESOL(consPresolOrbitope)
1927 { /*lint --e{715}*/
1928  SCIP_Bool infeasible = FALSE;
1929  int noldfixedvars;
1930  int c;
1931 
1932  assert( scip != NULL );
1933  assert( conshdlr != NULL );
1934  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1935  assert( result != NULL );
1936 
1937  *result = SCIP_DIDNOTRUN;
1938  noldfixedvars = *nfixedvars;
1939 
1940  /* propagate all useful constraints */
1941  for (c = 0; c < nconss && !infeasible; ++c)
1942  {
1943  int nfixed = 0;
1944 
1945  assert( conss[c] != 0 );
1946 
1947  SCIPdebugMessage("Presolving of orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1948 
1949  SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixed) );
1950  *nfixedvars += nfixed;
1951  }
1952 
1953  if ( infeasible )
1954  {
1955  *result = SCIP_CUTOFF;
1956  SCIPdebugMessage("Presolving detected infeasibility.\n");
1957  }
1958  else if ( *nfixedvars > noldfixedvars )
1959  {
1960  *result = SCIP_SUCCESS;
1961  }
1962  else if ( nconss > 0 )
1963  {
1964  *result = SCIP_DIDNOTFIND;
1965  SCIPdebugMessage("Presolving via orbitopal fixing did not find anything.\n");
1966  }
1967 
1968  return SCIP_OKAY;
1969 }
1970 
1971 
1972 /** propagation conflict resolving method of constraint handler */
1973 static
1974 SCIP_DECL_CONSRESPROP(consRespropOrbitope)
1975 { /*lint --e{715}*/
1976  assert( scip != NULL );
1977  assert( cons != NULL );
1978  assert( infervar != NULL );
1979  assert( bdchgidx != NULL );
1980  assert( result != NULL );
1981 
1982  SCIP_CALL( resolvePropagation(scip, cons, infervar, inferinfo, boundtype, bdchgidx, result) );
1983 
1984  return SCIP_OKAY;
1985 }
1986 
1987 
1988 /** variable rounding lock method of constraint handler */
1989 static
1990 SCIP_DECL_CONSLOCK(consLockOrbitope)
1991 { /*lint --e{715}*/
1992  SCIP_CONSDATA* consdata;
1993  SCIP_VAR*** vars;
1994  int i;
1995  int j;
1996  int nspcons;
1997  int nblocks;
1998 
1999  assert( scip != NULL );
2000  assert( conshdlr != NULL );
2001  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2002  assert( cons != NULL );
2003 
2004  consdata = SCIPconsGetData(cons);
2005  assert( consdata != NULL );
2006  assert( consdata->nspcons > 0 );
2007  assert( consdata->nblocks > 0 );
2008  assert( consdata->vars != NULL );
2009 
2010  SCIPdebugMessage("Locking method for orbitope constraint handler\n");
2011 
2012  nspcons = consdata->nspcons;
2013  nblocks = consdata->nblocks;
2014  vars = consdata->vars;
2015 
2016  /* add up locks and down locks on each variable */
2017  for (i = 0; i < nspcons; ++i)
2018  {
2019  for (j = 0; j < nblocks; ++j)
2020  SCIP_CALL( SCIPaddVarLocks(scip, vars[i][j], nlockspos + nlocksneg, nlockspos + nlocksneg) );
2021  }
2022 
2023  return SCIP_OKAY;
2024 }
2025 
2026 
2027 /** constraint display method of constraint handler */
2028 static
2029 SCIP_DECL_CONSPRINT(consPrintOrbitope)
2031  SCIP_CONSDATA* consdata;
2032  SCIP_VAR*** vars;
2033  int i;
2034  int j;
2035  int nspcons;
2036  int nblocks;
2037 
2038  assert( scip != NULL );
2039  assert( conshdlr != NULL );
2040  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
2041  assert( cons != NULL );
2042 
2043  consdata = SCIPconsGetData(cons);
2044  assert( consdata != NULL );
2045  assert( consdata->nspcons > 0 );
2046  assert( consdata->nblocks > 0 );
2047  assert( consdata->vars != NULL );
2048 
2049  nspcons = consdata->nspcons;
2050  nblocks = consdata->nblocks;
2051  vars = consdata->vars;
2052 
2053  SCIPdebugMessage("Printing method for orbitope constraint handler\n");
2054 
2055  if ( consdata->ispart )
2056  SCIPinfoMessage(scip, file, "partOrbitope(");
2057  else
2058  SCIPinfoMessage(scip, file, "packOrbitope(");
2059 
2060  for (i = 0; i < nspcons; ++i)
2061  {
2062  for (j = 0; j < nblocks; ++j)
2063  {
2064  if ( j > 0 )
2065  SCIPinfoMessage(scip, file, ",");
2066  SCIPinfoMessage(scip, file, "%s", SCIPvarGetName(vars[i][j]));
2067  }
2068  if ( i < nspcons-1 )
2069  SCIPinfoMessage(scip, file, ".");
2070  }
2071  SCIPinfoMessage(scip, file, ")");
2072 
2073  return SCIP_OKAY;
2074 }
2075 
2076 
2077 /** constraint copying method of constraint handler */
2078 static
2079 SCIP_DECL_CONSCOPY(consCopyOrbitope)
2081  SCIP_CONSDATA* sourcedata;
2082  SCIP_VAR*** sourcevars;
2083  SCIP_VAR*** vars;
2084  int i;
2085  int j;
2086  int nspcons;
2087  int nblocks;
2088 
2089  assert( scip != NULL );
2090  assert( cons != NULL );
2091  assert( sourcescip != NULL );
2092  assert( sourceconshdlr != NULL );
2093  assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
2094  assert( sourcecons != NULL );
2095  assert( varmap != NULL );
2096 
2097  *valid = TRUE;
2098 
2099  SCIPdebugMessage("Copying method for orbitope constraint handler.\n");
2100 
2101  sourcedata = SCIPconsGetData(sourcecons);
2102  assert(sourcedata != NULL);
2103  assert(sourcedata->nspcons > 0);
2104  assert(sourcedata->nblocks > 0);
2105  assert(sourcedata->vars != NULL);
2106 
2107  nspcons = sourcedata->nspcons;
2108  nblocks = sourcedata->nblocks;
2109  sourcevars = sourcedata->vars;
2110 
2111  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nspcons) );
2112  for (i = 0; i < nspcons && *valid; ++i)
2113  {
2114  SCIP_CALL( SCIPallocBufferArray(scip, &(vars[i]), nblocks) ); /*lint !e866*/
2115 
2116  for (j = 0; j < nblocks && *valid; ++j)
2117  {
2118  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[i][j], &vars[i][j], varmap, consmap, global, valid) );
2119  assert(!(*valid) || vars[i][j] != NULL);
2120  }
2121  }
2122 
2123  /* only create the target constraint, if all variables could be copied */
2124  if ( *valid )
2125  {
2126  /* create copied constraint */
2127  if ( name == NULL )
2128  name = SCIPconsGetName(sourcecons);
2129 
2130  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, name,
2131  vars, sourcedata->ispart, nspcons, nblocks, sourcedata->resolveprop,
2132  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2133  }
2134 
2135  for (i = 0; i < nspcons; ++i)
2136  SCIPfreeBufferArray(scip, &vars[i]);
2137  SCIPfreeBufferArray(scip, &vars);
2138 
2139  return SCIP_OKAY;
2140 }
2141 
2142 
2143 /** constraint parsing method of constraint handler */
2144 static
2145 SCIP_DECL_CONSPARSE(consParseOrbitope)
2146 { /*lint --e{715}*/
2147  const char* s;
2148  SCIP_Bool ispart;
2149  char varname[SCIP_MAXSTRLEN];
2150  SCIP_VAR*** vars;
2151  SCIP_VAR* var;
2152  int nspcons;
2153  int maxnspcons;
2154  int nblocks;
2155  int maxnblocks;
2156  int k;
2157  int j;
2158 
2159  assert( success != NULL );
2160 
2161  *success = TRUE;
2162  s = str;
2163 
2164  /* skip white space */
2165  while ( *s != '\0' && isspace((unsigned char)*s) )
2166  ++s;
2167 
2168  ispart = FALSE;
2169  if ( strncmp(s, "partOrbitope(", 13) == 0 )
2170  ispart = TRUE;
2171  else
2172  {
2173  if ( strncmp(s, "packOrbitope(", 13) != 0 )
2174  {
2175  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "Syntax error - expected \"partOrbitope\" or \"packOrbitope\": %s\n", s);
2176  *success = FALSE;
2177  return SCIP_OKAY;
2178  }
2179  }
2180  s += 13;
2181 
2182  /* loop through string */
2183  nspcons = 0;
2184  nblocks = 0;
2185  maxnspcons = 10;
2186  maxnblocks = 10;
2187 
2188  SCIP_CALL( SCIPallocBufferArray(scip, &vars, maxnspcons) );
2189  SCIP_CALL( SCIPallocBufferArray(scip, &(vars[0]), maxnblocks) );
2190 
2191  j = 0;
2192  do
2193  {
2194  /* find variable name */
2195  k = 0;
2196  while ( *s != '\0' && ! isspace((unsigned char)*s) && *s != ',' && *s != '.' && *s != ')' )
2197  varname[k++] = *s++;
2198  varname[k] = '\0';
2199 
2200  /* get variable */
2201  var = SCIPfindVar(scip, varname);
2202  if ( var == NULL )
2203  {
2204  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "unknown variable <%s>\n", varname);
2205  *success = FALSE;
2206  return SCIP_OKAY;
2207  }
2208  vars[nspcons][j++] = var;
2209 
2210  if ( j > nblocks )
2211  {
2212  int newsize;
2213 
2214  if ( nspcons > 0 )
2215  {
2216  SCIPverbMessage(scip, SCIP_VERBLEVEL_MINIMAL, NULL, "variables per row do not match.\n");
2217  *success = FALSE;
2218  return SCIP_OKAY;
2219  }
2220 
2221  nblocks = j;
2222  newsize = SCIPcalcMemGrowSize(scip, nblocks);
2223  SCIP_CALL( SCIPreallocBufferArray(scip, &(vars[nspcons]), newsize) ); /*lint !e866*/
2224  maxnblocks = newsize;
2225  assert( nblocks <= maxnblocks );
2226  }
2227 
2228  /* skip white space and ',' */
2229  while ( *s != '\0' && ( isspace((unsigned char)*s) || *s == ',' ) )
2230  ++s;
2231 
2232  /* begin new row if required */
2233  if ( *s == '.' )
2234  {
2235  ++nspcons;
2236  ++s;
2237 
2238  if ( nspcons >= maxnspcons )
2239  {
2240  int newsize;
2241 
2242  newsize = SCIPcalcMemGrowSize(scip, nspcons+1);
2243  SCIP_CALL( SCIPreallocBufferArray(scip, &vars, newsize) );
2244  maxnspcons = newsize;
2245  }
2246  assert(nspcons < maxnspcons);
2247 
2248  SCIP_CALL( SCIPallocBufferArray(scip, &(vars[nspcons]), nblocks) ); /*lint !e866*/
2249  j = 0;
2250  }
2251  }
2252  while ( *s != ')' );
2253  ++nspcons;
2254 
2255  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, name, vars, ispart, nspcons, nblocks, TRUE,
2256  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
2257 
2258  for (k = 0; k < nspcons; ++k)
2259  SCIPfreeBufferArray(scip, &vars[k]);
2260  SCIPfreeBufferArray(scip, &vars);
2261 
2262  return SCIP_OKAY;
2263 }
2264 
2265 
2266 /** constraint method of constraint handler which returns the variables (if possible) */
2267 static
2268 SCIP_DECL_CONSGETVARS(consGetVarsOrbitope)
2269 { /*lint --e{715}*/
2270  SCIP_CONSDATA* consdata;
2271 
2272  assert( cons != NULL );
2273  assert( success != NULL );
2274  assert( vars != NULL );
2275 
2276  consdata = SCIPconsGetData(cons);
2277  assert( consdata != NULL );
2278 
2279  if ( varssize < consdata->nblocks * consdata->nspcons )
2280  (*success) = FALSE;
2281  else
2282  {
2283  int cnt = 0;
2284  int i;
2285  int j;
2286 
2287  for (i = 0; i < consdata->nspcons; ++i)
2288  {
2289  for (j = 0; j < consdata->nblocks; ++j)
2290  vars[cnt++] = consdata->vars[i][j];
2291  }
2292  (*success) = TRUE;
2293  }
2294 
2295  return SCIP_OKAY;
2296 }
2297 
2298 
2299 /** constraint method of constraint handler which returns the number of variables (if possible) */
2300 static
2301 SCIP_DECL_CONSGETNVARS(consGetNVarsOrbitope)
2302 { /*lint --e{715}*/
2303  SCIP_CONSDATA* consdata;
2304 
2305  assert( cons != NULL );
2306 
2307  consdata = SCIPconsGetData(cons);
2308  assert( consdata != NULL );
2309 
2310  (*nvars) = consdata->nblocks * consdata->nspcons;
2311  (*success) = TRUE;
2312 
2313  return SCIP_OKAY;
2314 }
2315 
2316 
2317 /*
2318  * constraint specific interface methods
2319  */
2320 
2321 /** creates the handler for orbitope constraints and includes it in SCIP */
2323  SCIP* scip /**< SCIP data structure */
2324  )
2325 {
2326  SCIP_CONSHDLRDATA* conshdlrdata;
2327  SCIP_CONSHDLR* conshdlr;
2328 
2329  /* create orbitope constraint handler data */
2330  conshdlrdata = NULL;
2331 
2332  /* include constraint handler */
2336  consEnfolpOrbitope, consEnfopsOrbitope, consCheckOrbitope, consLockOrbitope,
2337  conshdlrdata) );
2338  assert(conshdlr != NULL);
2339 
2340  /* set non-fundamental callbacks via specific setter functions */
2341  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOrbitope, consCopyOrbitope) );
2342  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrbitope) );
2343  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOrbitope) );
2344  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOrbitope) );
2345  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOrbitope) );
2346  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolOrbitope, CONSHDLR_MAXPREROUNDS, CONSHDLR_DELAYPRESOL) );
2347  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOrbitope) );
2348  SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropOrbitope, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
2350  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOrbitope) );
2351  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOrbitope, consSepasolOrbitope, CONSHDLR_SEPAFREQ,
2353  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOrbitope) );
2354 
2355  return SCIP_OKAY;
2356 }
2357 
2358 
2359 /** creates and captures a orbitope constraint
2360  *
2361  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2362  */
2364  SCIP* scip, /**< SCIP data structure */
2365  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2366  const char* name, /**< name of constraint */
2367  SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
2368  SCIP_Bool ispart, /**< whether we deal with the partitioning case (packing otherwise) */
2369  int nspcons, /**< number of set partitioning/packing constraints <=> p */
2370  int nblocks, /**< number of symmetric variable blocks <=> q */
2371  SCIP_Bool resolveprop, /**< should propagation be resolved? */
2372  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2373  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2374  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2375  * Usually set to TRUE. */
2376  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2377  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2378  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2379  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2380  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2381  * Usually set to TRUE. */
2382  SCIP_Bool local, /**< is constraint only valid locally?
2383  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2384  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2385  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2386  * adds coefficients to this constraint. */
2387  SCIP_Bool dynamic, /**< is constraint subject to aging?
2388  * Usually set to FALSE. Set to TRUE for own cuts which
2389  * are separated as constraints. */
2390  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2391  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2392  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2393  * if it may be moved to a more global node?
2394  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2395  )
2396 {
2397  SCIP_CONSHDLR* conshdlr;
2398  SCIP_CONSDATA* consdata;
2399 
2400  /* find the orbitope constraint handler */
2401  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2402  if ( conshdlr == NULL )
2403  {
2404  SCIPerrorMessage("orbitope constraint handler not found\n");
2405  return SCIP_PLUGINNOTFOUND;
2406  }
2407 
2408  assert( nspcons > 0 );
2409  assert( nblocks > 0 );
2410 
2411  /* run some checks */
2412 #ifndef NDEBUG
2413  {
2414  SCIP_Real obj;
2415  int i;
2416  int j;
2417  for (i = 0; i < nspcons; ++i)
2418  {
2419  /* initialize obj to infinity */
2420  obj = SCIPinfinity(scip);
2421  for (j = 0; j < nblocks; ++j)
2422  {
2423  SCIP_Bool fixedZero;
2424  SCIP_VAR* var;
2425 
2426  var = vars[i][j];
2427  assert(var != NULL);
2428 
2429  /* all variables need to be binary */
2430  assert( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY );
2431 
2432  /* fixed variables have obj = 0; for variables fixed to 0, we assume that there is no
2433  problem (but we cannot always check it, e.g., when in the original problem
2434  variables were fixed and this problem was copied.) */
2435  fixedZero = ( SCIPisZero(scip, SCIPvarGetLbGlobal(var)) && SCIPisZero(scip, SCIPvarGetUbGlobal(var)) );
2436 
2437  /* check whether all variables in a row have the same objective */
2438  if ( ! fixedZero && SCIPisInfinity(scip, obj) )
2439  obj = SCIPvarGetObj(var);
2440  else
2441  {
2442  assert( fixedZero || SCIPisEQ(scip, obj, SCIPvarGetObj(var)) );
2443  }
2444  }
2445  }
2446  }
2447 #endif
2448 
2449  /* create constraint data */
2450  SCIP_CALL( consdataCreate(scip, &consdata, vars, nspcons, nblocks, ispart, resolveprop) );
2451 
2452  /* create constraint */
2453  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2454  local, modifiable, dynamic, removable, stickingatnode) );
2455 
2456  return SCIP_OKAY;
2457 }
2458 
2459 /** creates and captures an orbitope constraint
2460  * in its most basic variant, i. e., with all constraint flags set to their default values
2461  *
2462  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2463  */
2465  SCIP* scip, /**< SCIP data structure */
2466  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2467  const char* name, /**< name of constraint */
2468  SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
2469  SCIP_Bool ispart, /**< whether we deal with the partitioning case (packing otherwise) */
2470  int nspcons, /**< number of set partitioning/packing constraints <=> p */
2471  int nblocks, /**< number of symmetric variable blocks <=> q */
2472  SCIP_Bool resolveprop /**< should propagation be resolved? */
2473  )
2474 {
2475  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, name, vars, ispart, nspcons, nblocks, resolveprop,
2476  TRUE, TRUE, TRUE, TRUE, TRUE,
2477  FALSE, FALSE, FALSE, FALSE, FALSE) );
2478 
2479  return SCIP_OKAY;
2480 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:30035
SCIP_RETCODE SCIPfixVar(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: scip.c:20784
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38254
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:38397
static SCIP_DECL_CONSPARSE(consParseOrbitope)
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5600
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip.c:5332
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
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
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:38360
#define SCIP_MAXSTRLEN
Definition: def.h:196
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:5378
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip.c:28166
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:4990
#define NULL
Definition: lpi_spx.cpp:129
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:16426
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:7786
#define CONSHDLR_DELAYPRESOL
Definition: cons_orbitope.c:82
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip.c:5078
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16380
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
Definition: scip.c:22044
#define CONSHDLR_SEPAPRIORITY
Definition: cons_orbitope.c:71
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip.c:5562
#define FALSE
Definition: def.h:52
static SCIP_DECL_CONSPRESOL(consPresolOrbitope)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:7579
#define TRUE
Definition: def.h:51
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:5539
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:38743
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_Bool delaypresol)
Definition: scip.c:5271
#define CONSHDLR_DESC
Definition: cons_orbitope.c:70
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:38779
SCIP_RETCODE SCIPaddVarsToRow(SCIP *scip, SCIP_ROW *row, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:25564
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:19185
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15141
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:31775
#define CONSHDLR_NAME
Definition: cons_orbitope.c:69
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:19214
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16227
#define CONSHDLR_PROPFREQ
Definition: cons_orbitope.c:75
#define CONSHDLR_PROP_TIMING
Definition: cons_orbitope.c:85
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING timingmask)
Definition: scip.c:5036
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:7776
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:7716
SCIP_RETCODE SCIPaddCut(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip.c:28256
static SCIP_DECL_CONSPRINT(consPrintOrbitope)
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip.h:19215
#define CONSHDLR_ENFOPRIORITY
Definition: cons_orbitope.c:72
static SCIP_DECL_CONSENFOLP(consEnfolpOrbitope)
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:7706
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:22424
constraint handler for (partitioning/packing) orbitope constraints w.r.t. the full symmetric group ...
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip)
Definition: scip.c:22066
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38273
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:1690
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:19183
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:7816
#define SCIPerrorMessage
Definition: pub_message.h:45
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:19221
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:19207
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:83
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:3873
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15233
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7557
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:18783
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)
#define REALABS(x)
Definition: def.h:146
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:38349
#define SCIP_CALL(x)
Definition: def.h:258
static SCIP_DECL_CONSPROP(consPropOrbitope)
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:4936
SCIP_Bool SCIPinProbing(SCIP *scip)
Definition: scip.c:29454
static SCIP_DECL_CONSSEPASOL(consSepasolOrbitope)
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:49
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:7587
SCIP_RETCODE SCIPgetTransformedVars(SCIP *scip, int nvars, SCIP_VAR **vars, SCIP_VAR **transvars)
Definition: scip.c:15360
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38311
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:16436
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:983
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:22476
#define SCIP_Bool
Definition: def.h:49
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbitope)
SCIP_STAGE SCIPgetStage(SCIP *scip)
Definition: scip.c:790
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:7796
static SCIP_DECL_CONSDELETE(consDeleteOrbitope)
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22093
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:7806
static SCIP_DECL_CONSLOCK(consLockOrbitope)
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:19204
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1256
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:5309
static SCIP_DECL_CONSTRANS(consTransOrbitope)
static SCIP_DECL_CONSCHECK(consCheckOrbitope)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:15953
SCIP_Bool SCIPisSumEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38518
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16370
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip.c:5516
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1239
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:38433
#define CONSHDLR_MAXPREROUNDS
Definition: cons_orbitope.c:79
#define SCIP_Real
Definition: def.h:123
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:7736
#define MIN(x, y)
Definition: memory.c:59
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:25276
SCIP_VAR * SCIPfindVar(SCIP *scip, const char *name)
Definition: scip.c:10765
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip.h:19198
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip.c:25414
SCIP_RETCODE SCIPaddVarLocks(SCIP *scip, SCIP_VAR *var, int nlocksdown, int nlocksup)
Definition: scip.c:17590
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:48
static SCIP_DECL_CONSRESPROP(consRespropOrbitope)
static SCIP_DECL_CONSGETNVARS(consGetNVarsOrbitope)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:22285
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
Definition: scip.c:22156
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip.c:38001
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip.c:5585
#define SCIPABORT()
Definition: def.h:230
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:7726
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:7756
#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)