Scippy

SCIP

Solving Constraint Integer Programs

cons_orbisack.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright 2002-2022 Zuse Institute Berlin */
7 /* */
8 /* Licensed under the Apache License, Version 2.0 (the "License"); */
9 /* you may not use this file except in compliance with the License. */
10 /* You may obtain a copy of the License at */
11 /* */
12 /* http://www.apache.org/licenses/LICENSE-2.0 */
13 /* */
14 /* Unless required by applicable law or agreed to in writing, software */
15 /* distributed under the License is distributed on an "AS IS" BASIS, */
16 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17 /* See the License for the specific language governing permissions and */
18 /* limitations under the License. */
19 /* */
20 /* You should have received a copy of the Apache-2.0 license */
21 /* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22 /* */
23 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24 
25 /**@file cons_orbisack.c
26  * @ingroup DEFPLUGINS_CONS
27  * @brief constraint handler for orbisack constraints
28  * @author Christopher Hojny
29  * @author Jasper van Doornmalen
30  *
31  *
32  * The type of constraints of this constraint handler is described in cons_orbisack.h.
33  *
34  * The details of the method implemented here are described in the following papers:
35  *
36  * Describing Orbitopes by Linear Inequalities and Projection Based Tools@n
37  * Andreas Loos,@n
38  * PhD thesis, Otto-von-Guericke-Universitaet Magdeburg (2010).
39  *
40  * This thesis provides a complete linear description of orbisacks and a separation
41  * routine for its inequalities.
42  *
43  * Polytopes Associated with Symmetry Handling@n
44  * Christopher Hojny and Marc E. Pfetsch,@n
45  * (2017), preprint available at http://www.optimization-online.org/DB_HTML/2017/01/5835.html
46  *
47  * This paper describes a linear time separation routine for so-called cover inequalities of
48  * orbisacks.
49  */
50 
51 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
52 
53 #include "blockmemshell/memory.h"
54 #include "scip/cons_orbisack.h"
55 #include "scip/cons_orbitope.h"
56 #include "scip/cons_setppc.h"
57 #include "scip/pub_cons.h"
58 #include "scip/pub_message.h"
59 #include "scip/pub_var.h"
60 #include "scip/scip.h"
61 #include "scip/scip_branch.h"
62 #include "scip/scip_conflict.h"
63 #include "scip/scip_cons.h"
64 #include "scip/scip_cut.h"
65 #include "scip/scip_general.h"
66 #include "scip/scip_lp.h"
67 #include "scip/scip_mem.h"
68 #include "scip/scip_message.h"
69 #include "scip/scip_numerics.h"
70 #include "scip/scip_param.h"
71 #include "scip/scip_sol.h"
72 #include "scip/scip_var.h"
73 #include "scip/symmetry.h"
74 #include <ctype.h>
75 #include <string.h>
76 
77 /* constraint handler properties */
78 #define CONSHDLR_NAME "orbisack"
79 #define CONSHDLR_DESC "symmetry breaking constraint handler for orbisacks"
80 #define CONSHDLR_SEPAPRIORITY +40100 /**< priority of the constraint handler for separation */
81 #define CONSHDLR_ENFOPRIORITY -1005200 /**< priority of the constraint handler for constraint enforcing */
82 #define CONSHDLR_CHECKPRIORITY -1005200 /**< priority of the constraint handler for checking feasibility */
83 #define CONSHDLR_SEPAFREQ 5 /**< frequency for separating cuts; zero means to separate only in the root node */
84 #define CONSHDLR_PROPFREQ 5 /**< frequency for propagating domains; zero means only preprocessing propagation */
85 #define CONSHDLR_EAGERFREQ -1 /**< frequency for using all instead of only the useful constraints in separation,
86  * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
87 #define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
88 #define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
89 #define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
90 #define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
91 
92 #define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
93 #define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_EXHAUSTIVE
94 
95 /* default parameters for separation routines: */
96 #define DEFAULT_ORBISEPARATION FALSE /**< whether orbisack inequalities should be separated */
97 #define DEFAULT_COVERSEPARATION TRUE /**< whether cover inequalities should be separated */
98 
99 /* default parameters for constraints */
100 #define DEFAULT_COEFFBOUND 1000000.0 /**< maximum size of coefficients in orbisack inequalities */
101 #define DEFAULT_PPORBISACK TRUE /**< whether we allow upgrading to packing/partitioning orbisacks */
102 #define DEFAULT_FORCECONSCOPY FALSE /**< whether orbisack constraints should be forced to be copied to sub SCIPs */
104 /* Constants to store fixings */
105 #define FIXED0 1 /* When a variable is fixed to 0. */
106 #define FIXED1 2 /* When a variable is fixed to 1. */
107 #define UNFIXED 3 /* When a variable is neither fixed to 0 or to 1. */
109 
110 /*
111  * Data structures
112  */
113 
114 /** constraint handler data */
115 struct SCIP_ConshdlrData
116 {
117  SCIP_Bool coverseparation; /**< whether only cover inequalities should be separated */
118  SCIP_Bool orbiseparation; /**< whether orbisack as well as cover inequalities should be separated */
119  SCIP_Real coeffbound; /**< maximum size of coefficients in orbisack inequalities */
120  SCIP_Bool checkpporbisack; /**< whether we allow upgrading to packing/partitioning orbisacks */
121  int maxnrows; /**< maximal number of rows in an orbisack constraint */
122  SCIP_Bool forceconscopy; /**< whether orbisack constraints should be forced to be copied to sub SCIPs */
123 };
124 
125 /** constraint data for orbisack constraints */
126 struct SCIP_ConsData
127 {
128  SCIP_VAR** vars1; /**< first column of variable matrix */
129  SCIP_VAR** vars2; /**< second column of variable matrix */
130  int nrows; /**< number of rows of variable matrix */
131  SCIP_Bool ismodelcons; /**< whether the orbisack is a model constraint */
132 };
133 
134 
135 /*
136  * Local methods
137  */
138 
139 /** frees orbisack constraint data */
140 static
142  SCIP* scip, /**< SCIP data structure */
143  SCIP_CONSDATA** consdata /**< pointer to orbisack constraint data */
144  )
145 {
146  int nrows;
147 
148  assert( consdata != NULL );
149  assert( *consdata != NULL );
150 
151  nrows = (*consdata)->nrows;
152  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars2), nrows);
153  SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars1), nrows);
154 
155  SCIPfreeBlockMemory(scip, consdata);
156 
157  return SCIP_OKAY;
158 }
159 
160 
161 /** creates orbisack constraint data */
162 static
164  SCIP* scip, /**< SCIP data structure */
165  SCIP_CONSDATA** consdata, /**< pointer to store constraint data */
166  SCIP_VAR*const* vars1, /**< first column of variable matrix */
167  SCIP_VAR*const* vars2, /**< second column of variable matrix */
168  int nrows, /**< number of rows in variable matrix */
169  SCIP_Bool ismodelcons /**< whether the orbisack is a model constraint */
170  )
171 {
172  int i;
173 
174  assert( consdata != NULL );
175 
176  SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
177 
178  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars1, vars1, nrows) );
179  SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars2, vars2, nrows) );
180 
181 #ifndef NDEBUG
182  {
183  for (i = 0; i < nrows; ++i)
184  {
185  assert( SCIPvarIsBinary(vars1[i]) );
186  assert( SCIPvarIsBinary(vars2[i]) );
187  }
188  }
189 #endif
190 
191  (*consdata)->nrows = nrows;
192  (*consdata)->ismodelcons = ismodelcons;
193 
194  /* get transformed variables, if we are in the transformed problem */
195  if ( SCIPisTransformed(scip) )
196  {
197  /* Make sure that all variables cannot be multiaggregated (cannot be handled by cons_orbisack, since one cannot
198  * easily eliminate single variables from an orbisack constraint. */
199  for (i = 0; i < nrows; ++i)
200  {
201  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vars1[i], &(*consdata)->vars1[i]) );
202  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars1[i]) );
203 
204  SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vars2[i], &(*consdata)->vars2[i]) );
205  SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars2[i]) );
206  }
207  }
208 
209  return SCIP_OKAY;
210 }
211 
212 
213 /** check wether an orbisack is even a packing/partitioning orbisack */
214 static
216  SCIP* scip, /**< SCIP pointer */
217  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
218  SCIP_VAR*const* vars2, /**< variables of second column */
219  int nrows, /**< number of rows of orbisack */
220  SCIP_Bool* success, /**< memory address to store whether constraint can be upgraded */
221  SCIP_Bool* isparttype /**< memory address to store whether upgraded orbisack is partitioning orbisack */
222  )
223 {
224  SCIP_VAR*** vars;
225  SCIP_ORBITOPETYPE type;
226  int i;
227 
228  assert( scip != NULL );
229  assert( vars1 != NULL );
230  assert( vars2 != NULL );
231  assert( success != NULL );
232  assert( isparttype != NULL );
233 
234  *success = FALSE;
235  *isparttype = FALSE;
236 
237  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nrows) );
238  for (i = 0; i < nrows; ++i)
239  {
240  SCIP_CALL( SCIPallocBufferArray(scip, &vars[i], 2) );
241  vars[i][0] = vars1[i];
242  vars[i][1] = vars2[i];
243  }
244 
245  SCIP_CALL( SCIPisPackingPartitioningOrbitope(scip, vars, nrows, 2, NULL, NULL, &type) );
246 
247  if ( type == SCIP_ORBITOPETYPE_PACKING )
248  *success = TRUE;
249  else if ( type == SCIP_ORBITOPETYPE_PARTITIONING )
250  {
251  *success = TRUE;
252  *isparttype = TRUE;
253  }
254 
255  for (i = nrows - 1; i >= 0; --i)
256  {
257  SCIPfreeBufferArray(scip, &vars[i]);
258  }
259  SCIPfreeBufferArray(scip, &vars);
260 
261  return SCIP_OKAY;
262 }
263 
264 
265 /** generate initial LP cut
266  *
267  * We generate the inequality of the orbisack on the elements of the first row, i.e.,
268  * the inequality \f$-x_{1,1} + x_{1,2} \leq 0\f$.
269  */
270 static
272  SCIP* scip, /**< SCIP pointer */
273  SCIP_CONS* cons, /**< constraint */
274  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
275  )
276 {
277  SCIP_CONSDATA* consdata;
278  SCIP_VAR** vars1;
279  SCIP_VAR** vars2;
280  SCIP_VAR* tmpvars[2];
281  SCIP_ROW* row;
282 
283  assert( scip != NULL );
284  assert( cons != NULL );
285  assert( infeasible != NULL );
286 
287  *infeasible = FALSE;
288 
289  consdata = SCIPconsGetData(cons);
290  assert( consdata != 0 );
291  assert( consdata->nrows > 0 );
292  assert( consdata->vars1 != NULL );
293  assert( consdata->vars2 != NULL );
294 
295  vars1 = consdata->vars1;
296  vars2 = consdata->vars2;
297 
298  tmpvars[0] = vars1[0];
299  tmpvars[1] = vars2[0];
300 
301  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisack0#0", -SCIPinfinity(scip), 0.0, FALSE, FALSE, TRUE) );
302  SCIP_CALL( SCIPaddVarToRow(scip, row, tmpvars[0], -1.0) );
303  SCIP_CALL( SCIPaddVarToRow(scip, row, tmpvars[1], 1.0) );
304 
305  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
306 #ifdef SCIP_DEBUG
307  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
308 #endif
309  SCIP_CALL( SCIPreleaseRow(scip, &row) );
310 
311  return SCIP_OKAY;
312 }
313 
314 
315 /** add orbisack cover inequality */
316 static
318  SCIP* scip, /**< SCIP pointer */
319  SCIP_CONS* cons, /**< constraint */
320  int nrows, /**< number of rows of orbisack */
321  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
322  SCIP_VAR*const* vars2, /**< variables of second column */
323  SCIP_Real* coeffs1, /**< coefficients of the variables of the first column of the inequality to be added */
324  SCIP_Real* coeffs2, /**< coefficients of the variables of the second column of the inequality to be added */
325  SCIP_Real rhs, /**< right-hand side of inequality to be added */
326  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
327  )
328 {
329  SCIP_ROW* row;
330  int i;
331 
332  assert( scip != NULL );
333  assert( cons != NULL );
334  assert( vars1 != NULL );
335  assert( vars2 != NULL );
336  assert( coeffs1 != NULL );
337  assert( coeffs2 != NULL );
338  assert( infeasible != NULL );
339 
340  *infeasible = FALSE;
341 
342  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisackcover", -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
343  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
344  for (i = 0; i < nrows; ++i)
345  {
346  SCIP_CALL( SCIPaddVarToRow(scip, row, vars1[i], coeffs1[i]) );
347  SCIP_CALL( SCIPaddVarToRow(scip, row, vars2[i], coeffs2[i]) );
348  }
349  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
350 
351  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
352 #ifdef SCIP_DEBUG
353  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
354 #endif
355  SCIP_CALL( SCIPreleaseRow(scip, &row) );
356 
357  return SCIP_OKAY;
358 }
359 
360 
361 /** Separate lifted orbisack cover inequalities
362  *
363  * We currently do NOT enter cuts into the pool.
364  *
365  * We iterate over the nrows-many cover inequalities which are potentially
366  * maximal w.r.t. their violation.
367  */
368 static
370  SCIP* scip, /**< SCIP pointer */
371  SCIP_CONS* cons, /**< constraint */
372  int nrows, /**< number of rows of orbisack */
373  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
374  SCIP_VAR*const* vars2, /**< variables of second column */
375  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
376  SCIP_Real* vals2, /**< LP-solution for those variables in second column */
377  int* ngen, /**< number of separated covers */
378  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
379  )
380 {
381  SCIP_Real rhs = 0.0;
382  SCIP_Real lhs = 0.0;
383  SCIP_Real* coeff1;
384  SCIP_Real* coeff2;
385  int i;
386 
387  assert( scip != NULL );
388  assert( cons != NULL );
389  assert( nrows > 0 );
390  assert( vars1 != NULL );
391  assert( vars2 != NULL );
392  assert( infeasible != NULL );
393  assert( ngen != NULL );
394 
395  *infeasible = FALSE;
396  *ngen = 0;
397 
398  /* allocate memory for inequality coefficients */
399  SCIP_CALL( SCIPallocBufferArray(scip, &coeff1, nrows) );
400  SCIP_CALL( SCIPallocBufferArray(scip, &coeff2, nrows) );
401 
402  /* initialize coefficient matrix */
403  for (i = 0; i < nrows; ++i)
404  {
405  coeff1[i] = 0.0;
406  coeff2[i] = 0.0;
407  }
408 
409  /* detect violated covers */
410  for (i = 0; i < nrows; ++i)
411  {
412  /* cover inequality is violated */
413  if ( SCIPisEfficacious(scip, -vals1[i] + vals2[i] + lhs - rhs) )
414  {
415  /* set coefficients for inequality */
416  coeff1[i] = -1.0;
417  coeff2[i] = 1.0;
418 
419  SCIP_CALL( addOrbisackCover(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
420  ++(*ngen);
421  if ( *infeasible )
422  break;
423 
424  /* reset coefficients for next inequality */
425  coeff1[i] = 0.0;
426  coeff2[i] = 0.0;
427  }
428 
429  /* add argmax( 1 - vals[i][0], vals[i][1] ) as coefficient and ensure that both vars1[0] and vars2[0] are
430  * contained in the LIFTED cover inequality */
431  if ( SCIPisEfficacious(scip, 1.0 - vals1[i] - vals2[i]) )
432  {
433  coeff1[i] = -1.0;
434  lhs = lhs - vals1[i];
435 
436  /* lifting */
437  if ( i == 0 )
438  {
439  coeff2[0] = 1.0;
440  lhs += vals2[i];
441  }
442  }
443  else
444  {
445  coeff2[i] = 1.0;
446  rhs += 1.0;
447  lhs = lhs + vals2[i];
448 
449  /* lifting */
450  if ( i == 0 )
451  {
452  coeff1[0] = -1.0;
453  lhs -= vals1[i];
454  rhs -= 1.0;
455  }
456  }
457  }
458 
459  /* free coefficient matrix */
460  SCIPfreeBufferArray(scip, &coeff2);
461  SCIPfreeBufferArray(scip, &coeff1);
462 
463  return SCIP_OKAY;
464 }
465 
466 
467 /** add orbisack inequality */
468 static
470  SCIP* scip, /**< SCIP pointer */
471  SCIP_CONS* cons, /**< constraint */
472  int nrows, /**< number of rows of orbisack */
473  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
474  SCIP_VAR*const* vars2, /**< variables of second column */
475  SCIP_Real* coeffs1, /**< first column of coefficient matrix of inequality to be added */
476  SCIP_Real* coeffs2, /**< second column of coefficient matrix of inequality to be added */
477  SCIP_Real rhs, /**< right-hand side of inequality to be added */
478  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
479  )
480 {
481  SCIP_ROW* row;
482  int i;
483 
484  assert( scip != NULL );
485  assert( cons != NULL );
486  assert( vars1 != NULL );
487  assert( vars2 != NULL );
488  assert( coeffs1 != NULL );
489  assert( coeffs2 != NULL );
490  assert( infeasible != NULL );
491 
492  *infeasible = FALSE;
493 
494  SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisack", -SCIPinfinity(scip), rhs, FALSE, FALSE, TRUE) );
495  SCIP_CALL( SCIPcacheRowExtensions(scip, row) );
496 
497  for (i = 0; i < nrows; ++i)
498  {
499  SCIP_CALL( SCIPaddVarToRow(scip, row, vars1[i], coeffs1[i]) );
500  SCIP_CALL( SCIPaddVarToRow(scip, row, vars2[i], coeffs2[i]) );
501  }
502  SCIP_CALL( SCIPflushRowExtensions(scip, row) );
503 
504  SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
505 #ifdef SCIP_DEBUG
506  SCIP_CALL( SCIPprintRow(scip, row, NULL) );
507 #endif
508  SCIP_CALL( SCIPreleaseRow(scip, &row) );
509 
510  return SCIP_OKAY;
511 }
512 
513 
514 /** separate orbisack inequalities
515  *
516  * We currently do NOT enter cuts into the pool.
517  *
518  * We stop if we checked for each possible basement row, whether a cut could be added. If the coefficients grow too
519  * large, we start separating cover inequalities.
520  *
521  * We implement the separation algorithm for orbisacks described in@n
522  * A. Loos. Describing Orbitopes by Linear Inequalities and Projection Based Tools.
523  * PhD thesis, Otto-von-Guericke-Universitaet Magdeburg, 2010.
524  */
525 static
527  SCIP* scip, /**< SCIP pointer */
528  SCIP_CONS* cons, /**< constraint */
529  int nrows, /**< number of rows of orbisack */
530  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
531  SCIP_VAR*const* vars2, /**< variables of second column */
532  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
533  SCIP_Real* vals2, /**< LP-solution for those variables in second column */
534  SCIP_Bool coverseparation, /**< whether we separate cover inequalities */
535  SCIP_Real coeffbound, /**< maximum size of coefficients in orbisack inequalities */
536  int* ngen, /**< pointer to store the number of generated cuts */
537  SCIP_Bool* infeasible /**< pointer to store whether we detected infeasibility */
538  )
539 {
540  SCIP_Real* coeff1;
541  SCIP_Real* coeff2;
542  SCIP_Real rhs;
543  SCIP_Real lhs;
544  SCIP_Real valueA;
545  SCIP_Real valueB;
546  SCIP_Real valueC;
547  int basement;
548  int i;
549 
550  assert( scip != NULL );
551  assert( cons != NULL );
552  assert( nrows > 0 );
553  assert( vars1 != NULL );
554  assert( vars2 != NULL );
555  assert( coeffbound >= 0.0 );
556  assert( ngen != NULL );
557  assert( infeasible != NULL );
558 
559  *infeasible = FALSE;
560  *ngen = 0;
561 
562  /* if there is only one row, all cuts are added by initLP */
563  if ( nrows < 2 )
564  return SCIP_OKAY;
565 
566  /* allocate memory for inequality coefficients */
567  SCIP_CALL( SCIPallocBufferArray(scip, &coeff1, nrows) );
568  SCIP_CALL( SCIPallocBufferArray(scip, &coeff2, nrows) );
569 
570  /* initialize coefficient matrix row 0 */
571  coeff1[0] = -1.0;
572  coeff2[0] = 1.0;
573  for (i = 2; i < nrows; ++i)
574  {
575  coeff1[i] = 0.0;
576  coeff2[i] = 0.0;
577  }
578 
579  /* initialize right-hand side and left-hand side (lhs for row 0) */
580  rhs = 0.0;
581  lhs = - vals1[0] + vals2[0];
582 
583  /* basement row of orbisack */
584  basement = 1;
585 
586  /* update value of left-hand side and coefficients for basement row = 1 */
587  lhs += - vals1[1] + vals2[1];
588  coeff1[1] = -1.0;
589  coeff2[1] = 1.0;
590 
591  /* check whether cut for basement row = 1 is violated */
592  if ( SCIPisEfficacious(scip, lhs - rhs) )
593  {
594  SCIP_CALL( addOrbisackInequality(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
595  ++(*ngen);
596  }
597 
598  /* check whether there exists a cut with basement rows > 1 that is violated */
599  while ( basement < nrows - 1 && ! *infeasible )
600  {
601  valueA = lhs + vals1[basement] - vals1[basement + 1] + vals2[basement + 1] - rhs - 1.0; /*lint !e679, !e834*/
602  valueB = lhs - vals2[basement] - vals1[basement + 1] + vals2[basement + 1] - rhs; /*lint !e679, !e834*/
603  valueC = 2.0 * lhs + vals1[basement] - vals2[basement] - vals1[basement + 1] + vals2[basement + 1] - 2.0 * rhs; /*lint !e679, !e834*/
604 
605  /* update inequality */
606  if ( valueA >= valueB && valueA >= valueC )
607  {
608  ++rhs;
609  coeff1[basement] = 0.0;
610  lhs += vals1[basement++];
611  coeff1[basement] = -1.0;
612  coeff2[basement] = 1.0;
613  lhs += - vals1[basement] + vals2[basement];
614  }
615  else if ( valueB >= valueA && valueB >= valueC )
616  {
617  coeff2[basement] = 0.0;
618  lhs -= vals2[basement++];
619  coeff1[basement] = -1.0;
620  coeff2[basement] = 1.0;
621  lhs += - vals1[basement] + vals2[basement];
622  }
623  else
624  {
625  rhs *= 2.0;
626  lhs = 0.0;
627  for (i = 0; i < basement; ++i)
628  {
629  coeff1[i] = 2.0 * coeff1[i];
630  coeff2[i] = 2.0 * coeff2[i];
631  lhs += coeff1[i] * vals1[i] + coeff2[i] * vals2[i];
632  }
633  coeff1[basement] = -1.0;
634  coeff2[basement] = 1.0;
635  lhs -= vals1[basement];
636  lhs += vals2[basement++];
637  coeff1[basement] = -1.0;
638  coeff2[basement] = 1.0;
639  lhs -= vals1[basement];
640  lhs += vals2[basement];
641  }
642 
643  /* to avoid numerical troubles, we bound the size of coefficients and rhs */
644  if ( rhs > coeffbound || -coeff1[0] > coeffbound || coeff2[0] > coeffbound )
645  {
646  /* avoid separating cover inequalities twice */
647  if ( ! coverseparation )
648  {
649  int ncuts;
650  SCIP_CALL( separateOrbisackCovers(scip, cons, nrows, vars1, vars2, vals1, vals2, &ncuts, infeasible) );
651  *ngen += ncuts;
652  }
653  break;
654  }
655 
656  /* if current inequality is violated */
657  if ( SCIPisEfficacious(scip, lhs - rhs) )
658  {
659  SCIP_CALL( addOrbisackInequality(scip, cons, nrows, vars1, vars2, coeff1, coeff2, rhs, infeasible) );
660  ++(*ngen);
661  }
662  }
663 
664  /* free allocated memory */
665  SCIPfreeBufferArray(scip, &coeff2);
666  SCIPfreeBufferArray(scip, &coeff1);
667 
668  return SCIP_OKAY;
669 }
670 
671 
672 /** Determines if a vector with additional fixings could exist that is lexicographically larger than another vector.
673  *
674  * Given two vectors of variables with local lower and upper bounds, and a set of additional (virtual) fixings.
675  * Assuming that the entries of both vectors are equal until entry "start", this function determines if there exists
676  * a vector where the left vector is lexicographically larger or equal to the right vector.
677  * If a vector exsits, infeasible is set to FALSE, otherwise TRUE.
678  */
679 static
681  SCIP* scip, /**< SCIP pointer */
682  SCIP_VAR** vars1, /**< array of variables in first vector */
683  SCIP_VAR** vars2, /**< array of variables in second vector */
684  int nrows, /**< number of rows */
685  int start, /**< at which row to start (assuming previous rows are equal) */
686  SCIP_Bool* infeasible, /**< pointer to store whether infeasibility is detected in these fixings */
687  int* infeasiblerow /**< pointer to store at which row a (0, 1) pattern is found */
688 )
689 {
690  SCIP_VAR* var1;
691  SCIP_VAR* var2;
692  int var1fix;
693  int var2fix;
694  int i;
695 
696  assert( scip != NULL );
697  assert( vars1 != NULL );
698  assert( vars2 != NULL );
699  assert( infeasible != NULL );
700  assert( start >= 0 );
701 
702  *infeasible = FALSE;
703 
704  for (i = start; i < nrows; ++i)
705  {
706  /* get variables of first and second vector */
707  var1 = vars1[i];
708  var2 = vars2[i];
709 
710  assert( var1 != NULL );
711  assert( var2 != NULL );
712 
713  /* Get virtual fixing of variable in first vector, for var1 */
714  if ( SCIPvarGetUbLocal(var1) < 0.5 )
715  {
716  var1fix = FIXED0;
717  assert( SCIPvarGetLbLocal(var1) <= 0.5 );
718  }
719  else if ( SCIPvarGetLbLocal(var1) > 0.5 )
720  var1fix = FIXED1;
721  else
722  var1fix = UNFIXED;
723 
724  /* Get virtual fixing of variable in second vector, for var2 */
725  if ( SCIPvarGetUbLocal(var2) < 0.5 )
726  {
727  var2fix = FIXED0;
728  assert( SCIPvarGetLbLocal(var2) <= 0.5 );
729  }
730  else if ( SCIPvarGetLbLocal(var2) > 0.5 )
731  var2fix = FIXED1;
732  else
733  var2fix = UNFIXED;
734 
735  /* Encounter one of (_, _), (_, 0), (1, _), (1, 0). In all cases (1, 0) can be constructed. Thus feasible. */
736  if ( var1fix != FIXED0 && var2fix != FIXED1 )
737  break;
738  /* Encounter (0, 1). Infeasible. */
739  else if ( var1fix == FIXED0 && var2fix == FIXED1 )
740  {
741  *infeasible = TRUE;
742  *infeasiblerow = i;
743  break;
744  }
745  /* Remaining cases are (0, _), (_, 1), (0, 0) and (1, 1). In all cases: continue. */
746  }
747 
748  return SCIP_OKAY;
749 }
750 
751 
752 /** propagation */
753 static
755  SCIP* scip, /**< SCIP pointer */
756  SCIP_CONS* cons, /**< constraint to be propagated */
757  SCIP_Bool* infeasible, /**< pointer to store whether it was detected that the node is infeasible */
758  SCIP_Bool* found, /**< pointer to store whether a new propagation could be found */
759  int* ngen /**< pointer to store the number of generated bound strengthenings */
760  )
761 {
762  SCIP_CONSDATA* consdata;
763  SCIP_VAR** vars1;
764  SCIP_VAR** vars2;
765  SCIP_VAR* var1;
766  SCIP_VAR* var2;
767  int var1fix;
768  int var2fix;
769  SCIP_Bool tightened;
770  SCIP_Bool peekinfeasible;
771  int peekinfeasiblerow;
772  int nrows;
773  int i;
774 
775  assert( scip != NULL );
776  assert( cons != NULL );
777  assert( infeasible != NULL );
778  assert( ngen != NULL );
779  assert( found != NULL );
780 
781  SCIPdebugMsg(scip, "Propagating variables of constraint <%s>.\n", SCIPconsGetName(cons));
782 
783  *ngen = 0;
784  *infeasible = FALSE;
785  *found = FALSE;
786 
787  /* get data of constraint */
788  consdata = SCIPconsGetData(cons);
789  assert( consdata != NULL );
790  assert( consdata->vars1 != NULL );
791  assert( consdata->vars2 != NULL );
792  assert( consdata->nrows > 0 );
793 
794  nrows = consdata->nrows;
795  vars1 = consdata->vars1;
796  vars2 = consdata->vars2;
797 
798  /* loop through all variables */
799  for (i = 0; i < nrows; ++i)
800  {
801  /* get variables of first and second column */
802  var1 = vars1[i];
803  var2 = vars2[i];
804  assert( var1 != NULL );
805  assert( var2 != NULL );
806 
807  /* Get the fixing status of the left column variable var1 */
808  if ( SCIPvarGetUbLocal(var1) < 0.5 )
809  {
810  var1fix = FIXED0;
811  assert( SCIPvarGetLbLocal(var1) <= 0.5 );
812  }
813  else if ( SCIPvarGetLbLocal(var1) > 0.5 )
814  var1fix = FIXED1;
815  else
816  var1fix = UNFIXED;
817 
818  /* Get the fixing status of the right column variable var2 */
819  if ( SCIPvarGetUbLocal(var2) < 0.5 )
820  {
821  var2fix = FIXED0;
822  assert( SCIPvarGetLbLocal(var2) <= 0.5 );
823  }
824  else if ( SCIPvarGetLbLocal(var2) > 0.5 )
825  var2fix = FIXED1;
826  else
827  var2fix = UNFIXED;
828 
829  /* Encounter one of (1, 0). All above rows are constant. This is a feasible situation. Stop. */
830  if ( var1fix == FIXED1 && var2fix == FIXED0 )
831  {
832  assert( SCIPvarGetLbLocal(var1) > 0.5 );
833  assert( SCIPvarGetUbLocal(var2) < 0.5 );
834 
835  SCIPdebugMsg(scip, "Row %d is (1, 0)\n", i);
836  break;
837  }
838  /* Encounter one of (_, _), (_, 0), (1, _). Check if a constant row is possible, otherwise fix to (1, 0). */
839  if ( var1fix != FIXED0 && var2fix != FIXED1 )
840  {
841  assert( SCIPvarGetUbLocal(var1) > 0.5 );
842  assert( SCIPvarGetLbLocal(var2) < 0.5 );
843 
844  SCIPdebugMsg(scip, "Row %d is (_, _), (_, 0) or (1, _).\n", i);
845 
846  SCIP_CALL( checkFeasible(scip, vars1, vars2, nrows, i + 1, &peekinfeasible, &peekinfeasiblerow) );
847 
848  if ( peekinfeasible )
849  {
850  /* If row i is constant, then we end up in an infeasible solution. Hence, row i must be (1, 0). */
851  SCIPdebugMsg(scip, "Making row %d constant is infeasible. Fix to (1, 0).\n", i);
852 
853  assert( peekinfeasiblerow > i );
854  assert( peekinfeasiblerow < nrows );
855 
856  if ( var1fix != FIXED1 )
857  {
858  /* Fix variable in first column to 1 */
859  SCIP_CALL( SCIPinferVarLbCons(scip, var1, 1.0, cons, i + nrows * peekinfeasiblerow, FALSE, infeasible,
860  &tightened) ); /*lint !e713*/
861  assert( ! *infeasible );
862 
863  *found = *found || tightened;
864  if ( tightened )
865  ++(*ngen);
866  }
867 
868  if ( var2fix != FIXED0 )
869  {
870  /* Fix variable in second column to 0 */
871  SCIP_CALL( SCIPinferVarUbCons(scip, var2, 0.0, cons, i + nrows * peekinfeasiblerow, FALSE, infeasible,
872  &tightened) ); /*lint !e713*/
873  assert( ! *infeasible );
874 
875  *found = *found || tightened;
876  if ( tightened )
877  ++(*ngen);
878  }
879  }
880 
881  /* In all cases, we could make this row (1, 0), so it is feasible. Stop. */
882  break;
883  }
884  /* Encounter (0, 1): if variable in first column is fixed to 0 and variable in second column is fixed to 1 */
885  else if ( var1fix == FIXED0 && var2fix == FIXED1 )
886  {
887  assert( SCIPvarGetUbLocal(var1) < 0.5 );
888  assert( SCIPvarGetLbLocal(var2) > 0.5 );
889 
890  SCIPdebugMsg(scip, "Row %d is (0, 1). Infeasible!\n", i);
891 
892  /* Mark solution as infeasible. */
893  *infeasible = TRUE;
894 
895  /* Perform conflict analysis */
897  {
899 
900  /* Mark all variables from row i and above as part of the conflict */
901  while (i >= 0)
902  {
903  SCIP_CALL( SCIPaddConflictBinvar(scip, vars1[i]) );
904  SCIP_CALL( SCIPaddConflictBinvar(scip, vars2[i--]) ); /*lint !e850*/
905  }
906 
907  SCIP_CALL( SCIPanalyzeConflictCons(scip, cons, NULL) );
908  }
909 
910  break;
911  }
912  /* Encounter (0, _): Fix second part to 0 */
913  else if ( var1fix == FIXED0 && var2fix != FIXED0 )
914  {
915  assert( SCIPvarGetUbLocal(var1) < 0.5 );
916  assert( SCIPvarGetLbLocal(var2) < 0.5 );
917  assert( SCIPvarGetUbLocal(var2) > 0.5 );
918 
919  SCIPdebugMsg(scip, "Row %d is (0, _). Fixing to (0, 0).\n", i);
920 
921  SCIP_CALL( SCIPinferVarUbCons(scip, var2, 0.0, cons, i, FALSE, infeasible, &tightened) ); /*lint !e713*/
922  assert( ! *infeasible );
923 
924  *found = *found || tightened;
925  if ( tightened )
926  ++(*ngen);
927  }
928  /* Encounter (_, 1): fix first part to 1 */
929  else if ( var1fix != FIXED1 && var2fix == FIXED1 )
930  {
931  assert( SCIPvarGetLbLocal(var1) < 0.5 );
932  assert( SCIPvarGetUbLocal(var1) > 0.5 );
933  assert( SCIPvarGetLbLocal(var2) > 0.5 );
934 
935  SCIPdebugMsg(scip, "Row %d is (_, 1). Fixing to (1, 1).\n", i);
936 
937  SCIP_CALL( SCIPinferVarLbCons(scip, var1, 1.0, cons, i, FALSE, infeasible, &tightened) ); /*lint !e713*/
938  assert( ! *infeasible );
939 
940  *found = *found || tightened;
941  if ( tightened )
942  ++(*ngen);
943  }
944  /* Remaining cases are (0, 0) and (1, 1). In these cases we can continue! */
945  }
946 
947  SCIPdebugMsg(scip, "No further fixings possible. Stopping at row %d\n", i);
948  return SCIP_OKAY;
949 }
950 
951 
952 /** separate orbisack and cover inequalities */
953 static
955  SCIP* scip, /**< pointer to scip */
956  SCIP_RESULT* result, /**< pointer to store the result of separation */
957  SCIP_CONS* cons, /**< constraint */
958  int nrows, /**< number of rows of orbisack */
959  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
960  SCIP_VAR*const* vars2, /**< variables of second column */
961  SCIP_Real* vals1, /**< LP-solution for those variables in first column */
962  SCIP_Real* vals2 /**< LP-solution for those variables in second column */
963  )
964 {
965  SCIP_CONSHDLRDATA* conshdlrdata;
966  SCIP_Bool infeasible = FALSE;
967  int ngen1 = 0;
968  int ngen2 = 0;
969 
970  assert( scip != NULL );
971  assert( result != NULL );
972  assert( cons != NULL );
973  assert( vars1 != NULL );
974  assert( vars2 != NULL );
975  assert( vals1 != NULL );
976  assert( vals2 != NULL );
977 
978  conshdlrdata = SCIPconshdlrGetData(SCIPconsGetHdlr(cons));
979  assert( conshdlrdata != NULL );
980 
981  if ( conshdlrdata->orbiseparation )
982  {
983  SCIP_CALL( separateOrbisack(scip, cons, nrows, vars1, vars2, vals1, vals2, FALSE, conshdlrdata->coeffbound, &ngen1, &infeasible) );
984  }
985 
986  if ( ! infeasible && conshdlrdata->coverseparation )
987  {
988  SCIP_CALL( separateOrbisackCovers(scip, cons, nrows, vars1, vars2, vals1, vals2, &ngen2, &infeasible) );
989  }
990 
991  if ( infeasible )
992  {
993  *result = SCIP_CUTOFF;
994  return SCIP_OKAY;
995  }
996 
997  if ( ngen1 + ngen2 > 0 )
998  *result = SCIP_SEPARATED;
999 
1000  return SCIP_OKAY;
1001 }
1002 
1003 
1004 /*--------------------------------------------------------------------------------------------
1005  *--------------------------------- SCIP functions -------------------------------------------
1006  *--------------------------------------------------------------------------------------------*/
1007 
1008 /** copy method for constraint handler plugins (called when SCIP copies plugins) */
1009 static
1010 SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbisack)
1011 { /*lint --e{715}*/
1012  assert(scip != NULL);
1013  assert(conshdlr != NULL);
1014  assert(strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0);
1015 
1016  /* call inclusion method of constraint handler */
1018 
1019  *valid = TRUE;
1020 
1021  return SCIP_OKAY;
1022 }
1023 
1024 /** frees specific constraint data */
1025 static
1026 SCIP_DECL_CONSDELETE(consDeleteOrbisack)
1027 { /*lint --e{715}*/
1028  assert( scip != 0 );
1029  assert( conshdlr != 0 );
1030  assert( consdata != 0 );
1031  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1032 
1033  SCIP_CALL( consdataFree(scip, consdata) );
1034 
1035  return SCIP_OKAY;
1036 }
1037 
1038 
1039 /** frees constraint handler */
1040 static
1041 SCIP_DECL_CONSFREE(consFreeOrbisack)
1042 { /*lint --e{715}*/
1043  SCIP_CONSHDLRDATA* conshdlrdata;
1044 
1045  assert( scip != 0 );
1046  assert( conshdlr != 0 );
1047  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1048 
1049  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1050  assert( conshdlrdata != NULL );
1051 
1052  SCIPfreeBlockMemory(scip, &conshdlrdata);
1053 
1054  return SCIP_OKAY;
1055 }
1056 
1057 
1058 /** transforms constraint data into data belonging to the transformed problem */
1059 static
1060 SCIP_DECL_CONSTRANS(consTransOrbisack)
1062  SCIP_CONSDATA* sourcedata;
1063  SCIP_CONSDATA* consdata = NULL;
1064 
1065  assert( scip != NULL );
1066  assert( conshdlr != NULL );
1067  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1068  assert( sourcecons != NULL );
1069  assert( targetcons != NULL );
1070 
1071  SCIPdebugMsg(scip, "Transforming constraint.\n");
1072 
1073  /* get data of original constraint */
1074  sourcedata = SCIPconsGetData(sourcecons);
1075 
1076  /* create constraint data */
1077  SCIP_CALL( consdataCreate(scip, &consdata, sourcedata->vars1, sourcedata->vars2,
1078  sourcedata->nrows, sourcedata->ismodelcons) );
1079 
1080  /* create transformed constraint */
1081  SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, consdata,
1082  SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
1083  SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
1084  SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
1085  SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
1086  SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1087 
1088  return SCIP_OKAY;
1089 }
1090 
1091 
1092 /** LP initialization method of constraint handler (called before the initial LP relaxation at a node is solved) */
1093 static
1094 SCIP_DECL_CONSINITLP(consInitlpOrbisack)
1096  int c;
1097 
1098  assert( infeasible != NULL );
1099  *infeasible = FALSE;
1100 
1101  assert( scip != 0 );
1102  assert( conshdlr != 0 );
1103  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1104 
1105  /* loop through constraints */
1106  for (c = 0; c < nconss; ++c)
1107  {
1108  assert( conss[c] != 0 );
1109 
1110  SCIPdebugMsg(scip, "Generating initial orbisack cut for constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1111 
1112  SCIP_CALL( initLP(scip, conss[c], infeasible) );
1113  if ( *infeasible )
1114  break;
1115 
1116  SCIPdebugMsg(scip, "Generated initial orbisack cut.\n");
1117  }
1118 
1119  return SCIP_OKAY;
1120 }
1121 
1122 
1123 /** solving process initialization method of constraint handler (called when branch and bound process is about to begin) */
1124 static
1125 SCIP_DECL_CONSINITSOL(consInitsolOrbisack)
1127  SCIP_CONSHDLRDATA* conshdlrdata;
1128  int c;
1129 
1130  assert( scip != NULL );
1131  assert( conshdlr != NULL );
1132  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1133 
1134  /* determine maximum number of rows in an orbisack constraint */
1135  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1136  assert( conshdlrdata != NULL );
1137 
1138  conshdlrdata->maxnrows = 0;
1139 
1140  /* loop through constraints */
1141  for (c = 0; c < nconss; ++c)
1142  {
1143  SCIP_CONSDATA* consdata;
1144 
1145  assert( conss[c] != NULL );
1146 
1147  consdata = SCIPconsGetData(conss[c]);
1148  assert( consdata != NULL );
1149 
1150  /* update conshdlrdata if necessary */
1151  if ( consdata->nrows > conshdlrdata->maxnrows )
1152  conshdlrdata->maxnrows = consdata->nrows;
1153  }
1154 
1155  return SCIP_OKAY;
1156 }
1157 
1158 
1159 /** separation method of constraint handler for LP solution */
1160 static
1161 SCIP_DECL_CONSSEPALP(consSepalpOrbisack)
1162 { /*lint --e{715}*/
1163  SCIP_CONSDATA* consdata;
1164  SCIP_Real* vals1;
1165  SCIP_Real* vals2;
1166  int c;
1167 
1168  assert( scip != NULL );
1169  assert( conshdlr != NULL );
1170  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1171  assert( result != NULL );
1172 
1173  SCIPdebugMsg(scip, "Separation method for orbisack constraints.\n");
1174 
1175  *result = SCIP_DIDNOTRUN;
1176 
1177  /* if solution is not integer */
1178  if ( SCIPgetNLPBranchCands(scip) > 0 )
1179  {
1180  SCIP_CONSHDLRDATA* conshdlrdata;
1181  int nvals;
1182 
1183  *result = SCIP_DIDNOTFIND;
1184 
1185  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1186  assert( conshdlrdata != NULL );
1187 
1188  nvals = conshdlrdata->maxnrows;
1189  assert( nvals > 0 );
1190 
1191  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1192  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1193 
1194  /* loop through constraints */
1195  for (c = 0; c < nconss; ++c)
1196  {
1197  /* get data of constraint */
1198  assert( conss[c] != NULL );
1199  consdata = SCIPconsGetData(conss[c]);
1200 
1201  /* get solution */
1202  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars1, vals1) );
1203  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars2, vals2) );
1204 
1205  SCIPdebugMsg(scip, "Separating orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1206 
1207  SCIP_CALL( separateInequalities(scip, result, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2) );
1208 
1209  if ( *result == SCIP_CUTOFF )
1210  break;
1211  }
1212 
1213  SCIPfreeBufferArray(scip, &vals2);
1214  SCIPfreeBufferArray(scip, &vals1);
1215  }
1216 
1217  return SCIP_OKAY;
1218 }
1219 
1220 
1221 /** separation method of constraint handler for arbitrary primal solution */
1222 static
1223 SCIP_DECL_CONSSEPASOL(consSepasolOrbisack)
1224 { /*lint --e{715}*/
1225  SCIP_CONSDATA* consdata;
1226  SCIP_Real* vals1;
1227  SCIP_Real* vals2;
1228  int c;
1229 
1230  assert( scip != NULL );
1231  assert( conshdlr != NULL );
1232  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1233  assert( result != NULL );
1234 
1235  SCIPdebugMsg(scip, "Separation method for orbisack constraints\n");
1236 
1237  *result = SCIP_DIDNOTFIND;
1238 
1239  if ( nconss > 0 )
1240  {
1241  SCIP_CONSHDLRDATA* conshdlrdata;
1242  int nvals;
1243 
1244  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1245  assert( conshdlrdata != NULL );
1246 
1247  nvals = conshdlrdata->maxnrows;
1248  assert( nvals > 0 );
1249 
1250  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1251  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1252 
1253  /* loop through constraints */
1254  for (c = 0; c < nconss; ++c)
1255  {
1256  /* get data of constraint */
1257  assert( conss[c] != NULL );
1258  consdata = SCIPconsGetData(conss[c]);
1259 
1260  /* get solution */
1261  assert( consdata->nrows <= nvals );
1262  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars1, vals1) );
1263  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars2, vals2) );
1264 
1265  SCIPdebugMsg(scip, "Separating orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1266 
1267  SCIP_CALL( separateInequalities(scip, result, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2) );
1268  if ( *result == SCIP_CUTOFF )
1269  break;
1270  }
1271 
1272  SCIPfreeBufferArray(scip, &vals2);
1273  SCIPfreeBufferArray(scip, &vals1);
1274  }
1275 
1276  return SCIP_OKAY;
1277 }
1278 
1279 
1280 /** constraint enforcing method of constraint handler for LP solutions
1281  *
1282  * @pre It is assumed that the solution is integral (this can be ensured by appropriate priorities).
1283  */
1284 static
1285 SCIP_DECL_CONSENFOLP(consEnfolpOrbisack)
1286 { /*lint --e{715}*/
1287  SCIP_CONSDATA* consdata;
1288  SCIP_Bool infeasible = FALSE;
1289  SCIP_Real* vals1;
1290  SCIP_Real* vals2;
1291  int ngen = 0;
1292  int c;
1293 
1294  assert( scip != 0 );
1295  assert( conshdlr != 0 );
1296  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1297  assert( result != 0 );
1298 
1299  SCIPdebugMsg(scip, "Enfolp method for orbisack constraints\n");
1300 
1301  /* we have a negative priority, so we should come after the integrality conshdlr. */
1302  assert( SCIPgetNLPBranchCands(scip) == 0 );
1303 
1304  *result = SCIP_FEASIBLE;
1305 
1306  if ( nconss > 0 )
1307  {
1308  SCIP_CONSHDLRDATA* conshdlrdata;
1309  int nvals;
1310 
1311  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1312  assert( conshdlrdata != NULL );
1313 
1314  nvals = conshdlrdata->maxnrows;
1315  assert( nvals > 0 );
1316 
1317  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1318  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1319 
1320  /* loop through constraints */
1321  for (c = 0; c < nconss; ++c)
1322  {
1323  /* get data of constraint */
1324  assert( conss[c] != 0 );
1325  consdata = SCIPconsGetData(conss[c]);
1326  assert( consdata != NULL );
1327 
1328  /* do not enforce non-model constraints */
1329  if ( !consdata->ismodelcons )
1330  continue;
1331 
1332  /* get solution */
1333  assert( consdata->nrows <= nvals );
1334  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars1, vals1) );
1335  SCIP_CALL( SCIPgetSolVals(scip, NULL, consdata->nrows, consdata->vars2, vals2) );
1336 
1337  SCIPdebugMsg(scip, "Enforcing orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1338 
1339  /* Separate only cover inequalities to ensure that enforcing works correctly. */
1340  /* Otherwise, it may happen that infeasible solutions cannot be detected, since */
1341  /* we bound the size of the coefficients for the orbisack inequalities. */
1342  SCIP_CALL( separateOrbisackCovers(scip, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2, &ngen, &infeasible) );
1343 
1344  if ( infeasible )
1345  {
1346  *result = SCIP_CUTOFF;
1347  break;
1348  }
1349 
1350  SCIPdebugMsg(scip, "Generated orbisack inequalities for <%s>: %d\n", SCIPconsGetName(conss[c]), ngen);
1351 
1352  if ( ngen > 0 )
1353  *result = SCIP_SEPARATED;
1354  }
1355 
1356  SCIPfreeBufferArray(scip, &vals2);
1357  SCIPfreeBufferArray(scip, &vals1);
1358  }
1359 
1360  return SCIP_OKAY;
1361 }
1362 
1363 
1364 /** constraint enforcing method of constraint handler for pseudo solutions */
1365 static
1366 SCIP_DECL_CONSENFOPS(consEnfopsOrbisack)
1367 { /*lint --e{715}*/
1368  SCIP_Bool feasible = TRUE;
1369  SCIP_CONSDATA* consdata;
1370  int c;
1371 
1372  assert( scip != NULL );
1373  assert( conshdlr != NULL );
1374  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1375  assert( result != NULL );
1376 
1377  SCIPdebugMsg(scip, "Enforcing method for orbisack constraints (pseudo solutions) ...\n");
1378 
1379  *result = SCIP_FEASIBLE;
1380 
1381  if ( objinfeasible || solinfeasible )
1382  return SCIP_OKAY;
1383 
1384  /* loop through constraints */
1385  for (c = 0; c < nconss; ++c)
1386  {
1387  /* get data of constraint */
1388  assert( conss[c] != NULL );
1389  consdata = SCIPconsGetData(conss[c]);
1390  assert( consdata != NULL);
1391  assert( consdata->nrows > 0 );
1392  assert( consdata->vars1 != NULL );
1393  assert( consdata->vars2 != NULL );
1394 
1395  /* do not enforce non-model constraints */
1396  if ( !consdata->ismodelcons )
1397  continue;
1398 
1399  SCIP_CALL( SCIPcheckSolutionOrbisack(scip, NULL, consdata->vars1, consdata->vars2, consdata->nrows, FALSE, &feasible) );
1400 
1401  if ( ! feasible )
1402  {
1403  *result = SCIP_INFEASIBLE;
1404  break;
1405  }
1406  }
1407 
1408  return SCIP_OKAY;
1409 }
1410 
1411 
1412 /** constraint enforcing method of constraint handler for relaxation solutions */
1413 static
1414 SCIP_DECL_CONSENFORELAX(consEnforelaxOrbisack)
1415 { /*lint --e{715}*/
1416  SCIP_CONSDATA* consdata;
1417  SCIP_Bool infeasible = FALSE;
1418  SCIP_Real* vals1;
1419  SCIP_Real* vals2;
1420  int ngen = 0;
1421  int c;
1422 
1423  assert( scip != 0 );
1424  assert( conshdlr != 0 );
1425  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1426  assert( result != 0 );
1427 
1428  SCIPdebugMsg(scip, "Enforelax method for orbisack constraints.\n");
1429 
1430  /* we have a negative priority, so we should come after the integrality conshdlr. */
1431  assert( SCIPgetNLPBranchCands(scip) == 0 );
1432 
1433  *result = SCIP_FEASIBLE;
1434 
1435  if ( nconss > 0 )
1436  {
1437  SCIP_CONSHDLRDATA* conshdlrdata;
1438  int nvals;
1439 
1440  conshdlrdata = SCIPconshdlrGetData(conshdlr);
1441  assert( conshdlrdata != NULL );
1442 
1443  nvals = conshdlrdata->maxnrows;
1444  assert( nvals > 0 );
1445 
1446  SCIP_CALL( SCIPallocBufferArray(scip, &vals1, nvals) );
1447  SCIP_CALL( SCIPallocBufferArray(scip, &vals2, nvals) );
1448 
1449  /* loop through constraints */
1450  for (c = 0; c < nconss; ++c)
1451  {
1452  /* get data of constraint */
1453  assert( conss[c] != 0 );
1454  consdata = SCIPconsGetData(conss[c]);
1455  assert( consdata != NULL );
1456 
1457  /* do not enforce non-model constraints */
1458  if ( !consdata->ismodelcons )
1459  continue;
1460 
1461  /* get solution */
1462  assert( consdata->nrows <= nvals );
1463  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars1, vals1) );
1464  SCIP_CALL( SCIPgetSolVals(scip, sol, consdata->nrows, consdata->vars2, vals2) );
1465 
1466  SCIPdebugMsg(scip, "Enforcing orbisack constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1467 
1468  /* Separate only cover inequalities to ensure that enforcing works correctly. */
1469  /* Otherwise, it may happen that infeasible solutions cannot be detected, since */
1470  /* we bound the size of the coefficients for the orbisack inequalities. */
1471  SCIP_CALL( separateOrbisackCovers(scip, conss[c], consdata->nrows, consdata->vars1, consdata->vars2, vals1, vals2, &ngen, &infeasible) );
1472 
1473  if ( infeasible )
1474  {
1475  *result = SCIP_CUTOFF;
1476  break;
1477  }
1478 
1479  SCIPdebugMsg(scip, "Generated orbisack inequalities for <%s>: %d\n", SCIPconsGetName(conss[c]), ngen);
1480 
1481  if ( ngen > 0 )
1482  *result = SCIP_SEPARATED;
1483  }
1484 
1485  SCIPfreeBufferArray(scip, &vals2);
1486  SCIPfreeBufferArray(scip, &vals1);
1487  }
1488 
1489  return SCIP_OKAY;
1490 }
1491 
1492 
1493 /** feasibility check method of constraint handler for integral solutions */
1494 static
1495 SCIP_DECL_CONSCHECK(consCheckOrbisack)
1496 { /*lint --e{715}*/
1497  SCIP_Bool feasible = TRUE;
1498  SCIP_CONSDATA* consdata;
1499  int c;
1500 
1501  assert( scip != NULL );
1502  assert( conshdlr != NULL );
1503  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1504  assert( result != NULL );
1505 
1506  *result = SCIP_FEASIBLE;
1507 
1508  /* loop through constraints */
1509  for (c = 0; c < nconss; ++c)
1510  {
1511  /* get data of constraint */
1512  assert( conss[c] != NULL );
1513  consdata = SCIPconsGetData(conss[c]);
1514  assert( consdata != NULL);
1515  assert( consdata->nrows > 0 );
1516  assert( consdata->vars1 != NULL );
1517  assert( consdata->vars2 != NULL );
1518 
1519  SCIPdebugMsg(scip, "Check method for orbisack constraint <%s> (%d rows) ...\n", SCIPconsGetName(conss[c]), consdata->nrows);
1520 
1521  /* do not check non-model constraints */
1522  if ( !consdata->ismodelcons )
1523  continue;
1524 
1525  SCIP_CALL( SCIPcheckSolutionOrbisack(scip, sol, consdata->vars1, consdata->vars2, consdata->nrows, printreason, &feasible) );
1526 
1527  if ( ! feasible )
1528  {
1529  *result = SCIP_INFEASIBLE;
1530  SCIPdebugMsg(scip, "Solution is feasible.\n");
1531  break;
1532  }
1533  }
1534 
1535  if ( feasible )
1536  SCIPdebugMsg(scip, "Solution is feasible.\n");
1537 
1538  return SCIP_OKAY;
1539 }
1540 
1541 
1542 /** domain propagation method of constraint handler */
1543 static
1544 SCIP_DECL_CONSPROP(consPropOrbisack)
1545 { /*lint --e{715}*/
1546  int c;
1547 
1548  assert( scip != NULL );
1549  assert( conshdlr != NULL );
1550  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1551  assert( result != NULL );
1552 
1553  *result = SCIP_DIDNOTRUN;
1554 
1555  SCIPdebugMsg(scip, "Propagation method of orbisack constraint handler.\n");
1556 
1557  /* loop through constraints */
1558  for (c = 0; c < nconss; ++c)
1559  {
1560  SCIP_Bool infeasible = FALSE;
1561  SCIP_Bool found = FALSE;
1562  int ngen = 0;
1563 
1564  assert( conss[c] != NULL );
1565 
1566  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &found, &ngen) );
1567 
1568  if ( infeasible )
1569  {
1570  *result = SCIP_CUTOFF;
1571  return SCIP_OKAY;
1572  }
1573 
1574  if ( found )
1575  *result = SCIP_REDUCEDDOM;
1576  }
1577 
1578  return SCIP_OKAY;
1579 }
1580 
1581 
1582 /** presolving method of constraint handler */
1583 static
1584 SCIP_DECL_CONSPRESOL(consPresolOrbisack)
1585 { /*lint --e{715}*/
1586  int c;
1587  int ngen = 0;
1588 
1589  assert( scip != NULL );
1590  assert( conshdlr != NULL );
1591  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1592  assert( result != NULL );
1593 
1594  SCIPdebugMsg(scip, "Presolving method of orbisack constraint handler. Propagating orbisack inequalities.\n");
1595 
1596  *result = SCIP_DIDNOTFIND;
1597 
1598  /* loop through constraints */
1599  for (c = 0; c < nconss; ++c)
1600  {
1601  SCIP_Bool infeasible = FALSE;
1602  SCIP_Bool found = FALSE;
1603  int curngen = 0;
1604 
1605  assert( conss[c] != NULL );
1606  SCIP_CALL( propVariables(scip, conss[c], &infeasible, &found, &curngen) );
1607 
1608  if ( infeasible )
1609  {
1610  *result = SCIP_CUTOFF;
1611  break;
1612  }
1613 
1614  ngen += curngen;
1615  }
1616 
1617  if ( ngen > 0 )
1618  {
1619  *nfixedvars += ngen;
1620  *result = SCIP_SUCCESS;
1621  }
1622 
1623  return SCIP_OKAY;
1624 }
1625 
1626 
1627 /** Propagation resolution for conflict analysis */
1628 static
1629 SCIP_DECL_CONSRESPROP(consRespropOrbisack)
1630 { /*lint --e{715}*/
1631  SCIP_CONSDATA* consdata;
1632  SCIP_VAR** vars1;
1633  SCIP_VAR** vars2;
1634  int i;
1635  int varrow;
1636  int infrow;
1637 
1638  assert( scip != NULL );
1639  assert( conshdlr != NULL );
1640  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1641  assert( cons != NULL );
1642  assert( infervar != NULL );
1643  assert( bdchgidx != NULL );
1644  assert( result != NULL );
1645 
1646  SCIPdebugMsg(scip, "Propagation resolution method of orbisack constraint handler.\n");
1647 
1648  *result = SCIP_DIDNOTFIND;
1649 
1650  consdata = SCIPconsGetData(cons);
1651  assert( consdata != NULL);
1652  assert( consdata->nrows > 0 );
1653  assert( consdata->vars1 != NULL );
1654  assert( consdata->vars2 != NULL );
1655 
1656  vars1 = consdata->vars1;
1657  vars2 = consdata->vars2;
1658 
1659  /* inferinfo == varrow + infrow * nrows. infrow is 0 if the fixing is not caused by a lookahead. */
1660  varrow = inferinfo % consdata->nrows;
1661  infrow = inferinfo / consdata->nrows;
1662 
1663  assert( varrow >= 0 );
1664  assert( varrow < consdata->nrows );
1665  assert( infrow >= 0 );
1666  assert( infrow < consdata->nrows );
1667 
1668  /* In both cases, the rows until "varrow" are constants. */
1669  for (i = 0; i < varrow; ++i)
1670  {
1671  /* Conflict caused by bounds of previous variables */
1672  SCIP_CALL( SCIPaddConflictUb(scip, vars1[i], bdchgidx) );
1673  SCIP_CALL( SCIPaddConflictLb(scip, vars1[i], bdchgidx) );
1674  SCIP_CALL( SCIPaddConflictUb(scip, vars2[i], bdchgidx) );
1675  SCIP_CALL( SCIPaddConflictLb(scip, vars2[i], bdchgidx) );
1676  }
1677 
1678  if ( infrow > 0 )
1679  {
1680  /* The fixing of infervar is caused by a lookahead (checkFeasible).
1681  * The rows until "varrow" are constants, and row "varrow" is (_, _), (1, _), (_, 0).
1682  * If we assume "varrow" is constant, then the next rows until infrow are constants, and infrow is (0, 1).
1683  */
1684  for (i = varrow + 1; i < infrow; ++i)
1685  {
1686  /* These rows are one of (0, 0), (1, 1), (0, _), (_, 1), making them constants. */
1687  SCIP_CALL( SCIPaddConflictUb(scip, vars1[i], bdchgidx) );
1688  SCIP_CALL( SCIPaddConflictLb(scip, vars1[i], bdchgidx) );
1689  SCIP_CALL( SCIPaddConflictUb(scip, vars2[i], bdchgidx) );
1690  SCIP_CALL( SCIPaddConflictLb(scip, vars2[i], bdchgidx) );
1691  }
1692 
1693  /* And infrow itself is (0, 1). */
1694  assert( SCIPvarGetUbAtIndex(vars1[infrow], bdchgidx, TRUE) < 0.5 );
1695  assert( SCIPvarGetUbAtIndex(vars1[infrow], bdchgidx, FALSE) < 0.5 );
1696  assert( SCIPvarGetLbAtIndex(vars2[infrow], bdchgidx, TRUE) > 0.5 );
1697  assert( SCIPvarGetLbAtIndex(vars2[infrow], bdchgidx, FALSE) > 0.5 );
1698 
1699  SCIP_CALL( SCIPaddConflictUb(scip, vars1[infrow], bdchgidx) );
1700  SCIP_CALL( SCIPaddConflictLb(scip, vars2[infrow], bdchgidx) );
1701  }
1702  else
1703  {
1704  /* This is not a fixing caused by lookahead (checkFeasible),
1705  * so row "varrow" was (0, _) or (_, 1) and its previous rows are constants.
1706  */
1707  if ( boundtype == SCIP_BOUNDTYPE_LOWER )
1708  {
1709  /* We changed the lower bound of infervar to 1. This means that this fixing is due to (_, 1) */
1710  assert( infervar == vars1[varrow] );
1711  assert( SCIPvarGetLbAtIndex(vars1[varrow], bdchgidx, FALSE) < 0.5 );
1712  assert( SCIPvarGetLbAtIndex(vars1[varrow], bdchgidx, TRUE) > 0.5 );
1713  assert( SCIPvarGetLbAtIndex(vars2[varrow], bdchgidx, FALSE ) > 0.5);
1714  assert( SCIPvarGetUbAtIndex(vars2[varrow], bdchgidx, FALSE ) > 0.5);
1715 
1716  SCIP_CALL( SCIPaddConflictUb(scip, vars2[varrow], bdchgidx) );
1717  SCIP_CALL( SCIPaddConflictLb(scip, vars2[varrow], bdchgidx) );
1718  }
1719  else
1720  {
1721  /* We changed the upper bound to 0. This means that this fixing is due to (0, _) */
1722  assert( infervar == vars2[varrow] );
1723  assert( SCIPvarGetLbAtIndex(vars1[varrow], bdchgidx, FALSE ) < 0.5);
1724  assert( SCIPvarGetUbAtIndex(vars1[varrow], bdchgidx, FALSE ) < 0.5);
1725  assert( SCIPvarGetUbAtIndex(vars2[varrow], bdchgidx, FALSE) > 0.5 );
1726  assert( SCIPvarGetUbAtIndex(vars2[varrow], bdchgidx, TRUE) < 0.5 );
1727 
1728  SCIP_CALL( SCIPaddConflictUb(scip, vars1[varrow], bdchgidx) );
1729  SCIP_CALL( SCIPaddConflictLb(scip, vars1[varrow], bdchgidx) );
1730  }
1731  }
1732 
1733  *result = SCIP_SUCCESS;
1734  return SCIP_OKAY;
1735 }
1736 
1737 
1738 /** Lock variables
1739  *
1740  * We assume we have only one global (void) constraint and lock all variables.
1741  *
1742  * - Orbisack constraints may get violated if the variables of the first column
1743  * are rounded down, we therefor call SCIPaddVarLocksType(..., nlockspos, nlocksneg).
1744  * - Orbisack constraints may get violated if the variables of the second column
1745  * are rounded up , we therefor call SCIPaddVarLocksType(..., nlocksneg, nlockspo ).
1746  */
1747 static
1748 SCIP_DECL_CONSLOCK(consLockOrbisack)
1749 { /*lint --e{715}*/
1750  SCIP_CONSDATA* consdata;
1751  SCIP_VAR** vars1;
1752  SCIP_VAR** vars2;
1753  int nrows;
1754  int i;
1755 
1756  assert( scip != NULL );
1757  assert( conshdlr != NULL );
1758  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1759  assert( cons != NULL );
1760 
1761  SCIPdebugMsg(scip, "Locking method for orbisack constraint handler.\n");
1762 
1763  /* get data of original constraint */
1764  consdata = SCIPconsGetData(cons);
1765  assert( consdata != NULL);
1766  assert( consdata->nrows > 0 );
1767  assert( consdata->vars1 != NULL );
1768  assert( consdata->vars2 != NULL );
1769 
1770  nrows = consdata->nrows;
1771  vars1 = consdata->vars1;
1772  vars2 = consdata->vars2;
1773 
1774  for (i = 0; i < nrows; ++i)
1775  {
1776  SCIP_CALL( SCIPaddVarLocksType(scip, vars1[i], locktype, nlockspos, nlocksneg) );
1777  SCIP_CALL( SCIPaddVarLocksType(scip, vars2[i], locktype, nlocksneg, nlockspos) );
1778  }
1779 
1780  return SCIP_OKAY;
1781 }
1782 
1783 
1784 /** constraint copying method of constraint handler */
1785 static
1786 SCIP_DECL_CONSCOPY(consCopyOrbisack)
1788  SCIP_CONSHDLRDATA* conshdlrdata;
1789  SCIP_CONSDATA* sourcedata;
1790  SCIP_VAR** sourcevars1;
1791  SCIP_VAR** sourcevars2;
1792  SCIP_VAR** vars1;
1793  SCIP_VAR** vars2;
1794  int nrows;
1795  int i;
1796 
1797  assert( scip != NULL );
1798  assert( cons != NULL );
1799  assert( sourcescip != NULL );
1800  assert( sourceconshdlr != NULL );
1801  assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
1802  assert( sourcecons != NULL );
1803  assert( varmap != NULL );
1804  assert( valid != NULL );
1805 
1806  *valid = TRUE;
1807 
1808  SCIPdebugMsg(scip, "Copying method for orbisack constraint handler.\n");
1809 
1810  sourcedata = SCIPconsGetData(sourcecons);
1811  assert( sourcedata != NULL );
1812  assert( sourcedata->vars1 != NULL );
1813  assert( sourcedata->vars2 != NULL );
1814  assert( sourcedata->nrows > 0 );
1815 
1816  conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
1817  assert( conshdlrdata != NULL );
1818 
1819  /* do not copy non-model constraints */
1820  if ( !sourcedata->ismodelcons && !conshdlrdata->forceconscopy )
1821  {
1822  *valid = FALSE;
1823 
1824  return SCIP_OKAY;
1825  }
1826 
1827  sourcevars1 = sourcedata->vars1;
1828  sourcevars2 = sourcedata->vars2;
1829  nrows = sourcedata->nrows;
1830 
1831  SCIP_CALL( SCIPallocBufferArray(scip, &vars1, nrows) );
1832 
1833  for (i = 0; i < nrows && *valid; ++i)
1834  {
1835  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars1[i], &(vars1[i]), varmap, consmap, global, valid) );
1836  assert( !(*valid) || vars1[i] != NULL );
1837  }
1838 
1839  /* only create the target constraint, if all variables could be copied */
1840  if ( !(*valid) )
1841  {
1842  SCIPfreeBufferArray(scip, &vars1);
1843 
1844  return SCIP_OKAY;
1845  }
1846 
1847  SCIP_CALL( SCIPallocBufferArray(scip, &vars2, nrows) );
1848 
1849  for (i = 0; i < nrows && *valid; ++i)
1850  {
1851  SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars2[i], &(vars2[i]), varmap, consmap, global, valid) );
1852  assert( !(*valid) || vars2[i] != NULL );
1853  }
1854 
1855  /* only create the target constraint, if all variables could be copied */
1856  if ( *valid )
1857  {
1858  /* create copied constraint */
1859  if ( name == NULL )
1860  name = SCIPconsGetName(sourcecons);
1861 
1862  SCIP_CALL( SCIPcreateConsOrbisack(scip, cons, name, vars1, vars2, nrows, FALSE, FALSE, sourcedata->ismodelcons,
1863  initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1864  }
1865 
1866  SCIPfreeBufferArray(scip, &vars2);
1867  SCIPfreeBufferArray(scip, &vars1);
1868 
1869  return SCIP_OKAY;
1870 }
1871 
1872 
1873 /** constraint parsing method of constraint handler */
1874 static
1875 SCIP_DECL_CONSPARSE(consParseOrbisack)
1876 { /*lint --e{715}*/
1877  const char* s;
1878  char* endptr;
1879  SCIP_VAR** vars1;
1880  SCIP_VAR** vars2;
1881  SCIP_VAR* var;
1882  int nrows = 0;
1883  int maxnrows = 128;
1884  SCIP_Bool firstcolumn = TRUE;
1885  SCIP_Bool ispporbisack = FALSE;
1886  SCIP_Bool isparttype = FALSE;
1887 
1888  assert( success != NULL );
1889 
1890  *success = TRUE;
1891  s = str;
1892 
1893  /* skip white space */
1894  while ( *s != '\0' && isspace((unsigned char)*s) )
1895  ++s;
1896 
1897  if ( strncmp(s, "partOrbisack(", 13) == 0 )
1898  {
1899  ispporbisack = TRUE;
1900  isparttype = TRUE;
1901  }
1902  else if ( strncmp(s, "packOrbisack(", 13) == 0 )
1903  ispporbisack = TRUE;
1904  else
1905  {
1906  if ( strncmp(s, "fullOrbisack(", 13) != 0 )
1907  {
1908  SCIPerrorMessage("Syntax error - expected \"fullOrbisack(\", \"partOrbisack\" or \"packOrbisacj\": %s\n", s);
1909  *success = FALSE;
1910  return SCIP_OKAY;
1911  }
1912  }
1913  s += 13;
1914 
1915  /* loop through string */
1916  SCIP_CALL( SCIPallocBufferArray(scip, &vars1, maxnrows) );
1917  SCIP_CALL( SCIPallocBufferArray(scip, &vars2, maxnrows) );
1918 
1919  do
1920  {
1921  /* skip whitespace */
1922  while ( *s != '\0' && isspace((unsigned char)*s) )
1923  ++s;
1924 
1925  /* parse variable name */
1926  SCIP_CALL( SCIPparseVarName(scip, s, &var, &endptr) );
1927  if ( var == NULL )
1928  {
1929  SCIPerrorMessage("unknown variable name at '%s'\n", str);
1930  *success = FALSE;
1931 
1932  SCIPfreeBufferArray(scip, &vars2);
1933  SCIPfreeBufferArray(scip, &vars1);
1934 
1935  return SCIP_OKAY;
1936  }
1937 
1938  if ( firstcolumn )
1939  vars1[nrows] = var;
1940  else
1941  vars2[nrows] = var;
1942  s = endptr;
1943  assert( s != NULL );
1944 
1945  firstcolumn = !firstcolumn;
1946 
1947  /* skip white space and ',' */
1948  while ( *s != '\0' && ( isspace((unsigned char)*s) || *s == ',' ) )
1949  ++s;
1950 
1951  /* begin new row if required */
1952  if ( *s == '.' )
1953  {
1954  ++nrows;
1955  ++s;
1956 
1957  if ( nrows >= maxnrows )
1958  {
1959  int newsize;
1960 
1961  newsize = SCIPcalcMemGrowSize(scip, nrows + 1);
1962  SCIP_CALL( SCIPreallocBufferArray(scip, &vars1, newsize) );
1963  SCIP_CALL( SCIPreallocBufferArray(scip, &vars2, newsize) );
1964  maxnrows = newsize;
1965  }
1966  assert( nrows < maxnrows );
1967  }
1968  }
1969  while ( *s != ')' );
1970  ++nrows;
1971 
1972  SCIP_CALL( SCIPcreateConsBasicOrbisack(scip, cons, name, vars1, vars2, nrows, ispporbisack, isparttype, TRUE) );
1973 
1974  SCIPfreeBufferArray(scip, &vars2);
1975  SCIPfreeBufferArray(scip, &vars1);
1976 
1977  return SCIP_OKAY;
1978 }
1979 
1980 
1981 /** constraint display method of constraint handler
1982  *
1983  * The constraint handler should output a representation of the constraint into the given text file.
1984  */
1985 static
1986 SCIP_DECL_CONSPRINT(consPrintOrbisack)
1987 { /*lint --e{715}*/
1988  SCIP_CONSDATA* consdata;
1989  SCIP_VAR** vars1;
1990  SCIP_VAR** vars2;
1991  int nrows;
1992  int i;
1993 
1994  assert( scip != NULL );
1995  assert( conshdlr != NULL );
1996  assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1997  assert( cons != NULL );
1998 
1999  consdata = SCIPconsGetData(cons);
2000  assert( consdata != NULL );
2001  assert( consdata->vars1 != NULL );
2002  assert( consdata->vars2 != NULL );
2003  assert( consdata->nrows > 0 );
2004 
2005  vars1 = consdata->vars1;
2006  vars2 = consdata->vars2;
2007  nrows = consdata->nrows;
2008 
2009  SCIPdebugMsg(scip, "Printing method for orbisack constraint handler\n");
2010 
2011  SCIPinfoMessage(scip, file, "fullOrbisack(");
2012 
2013  for (i = 0; i < nrows; ++i)
2014  {
2015  SCIP_CALL( SCIPwriteVarName(scip, file, vars1[i], TRUE) );
2016  SCIPinfoMessage(scip, file, ",");
2017  SCIP_CALL( SCIPwriteVarName(scip, file, vars2[i], TRUE) );
2018  if ( i < nrows-1 )
2019  SCIPinfoMessage(scip, file, ".");
2020  }
2021 
2022  SCIPinfoMessage(scip, file, ")");
2023 
2024  return SCIP_OKAY;
2025 }
2026 
2027 
2028 /** checks given solution for feasibility */
2030  SCIP* scip, /**< SCIP data structure */
2031  SCIP_SOL* sol, /**< solution to check for feasibility */
2032  SCIP_VAR** vars1, /**< variables of first column */
2033  SCIP_VAR** vars2, /**< variables of second column */
2034  int nrows, /**< number of rows */
2035  SCIP_Bool printreason, /**< whether reason for infeasibility should be printed */
2036  SCIP_Bool* feasible /**< memory address to store whether sol is feasible */
2037  )
2038 {
2039  int i;
2040  int val1;
2041  int val2;
2042 
2043  assert( scip != NULL );
2044  assert( vars1 != NULL );
2045  assert( vars2 != NULL );
2046  assert( nrows > 0 );
2047  assert( feasible != NULL );
2048 
2049  *feasible = TRUE;
2050 
2051  /* find first non-constant row and check for feasibility */
2052  for (i = 0; i < nrows; ++i)
2053  {
2054  assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars1[i])) );
2055  assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars2[i])) );
2056 
2057  /* get values of i-th row */
2058  val1 = SCIPgetSolVal(scip, sol, vars1[i]) > 0.5 ? 1 : 0;
2059  val2 = SCIPgetSolVal(scip, sol, vars2[i]) > 0.5 ? 1 : 0;
2060 
2061  /* if row i is constrant */
2062  if ( val1 == val2 )
2063  continue;
2064  /* row i has type (1,0) -> feasible */
2065  else if ( val1 == 1 )
2066  {
2067  assert( val2 == 0 );
2068  break;
2069  }
2070  else /* infeasible */
2071  {
2072  if ( printreason )
2073  SCIPinfoMessage(scip, NULL, "First non-constant row %d is fixed to (0,1).\n", i);
2074  *feasible = FALSE;
2075  break;
2076  }
2077  }
2078 
2079  return SCIP_OKAY;
2080 }
2081 
2082 
2083 /** constraint method of constraint handler which returns the variables (if possible) */
2084 static
2085 SCIP_DECL_CONSGETVARS(consGetVarsOrbisack)
2086 { /*lint --e{715}*/
2087  SCIP_CONSDATA* consdata;
2088 
2089  assert( cons != NULL );
2090  assert( success != NULL );
2091  assert( vars != NULL );
2092 
2093  consdata = SCIPconsGetData(cons);
2094  assert( consdata != NULL );
2095 
2096  if ( varssize < 2 * consdata->nrows )
2097  (*success) = FALSE;
2098  else
2099  {
2100  int cnt = 0;
2101  int i;
2102 
2103  for (i = 0; i < consdata->nrows; ++i)
2104  {
2105  vars[cnt++] = consdata->vars1[i];
2106  vars[cnt++] = consdata->vars2[i];
2107  }
2108  (*success) = TRUE;
2109  }
2110 
2111  return SCIP_OKAY;
2112 }
2113 
2114 
2115 /** constraint method of constraint handler which returns the number of variables (if possible) */
2116 static
2117 SCIP_DECL_CONSGETNVARS(consGetNVarsOrbisack)
2118 { /*lint --e{715}*/
2119  SCIP_CONSDATA* consdata;
2120 
2121  assert( cons != NULL );
2122 
2123  consdata = SCIPconsGetData(cons);
2124  assert( consdata != NULL );
2125 
2126  (*nvars) = 2 * consdata->nrows;
2127  (*success) = TRUE;
2128 
2129  return SCIP_OKAY;
2130 }
2131 
2132 
2133 /** creates the handler for orbisack constraints and includes it in SCIP */
2135  SCIP* scip /**< SCIP data structure */
2136  )
2137 {
2138  SCIP_CONSHDLRDATA* conshdlrdata = NULL;
2139  SCIP_CONSHDLR* conshdlr;
2140 
2141  SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
2142 
2143  /* include constraint handler */
2147  consEnfolpOrbisack, consEnfopsOrbisack, consCheckOrbisack, consLockOrbisack,
2148  conshdlrdata) );
2149  assert( conshdlr != NULL );
2150 
2151  /* set non-fundamental callbacks via specific setter functions */
2152  SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOrbisack, consCopyOrbisack) );
2153  SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOrbisack) );
2154  SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOrbisack) );
2155  SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrbisack) );
2156  SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOrbisack) );
2157  SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOrbisack) );
2158  SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOrbisack) );
2159  SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolOrbisack, CONSHDLR_MAXPREROUNDS, CONSHDLR_PRESOLTIMING) );
2160  SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOrbisack) );
2162  SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOrbisack) );
2163  SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOrbisack, consSepasolOrbisack, CONSHDLR_SEPAFREQ, CONSHDLR_SEPAPRIORITY, CONSHDLR_DELAYSEPA) );
2164  SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOrbisack) );
2165  SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpOrbisack) );
2166  SCIP_CALL( SCIPsetConshdlrInitsol(scip, conshdlr, consInitsolOrbisack) );
2167 
2168  /* separation methods */
2169  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/coverseparation",
2170  "Separate cover inequalities for orbisacks?",
2171  &conshdlrdata->coverseparation, TRUE, DEFAULT_COVERSEPARATION, NULL, NULL) );
2172 
2173  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/orbiSeparation",
2174  "Separate orbisack inequalities?",
2175  &conshdlrdata->orbiseparation, TRUE, DEFAULT_ORBISEPARATION, NULL, NULL) );
2176 
2177  SCIP_CALL( SCIPaddRealParam(scip, "constraints/" CONSHDLR_NAME "/coeffbound",
2178  "Maximum size of coefficients for orbisack inequalities",
2179  &conshdlrdata->coeffbound, TRUE, DEFAULT_COEFFBOUND, 0.0, DBL_MAX, NULL, NULL) );
2180 
2181  /* whether we allow upgrading to packing/partioning orbisack constraints*/
2182  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/checkpporbisack",
2183  "Upgrade orbisack constraints to packing/partioning orbisacks?",
2184  &conshdlrdata->checkpporbisack, TRUE, DEFAULT_PPORBISACK, NULL, NULL) );
2185 
2186  SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/forceconscopy",
2187  "Whether orbisack constraints should be forced to be copied to sub SCIPs.",
2188  &conshdlrdata->forceconscopy, TRUE, DEFAULT_FORCECONSCOPY, NULL, NULL) );
2189 
2190  return SCIP_OKAY;
2191 }
2192 
2193 
2194 /*
2195  * constraint specific interface methods
2196  */
2197 
2198 /** creates and captures a orbisack constraint
2199  *
2200  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2201  */
2203  SCIP* scip, /**< SCIP data structure */
2204  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2205  const char* name, /**< name of constraint */
2206  SCIP_VAR*const* vars1, /**< first column of matrix of variables on which the symmetry acts */
2207  SCIP_VAR*const* vars2, /**< second column of matrix of variables on which the symmetry acts */
2208  int nrows, /**< number of rows in variable matrix */
2209  SCIP_Bool ispporbisack, /**< whether the orbisack is a packing/partitioning orbisack */
2210  SCIP_Bool isparttype, /**< whether the orbisack is a partitioning orbisack */
2211  SCIP_Bool ismodelcons, /**< whether the orbisack is a model constraint */
2212  SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
2213  * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
2214  SCIP_Bool separate, /**< should the constraint be separated during LP processing?
2215  * Usually set to TRUE. */
2216  SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
2217  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2218  SCIP_Bool check, /**< should the constraint be checked for feasibility?
2219  * TRUE for model constraints, FALSE for additional, redundant constraints. */
2220  SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
2221  * Usually set to TRUE. */
2222  SCIP_Bool local, /**< is constraint only valid locally?
2223  * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
2224  SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
2225  * Usually set to FALSE. In column generation applications, set to TRUE if pricing
2226  * adds coefficients to this constraint. */
2227  SCIP_Bool dynamic, /**< is constraint subject to aging?
2228  * Usually set to FALSE. Set to TRUE for own cuts which
2229  * are separated as constraints. */
2230  SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
2231  * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
2232  SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
2233  * if it may be moved to a more global node?
2234  * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
2235  )
2236 {
2237  SCIP_CONSHDLR* conshdlr;
2238  SCIP_CONSHDLRDATA* conshdlrdata;
2239  SCIP_CONSDATA* consdata;
2240  SCIP_VAR*** vars;
2241  SCIP_Bool success;
2242  SCIP_ORBITOPETYPE orbitopetype;
2243  int i;
2244 
2245  /* find the orbisack constraint handler */
2246  conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
2247  if ( conshdlr == NULL )
2248  {
2249  SCIPerrorMessage("orbisack constraint handler not found\n");
2250  return SCIP_PLUGINNOTFOUND;
2251  }
2252 
2253  assert( nrows > 0 );
2254 
2255  /* check for upgrade to packing/partitioning orbisacks*/
2256  conshdlrdata = SCIPconshdlrGetData(conshdlr);
2257  if ( ! ispporbisack && conshdlrdata->checkpporbisack )
2258  {
2259  SCIP_CALL( packingUpgrade(scip, vars1, vars2, nrows, &success, &isparttype) );
2260 
2261  if ( success )
2262  ispporbisack = TRUE;
2263  }
2264 
2265  /* create constraint, if it is a packing/partitioning orbisack, add orbitope constraint
2266  * instead of orbitsack constraint */
2267  if ( ispporbisack )
2268  {
2269  SCIP_CALL( SCIPallocBufferArray(scip, &vars, nrows) );
2270  for (i = 0; i < nrows; ++i)
2271  {
2272  SCIP_CALL( SCIPallocBufferArray(scip, &vars[i], 2) ); /*lint !e866*/
2273  vars[i][0] = vars1[i];
2274  vars[i][1] = vars2[i];
2275  }
2276 
2277  if ( isparttype )
2278  orbitopetype = SCIP_ORBITOPETYPE_PARTITIONING;
2279  else
2280  orbitopetype = SCIP_ORBITOPETYPE_PACKING;
2281 
2282  SCIP_CALL( SCIPcreateConsOrbitope(scip, cons, "pporbisack", vars, orbitopetype, nrows,
2283  2, FALSE, TRUE, TRUE, ismodelcons, initial, separate, enforce, check, propagate, local,
2284  modifiable, dynamic, removable, stickingatnode) );
2285 
2286  for (i = 0; i < nrows; ++i)
2287  SCIPfreeBufferArray(scip, &vars[i]);
2288  SCIPfreeBufferArray(scip, &vars);
2289  }
2290  else
2291  {
2292  /* create constraint data */
2293  SCIP_CALL( consdataCreate(scip, &consdata, vars1, vars2, nrows, ismodelcons) );
2294 
2295  SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
2296  local, modifiable, dynamic, removable, stickingatnode) );
2297  }
2298 
2299  return SCIP_OKAY;
2300 }
2301 
2302 
2303 /** creates and captures an orbisack constraint in its most basic variant
2304  *
2305  * All constraint flags set to their default values, which can be set afterwards using SCIPsetConsFLAGNAME() in scip.h.
2306  *
2307  * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
2308  */
2310  SCIP* scip, /**< SCIP data structure */
2311  SCIP_CONS** cons, /**< pointer to hold the created constraint */
2312  const char* name, /**< name of constraint */
2313  SCIP_VAR** vars1, /**< first column of matrix of variables on which the symmetry acts */
2314  SCIP_VAR** vars2, /**< second column of matrix of variables on which the symmetry acts */
2315  int nrows, /**< number of rows in constraint matrix */
2316  SCIP_Bool ispporbisack, /**< whether the orbisack is a packing/partitioning orbisack */
2317  SCIP_Bool isparttype, /**< whether the orbisack is a partitioning orbisack */
2318  SCIP_Bool ismodelcons /**< whether the orbisack is a model constraint */
2319  )
2320 {
2321  SCIP_CALL( SCIPcreateConsOrbisack(scip, cons, name, vars1, vars2, nrows, ispporbisack, isparttype, ismodelcons,
2323 
2324  return SCIP_OKAY;
2325 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
SCIP_RETCODE SCIPcreateEmptyRowCons(SCIP *scip, SCIP_ROW **row, SCIP_CONS *cons, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1422
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:572
static SCIP_DECL_CONSENFOPS(consEnfopsOrbisack)
SCIP_RETCODE SCIPcreateConsOrbisack(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, int nrows, SCIP_Bool ispporbisack, SCIP_Bool isparttype, SCIP_Bool ismodelcons, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1635
enum SCIP_OrbitopeType SCIP_ORBITOPETYPE
public methods for SCIP parameter handling
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8353
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:595
public methods for memory management
static SCIP_RETCODE packingUpgrade(SCIP *scip, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, int nrows, SCIP_Bool *success, SCIP_Bool *isparttype)
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:886
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1658
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETVARS((*consgetvars)))
Definition: scip_cons.c:825
static SCIP_DECL_CONSRESPROP(consRespropOrbisack)
public methods for conflict handler plugins and conflict analysis
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSENFORELAX((*consenforelax)))
Definition: scip_cons.c:317
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition: scip_mem.c:139
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition: scip_lp.c:1695
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17975
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPincludeConshdlrOrbisack(SCIP *scip)
#define UNFIXED
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:1445
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition: scip_var.c:533
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17440
#define DEFAULT_COEFFBOUND
static SCIP_DECL_CONSGETVARS(consGetVarsOrbisack)
#define FALSE
Definition: def.h:96
static SCIP_DECL_CONSSEPALP(consSepalpOrbisack)
SCIP_RETCODE SCIPincludeConshdlrBasic(SCIP *scip, SCIP_CONSHDLR **conshdlrptr, const char *name, const char *desc, int enfopriority, int chckpriority, int eagerfreq, SCIP_Bool needscons, SCIP_DECL_CONSENFOLP((*consenfolp)), SCIP_DECL_CONSENFOPS((*consenfops)), SCIP_DECL_CONSCHECK((*conscheck)), SCIP_DECL_CONSLOCK((*conslock)), SCIP_CONSHDLRDATA *conshdlrdata)
Definition: scip_cons.c:175
constraint handler for orbisack constraints
SCIP_Real SCIPinfinity(SCIP *scip)
static SCIP_RETCODE addOrbisackCover(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *coeffs1, SCIP_Real *coeffs2, SCIP_Real rhs, SCIP_Bool *infeasible)
#define TRUE
Definition: def.h:95
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
static SCIP_DECL_CONSINITSOL(consInitsolOrbisack)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
#define CONSHDLR_NEEDSCONS
Definition: cons_orbisack.c:91
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8373
public methods for problem variables
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
SCIP_RETCODE SCIPsetConshdlrSepa(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSSEPALP((*conssepalp)), SCIP_DECL_CONSSEPASOL((*conssepasol)), int sepafreq, int sepapriority, SCIP_Bool delaysepa)
Definition: scip_cons.c:229
static SCIP_RETCODE separateOrbisack(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *vals1, SCIP_Real *vals2, SCIP_Bool coverseparation, SCIP_Real coeffbound, int *ngen, SCIP_Bool *infeasible)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
Constraint handler for the set partitioning / packing / covering constraints .
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip_general.c:575
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:428
public methods for SCIP variables
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8363
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:618
#define SCIPdebugMsg
Definition: scip_message.h:78
#define DEFAULT_ORBISEPARATION
Definition: cons_orbisack.c:97
static SCIP_RETCODE initLP(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible)
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPARSE((*consparse)))
Definition: scip_cons.c:802
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
SCIP_RETCODE SCIPcreateCons(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_CONSHDLR *conshdlr, SCIP_CONSDATA *consdata, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
Definition: scip_cons.c:943
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
static SCIP_DECL_CONSTRANS(consTransOrbisack)
public methods for numerical tolerances
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:4265
static SCIP_RETCODE addOrbisackInequality(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *coeffs1, SCIP_Real *coeffs2, SCIP_Real rhs, SCIP_Bool *infeasible)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
constraint handler for (partitioning/packing/full) orbitope constraints w.r.t. the full symmetric gro...
SCIP_RETCODE SCIPsetConshdlrInitsol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITSOL((*consinitsol)))
Definition: scip_cons.c:438
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition: scip_mem.h:105
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbisack)
public methods for managing constraints
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:341
#define CONSHDLR_DELAYPROP
Definition: cons_orbisack.c:90
static SCIP_DECL_CONSPRINT(consPrintOrbisack)
#define DEFAULT_FORCECONSCOPY
static SCIP_DECL_CONSCHECK(consCheckOrbisack)
#define SCIPerrorMessage
Definition: pub_message.h:64
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4184
#define CONSHDLR_DESC
Definition: cons_orbisack.c:79
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip_sol.c:1398
#define CONSHDLR_SEPAFREQ
Definition: cons_orbisack.c:83
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip_cut.c:135
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16670
SCIP_RETCODE SCIPisPackingPartitioningOrbitope(SCIP *scip, SCIP_VAR ***vars, int nrows, int ncols, SCIP_Bool **pprows, int *npprows, SCIP_ORBITOPETYPE *type)
Definition: symmetry.c:1161
static SCIP_DECL_CONSCOPY(consCopyOrbisack)
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8094
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition: scip_var.c:8721
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition: cons.c:8313
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSFREE((*consfree)))
Definition: scip_cons.c:366
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4204
#define NULL
Definition: lpi_spx1.cpp:164
#define CONSHDLR_PROP_TIMING
Definition: cons_orbisack.c:93
static SCIP_DECL_CONSPROP(consPropOrbisack)
#define CONSHDLR_CHECKPRIORITY
Definition: cons_orbisack.c:82
#define SCIP_CALL(x)
Definition: def.h:393
#define FIXED0
#define DEFAULT_PPORBISACK
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8333
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:250
static SCIP_RETCODE propVariables(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, SCIP_Bool *found, int *ngen)
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:641
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
#define CONSHDLR_SEPAPRIORITY
Definition: cons_orbisack.c:80
public methods for constraint handler plugins and constraints
static SCIP_DECL_CONSGETNVARS(consGetNVarsOrbisack)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIP_Bool
Definition: def.h:93
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16551
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
SCIP_CONSHDLR * SCIPconsGetHdlr(SCIP_CONS *cons)
Definition: cons.c:8114
public methods for cuts and aggregation rows
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8293
#define CONSHDLR_ENFOPRIORITY
Definition: cons_orbisack.c:81
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8263
#define CONSHDLR_NAME
Definition: cons_orbisack.c:78
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:779
SCIP_RETCODE SCIPinferVarLbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5507
static SCIP_DECL_CONSDELETE(consDeleteOrbisack)
static SCIP_RETCODE separateInequalities(SCIP *scip, SCIP_RESULT *result, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *vals1, SCIP_Real *vals2)
public methods for the LP relaxation, rows and columns
static SCIP_RETCODE separateOrbisackCovers(SCIP *scip, SCIP_CONS *cons, int nrows, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, SCIP_Real *vals1, SCIP_Real *vals2, int *ngen, SCIP_Bool *infeasible)
static SCIP_DECL_CONSENFOLP(consEnfolpOrbisack)
public methods for branching rule plugins and branching
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition: scip_lp.c:1562
general public methods
static SCIP_DECL_CONSSEPASOL(consSepasolOrbisack)
public methods for solutions
SCIP_RETCODE SCIPgetVarCopy(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR *sourcevar, SCIP_VAR **targetvar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, SCIP_Bool *success)
Definition: scip_copy.c:711
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8124
SCIP_RETCODE SCIPinferVarUbCons(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound, SCIP_CONS *infercons, int inferinfo, SCIP_Bool force, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition: scip_var.c:5621
methods for handling symmetries
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition: scip_cons.c:534
public methods for message output
SCIP_RETCODE SCIPcreateConsBasicOrbisack(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR **vars1, SCIP_VAR **vars2, int nrows, SCIP_Bool ispporbisack, SCIP_Bool isparttype, SCIP_Bool ismodelcons)
#define SCIP_Real
Definition: def.h:186
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8343
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSGETNVARS((*consgetnvars)))
Definition: scip_cons.c:848
public methods for message handling
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8283
#define CONSHDLR_MAXPREROUNDS
Definition: cons_orbisack.c:88
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8273
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition: scip_lp.c:2206
#define CONSHDLR_PRESOLTIMING
Definition: cons_orbisack.c:94
static SCIP_DECL_CONSPRESOL(consPresolOrbisack)
static SCIP_DECL_CONSLOCK(consLockOrbisack)
#define FIXED1
SCIP_RETCODE SCIPcreateConsOrbitope(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, SCIP_ORBITOPETYPE orbitopetype, int nspcons, int nblocks, SCIP_Bool usedynamicprop, SCIP_Bool mayinteract, SCIP_Bool resolveprop, SCIP_Bool ismodelcons, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition: type_cons.h:64
static SCIP_DECL_CONSFREE(consFreeOrbisack)
#define CONSHDLR_DELAYSEPA
Definition: cons_orbisack.c:89
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17985
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip_mem.h:111
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
static SCIP_RETCODE checkFeasible(SCIP *scip, SCIP_VAR **vars1, SCIP_VAR **vars2, int nrows, int start, SCIP_Bool *infeasible, int *infeasiblerow)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR *const *vars1, SCIP_VAR *const *vars2, int nrows, SCIP_Bool ismodelcons)
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition: scip_var.c:230
#define CONSHDLR_PROPFREQ
Definition: cons_orbisack.c:84
static SCIP_DECL_CONSPARSE(consParseOrbisack)
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1361
static SCIP_DECL_CONSENFORELAX(consEnforelaxOrbisack)
#define CONSHDLR_EAGERFREQ
Definition: cons_orbisack.c:85
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:139
SCIP_RETCODE SCIPcheckSolutionOrbisack(SCIP *scip, SCIP_SOL *sol, SCIP_VAR **vars1, SCIP_VAR **vars2, int nrows, SCIP_Bool printreason, SCIP_Bool *feasible)
SCIP callable library.
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip_param.c:57
#define DEFAULT_COVERSEPARATION
Definition: cons_orbisack.c:98
static SCIP_DECL_CONSINITLP(consInitlpOrbisack)
#define SCIPreallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:128
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition: scip_cons.c:275
memory allocation routines