SCIP Doxygen Documentation
Loading...
Searching...
No Matches
cons_orbitope_full.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
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_orbitope_full.c
26 * @ingroup DEFPLUGINS_CONS
27 * @brief constraint handler for full orbitope constraints w.r.t. the full symmetric group
28 * @author Timo Berthold
29 * @author Marc Pfetsch
30 * @author Christopher Hojny
31 *
32 * The type of constraints of this constraint handler is described in cons_orbitope_full.h.
33 * When creating the constraint, users can decide whether it is a constraint defining the model
34 * or "just" use to handle symmetries. In the latter case, symmetry reductions are only performed
35 * by the constraint handler if strong dual reductions are permitted.
36 *
37 * The details of the method implemented here are described in the following papers.
38 *
39 * Orbitopal fixing for the full (sub-)orbitope and application to the Unit Commitment Problem@n
40 * Pascale Bendotti, Pierre Fouilhoux, and Cecile Rottner,@n
41 * Optimization Online: http://www.optimization-online.org/DB_HTML/2017/10/6301.html
42 *
43 * Two linear time propagation algorithms for full orbitopes are described in this paper, a static
44 * version and a dynamic one. While the static version uses a fixed variable order, the dynamic
45 * version determines the variable order during the solving process via branching descisions.
46 * We only implemented the static version, because constraints should define the model and should
47 * not be changed during the solving process. Instead, a dynamic version of orbitopal fixing has
48 * been implemented as a routine in prop_symmetry.c.
49 *
50 * Polytopes associated with symmetry handling@n
51 * Christopher Hojny and Marc E. Pfetsch,@n
52 * Math. Program. (2018)
53 *
54 * In this paper, a linear time separation algorithm for orbisacks (full orbitopes with two columnes)
55 * is described. We use this algorithm for every pair of adjacent columns within the orbitope.
56 */
57
58/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
59
61#include "scip/cons_orbisack.h"
63#include "scip/cons_setppc.h"
64#include "scip/pub_cons.h"
65#include "scip/pub_message.h"
66#include "scip/pub_var.h"
67#include "scip/scip.h"
68#include "scip/scip_branch.h"
69#include "scip/scip_conflict.h"
70#include "scip/scip_cons.h"
71#include "scip/scip_copy.h"
72#include "scip/scip_cut.h"
73#include "scip/scip_general.h"
74#include "scip/scip_lp.h"
75#include "scip/scip_mem.h"
76#include "scip/scip_message.h"
77#include "scip/scip_numerics.h"
78#include "scip/scip_param.h"
79#include "scip/scip_prob.h"
80#include "scip/scip_probing.h"
81#include "scip/scip_sol.h"
82#include "scip/scip_var.h"
83#include "scip/symmetry.h"
85
86/* constraint handler properties */
87#define CONSHDLR_NAME "orbitope_full"
88#define CONSHDLR_DESC "symmetry breaking constraint handler relying on full orbitopes"
89#define CONSHDLR_SEPAPRIORITY +40100 /**< priority of the constraint handler for separation */
90#define CONSHDLR_ENFOPRIORITY -1005200 /**< priority of the constraint handler for constraint enforcing */
91#define CONSHDLR_CHECKPRIORITY -1005200 /**< priority of the constraint handler for checking feasibility */
92#define CONSHDLR_SEPAFREQ -1 /**< frequency for separating cuts; zero means to separate only in the root node */
93#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
94#define CONSHDLR_EAGERFREQ -1 /**< frequency for using all instead of only the useful constraints in separation,
95 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
96#define CONSHDLR_MAXPREROUNDS -1 /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */
97#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
98#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
99#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
100
101#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP /**< propagation timing mask of the constraint handler */
102#define CONSHDLR_PRESOLTIMING SCIP_PRESOLTIMING_MEDIUM /**< presolving timing of the constraint handler (fast, medium, or exhaustive) */
103
104#define DEFAULT_FORCECONSCOPY FALSE /**< whether orbitope constraints should be forced to be copied to sub SCIPs */
105
106/*
107 * Data structures
108 */
109
110/** constraint handler data */
111struct SCIP_ConshdlrData
112{
113 SCIP_Bool forceconscopy; /**< whether orbitope constraints should be forced to be copied to sub SCIPs */
114};
115
116/** constraint data for orbitope constraints */
117struct SCIP_ConsData
118{
119 SCIP_VAR*** vars; /**< matrix of variables on which the symmetry acts */
120 int nrows; /**< number of rows */
121 int ncols; /**< number of columns*/
122 SCIP_Bool resolveprop; /**< should propagation be resolved? */
123 SCIP_Bool ismodelcons; /**< whether the orbitope is a model constraint */
124};
125
126
127/*
128 * Local methods
129 */
130
131/** frees an orbitope constraint data */
132static
134 SCIP* scip, /**< SCIP data structure */
135 SCIP_CONSDATA** consdata /**< pointer to orbitope constraint data */
136 )
137{
138 int i;
139 int j;
140 int nrows;
141 int ncols;
142
143 assert( consdata != NULL );
144 assert( *consdata != NULL );
145
146 nrows = (*consdata)->nrows;
147 ncols = (*consdata)->ncols;
148 for (i = 0; i < nrows; ++i)
149 {
150 /* release variables in vars array */
151 for (j = 0; j < ncols; ++j)
152 {
153 assert( (*consdata)->vars[i] != NULL );
154 SCIP_CALL( SCIPreleaseVar(scip, &(*consdata)->vars[i][j]) );
155 }
156
157 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars[i]), ncols); /*lint !e866*/
158 }
159
160 SCIPfreeBlockMemoryArrayNull(scip, &((*consdata)->vars), nrows);
161
162 SCIPfreeBlockMemory(scip, consdata);
163
164 return SCIP_OKAY;
165}
166
167
168/** creates orbitope constraint data */
169static
171 SCIP* scip, /**< SCIP data structure */
172 SCIP_CONSDATA** consdata, /**< pointer to store constraint data */
173 SCIP_VAR*** vars, /**< variables array, must have size nrows x ncols*/
174 int nrows, /**< number of rows */
175 int ncols, /**< number of columns */
176 SCIP_Bool resolveprop, /**< should propagation be resolved? */
177 SCIP_Bool ismodelcons /**< whether the orbitope is a model constraint */
178 )
179{
180 int i;
181 int j;
182
183 assert(consdata != NULL);
184
185 SCIP_CALL( SCIPallocBlockMemory(scip, consdata) );
186
187 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*consdata)->vars, nrows) );
188
189 for (i = 0; i < nrows; ++i)
190 {
191 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*consdata)->vars[i], vars[i], ncols) ); /*lint !e866*/
192 }
193
194 (*consdata)->nrows = nrows;
195 (*consdata)->ncols = ncols;
196 (*consdata)->resolveprop = resolveprop;
197 (*consdata)->ismodelcons = ismodelcons;
198
199 /* get transformed variables, if we are in the transformed problem */
200 if ( SCIPisTransformed(scip) )
201 {
202 for (i = 0; i < nrows; ++i)
203 {
204 /* make sure that no variable gets multiaggregated (cannot be handled by cons_orbitope, since one cannot easily
205 * eliminate single variables from an orbitope constraint).
206 */
207 for (j = 0; j < ncols; ++j)
208 {
209 SCIP_CALL( SCIPgetTransformedVar(scip, (*consdata)->vars[i][j], &(*consdata)->vars[i][j]) );
210 SCIP_CALL( SCIPmarkDoNotMultaggrVar(scip, (*consdata)->vars[i][j]) );
211 }
212 }
213 }
214
215 /* capture vars contained in vars array */
216 for (i = 0; i < nrows; ++i)
217 {
218 for (j = 0; j < ncols; ++j)
219 {
220 assert( (*consdata)->vars[i][j] != NULL );
221 SCIP_CALL( SCIPcaptureVar(scip, (*consdata)->vars[i][j]) );
222 }
223 }
224
225 return SCIP_OKAY;
226}
227
228
229/** Compute lexicographically minimal face of the hypercube w.r.t. some coordinate fixing */
230static
232 SCIP_VAR*** vars, /**< variable matrix */
233 int** lexminfixes, /**< fixings characterzing lex-min face */
234 int* minfixedrowlexmin, /**< index of minimum fixed row for each column or NULL (if in prop) */
235 SCIP_Bool* infeasible, /**< pointer to store whether infeasibility has been detected or NULL (if in resprop) */
236 int nrows, /**< number of rows in vars */
237 int ncols, /**< number of columns in vars */
238 SCIP_Bool resprop /**< whether we are in resprop (TRUE) or prop (FALSE) */
239 )
240{
241 int i;
242 int j;
243
244 *infeasible = FALSE;
245
246 assert( vars != NULL );
247 assert( lexminfixes != NULL );
248 assert( !resprop || minfixedrowlexmin != NULL );
249 assert( nrows > 0 );
250 assert( ncols > 0 );
251 assert( infeasible != NULL );
252
253 /* iterate over columns in reverse order and find the lexicographically minimal face
254 * of the hypercube containing lexminfixes
255 */
256 for (j = ncols - 2; j >= 0; --j)
257 {
258 int maxdiscriminating;
259 int minfixed = -1;
260
261 maxdiscriminating = nrows;
262
263 /* fix free entries in column j to the corresponding value in column j + 1 and collect some information */
264 for (i = 0; i < nrows; ++i)
265 {
266 /* is row i j-discriminating? */
267 if ( minfixed == -1 && lexminfixes[i][j] != 0 && lexminfixes[i][j + 1] != 1 )
268 {
269 assert( lexminfixes[i][j + 1] == 0 );
270
271 maxdiscriminating = i;
272 }
273
274 /* is row i j-fixed? */
275 if ( minfixed == -1 && lexminfixes[i][j] != lexminfixes[i][j + 1] && lexminfixes[i][j] != 2 )
276 {
277 assert( lexminfixes[i][j + 1] != 2 );
278
279 minfixed = i;
280
281 /* detect infeasibility */
282 if ( maxdiscriminating > minfixed )
283 {
284 *infeasible = TRUE;
285
286 return SCIP_OKAY;
287 }
288 }
289 }
290
291 /* ensure that column j is lexicographically not smaller than column j + 1 */
292 for (i = 0; i < nrows; ++i)
293 {
294 if ( lexminfixes[i][j] == 2 )
295 {
296 if ( i < maxdiscriminating || minfixed == -1 )
297 lexminfixes[i][j] = lexminfixes[i][j + 1];
298 else if ( i == maxdiscriminating )
299 lexminfixes[i][j] = 1;
300 else
301 lexminfixes[i][j] = 0;
302 }
303 }
304
305 if ( resprop )
306 {
307 assert( minfixedrowlexmin != NULL );
308
309 /* store minimum fixed row */
310 if ( minfixed == -1 )
311 minfixedrowlexmin[j] = nrows - 1;
312 else
313 minfixedrowlexmin[j] = minfixed;
314
315 /* columns 1, ..., n-2 are contained in two columns (take the minimum) and
316 * the minimum fixed row of column n-1 is determined by column n-2 */
317 if ( minfixedrowlexmin[j + 1] < minfixedrowlexmin[j] )
318 minfixedrowlexmin[j + 1] = minfixedrowlexmin[j];
319 }
320 }
321
322 return SCIP_OKAY;
323}
324
325
326/** Compute lexicographically maximal face of the hypercube w.r.t. some coordinate fixing */
327static
329 SCIP_VAR*** vars, /**< variable matrix */
330 int** lexmaxfixes, /**< fixings characterzing lex-max face */
331 int* minfixedrowlexmax, /**< index of minimum fixed row for each column or NULL (if in prop) */
332 SCIP_Bool* infeasible, /**< pointer to store whether infeasibility has been detected or NULL (if in resprop) */
333 int nrows, /**< number of rows in vars */
334 int ncols, /**< number of columns in vars */
335 SCIP_Bool resprop /**< whether we are in resprop (TRUE) or prop (FALSE) */
336 )
337{
338 int i;
339 int j;
340
341 *infeasible = FALSE;
342
343 assert( vars != NULL );
344 assert( lexmaxfixes != NULL );
345 assert( !resprop || minfixedrowlexmax != NULL );
346 assert( nrows > 0 );
347 assert( ncols > 0 );
348 assert( infeasible != NULL );
349
350 for (j = 1; j < ncols; ++j)
351 {
352 int maxdiscriminating;
353 int minfixed = -1;
354
355 maxdiscriminating = nrows;
356
357 /* fix free entries in column j to the corresponding value in column j - 1 and collect some information */
358 for (i = 0; i < nrows; ++i)
359 {
360 /* is row i j-discriminating? */
361 if ( minfixed == -1 && lexmaxfixes[i][j - 1] != 0 && lexmaxfixes[i][j] != 1 )
362 {
363 assert( lexmaxfixes[i][j - 1] == 1 );
364
365 maxdiscriminating = i;
366 }
367
368 /* is row i j-fixed? */
369 if ( minfixed == -1 && lexmaxfixes[i][j - 1] != lexmaxfixes[i][j] && lexmaxfixes[i][j] != 2 )
370 {
371 assert( lexmaxfixes[i][j - 1] != 2 );
372
373 minfixed = i;
374
375 /* detect infeasibility */
376 if ( maxdiscriminating > minfixed )
377 {
378 *infeasible = TRUE;
379
380 return SCIP_OKAY;
381 }
382 }
383 }
384
385 /* ensure that column j is lexicographically not greater than column j - 1 */
386 for (i = 0; i < nrows; ++i)
387 {
388 if ( lexmaxfixes[i][j] == 2 )
389 {
390 if ( i < maxdiscriminating || minfixed == -1 )
391 lexmaxfixes[i][j] = lexmaxfixes[i][j - 1];
392 else if ( i == maxdiscriminating )
393 lexmaxfixes[i][j] = 0;
394 else
395 lexmaxfixes[i][j] = 1;
396 }
397 }
398
399 if ( resprop )
400 {
401 assert( minfixedrowlexmax != NULL );
402
403 /* store minimum fixed row */
404 if ( minfixed == -1 )
405 minfixedrowlexmax[j] = nrows - 1;
406 else
407 minfixedrowlexmax[j] = minfixed;
408
409 /* columns 1, ..., n-2 are contained in two columns (take the minimum) and
410 * the minimum fixed row of column 0 is determined by column 1 */
411 if ( minfixedrowlexmax[j - 1] < minfixedrowlexmax[j] )
412 minfixedrowlexmax[j - 1] = minfixedrowlexmax[j];
413 }
414 }
415
416 return SCIP_OKAY;
417}
418
419
420/** propagation method for a single full orbitope constraint */
421static
423 SCIP* scip, /**< SCIP data structure */
424 SCIP_CONS* cons, /**< constraint to be processed */
425 SCIP_Bool* infeasible, /**< pointer to store TRUE, if the node can be cut off */
426 int* nfixedvars /**< pointer to add up the number of found domain reductions */
427 )
428{
429 SCIP_CONSDATA* consdata;
430 SCIP_VAR*** vars;
431 int** lexminfixes;
432 int** lexmaxfixes;
433 int i;
434 int j;
435 int nrows;
436 int ncols;
437
438 assert( scip != NULL );
439 assert( cons != NULL );
440 assert( infeasible != NULL );
441 assert( nfixedvars != NULL );
442
443 consdata = SCIPconsGetData(cons);
444 assert( consdata != NULL );
445
446 *nfixedvars = 0;
447 *infeasible = FALSE;
448
449 /* if the constraint is not a model constraint, check whether symmetry reductions are permitted */
450 if ( !consdata->ismodelcons && !SCIPallowStrongDualReds(scip) )
451 return SCIP_OKAY;
452
453 assert( consdata->nrows > 0 );
454 assert( consdata->ncols > 0 );
455 assert( consdata->vars != NULL );
456
457 nrows = consdata->nrows;
458 ncols = consdata->ncols;
459 vars = consdata->vars;
460
461 /* Initialize lexicographically minimal matrix by fixed entries at the current node.
462 * Free entries in the last column are set to 0.
463 */
464 SCIP_CALL( SCIPallocBufferArray(scip, &lexminfixes, nrows) );
465 for (i = 0; i < nrows; ++i)
466 {
467 SCIP_CALL( SCIPallocBufferArray(scip, &lexminfixes[i], ncols) ); /*lint !e866*/
468 }
469
470 for (i = 0; i < nrows; ++i)
471 {
472 for (j = 0; j < ncols; ++j)
473 {
474 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
475 lexminfixes[i][j] = 1;
476 else if ( SCIPvarGetUbLocal(vars[i][j]) < 0.5 || j == ncols - 1 )
477 lexminfixes[i][j] = 0;
478 else
479 lexminfixes[i][j] = 2;
480 }
481 }
482
483 /* find lexicographically minimal face of hypercube containing lexmin fixes */
484 SCIP_CALL( findLexMinFace(vars, lexminfixes, NULL, infeasible, nrows, ncols, FALSE) );
485
486 if ( *infeasible == TRUE )
487 goto FREELEXMIN;
488
489 /* Initialize lexicographically maximal matrix by fixed entries at the current node.
490 * Free entries in the first column are set to 1.
491 */
492 SCIP_CALL( SCIPallocBufferArray(scip, &lexmaxfixes, nrows) );
493 for (i = 0; i < nrows; ++i)
494 {
495 SCIP_CALL( SCIPallocBufferArray(scip, &lexmaxfixes[i], ncols) ); /*lint !e866*/
496 }
497
498 for (i = 0; i < nrows; ++i)
499 {
500 for (j = 0; j < ncols; ++j)
501 {
502 if ( SCIPvarGetUbLocal(vars[i][j]) < 0.5 )
503 lexmaxfixes[i][j] = 0;
504 else if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 || j == 0 )
505 lexmaxfixes[i][j] = 1;
506 else
507 lexmaxfixes[i][j] = 2;
508 }
509 }
510
511 /* find lexicographically maximal face of hypercube containing lexmax fixes */
512 SCIP_CALL( findLexMaxFace(vars, lexmaxfixes, NULL, infeasible, nrows, ncols, FALSE) );
513
514 if ( *infeasible )
515 goto FREELEXMAX;
516
517 /* Find for each column j the minimal row in which lexminfixes and lexmaxfixes differ. Fix all entries above this
518 * row to the corresponding value in lexminfixes (or lexmaxfixes).
519 */
520 for (j = 0; j < ncols; ++j)
521 {
522 for (i = 0; i < nrows; ++i)
523 {
524 if ( lexminfixes[i][j] != lexmaxfixes[i][j] )
525 break;
526
527 if ( SCIPvarGetLbLocal(vars[i][j]) < 0.5 && SCIPvarGetUbLocal(vars[i][j]) > 0.5 )
528 {
529 SCIP_Bool success;
530
531 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i][j], (SCIP_Bool) lexminfixes[i][j],
532 cons, 0, infeasible, &success) );
533
534 if ( success )
535 *nfixedvars += 1;
536 }
537 }
538 }
539
540 FREELEXMAX:
541 for (i = nrows - 1; i >= 0; --i)
542 SCIPfreeBufferArray(scip, &lexmaxfixes[i]);
543 SCIPfreeBufferArray(scip, &lexmaxfixes);
544
545 FREELEXMIN:
546 for (i = nrows - 1; i >= 0; --i)
547 SCIPfreeBufferArray(scip, &lexminfixes[i]);
548 SCIPfreeBufferArray(scip, &lexminfixes);
549
550 return SCIP_OKAY;
551}
552
553
554/** Propagation conflict resolving method of propagator
555 *
556 * In this function we use that all variable reductions that can be found by the propagation algorithm
557 * are only due to the fixed variables that are in or above the minimum fixed row of each pair of adjacent
558 * columns of the lexmin and lexmax matrices.
559 *
560 * Since the storage of an integer is not enough to store the complete information about the fixing,
561 * we have to use the linear time algorithm for finding the lexmin and lexmax
562 * matrices and determine from this the minimum fixed rows.
563 */
564static
566 SCIP* scip, /**< SCIP data structure */
567 SCIP_CONSHDLR* conshdlr, /**< constraint handler of the corresponding constraint */
568 SCIP_CONS* cons, /**< constraint that inferred the bound change */
569 int inferinfo, /**< inference information */
570 SCIP_BDCHGIDX* bdchgidx, /**< bound change index (time stamp of bound change), or NULL for current time */
571 SCIP_RESULT* result /**< pointer to store the result of the propagation conflict resolving call */
572 )
573{ /*lint --e{715}*/
574 SCIP_CONSDATA* consdata;
575 SCIP_VAR*** vars;
576 int** lexminfixes;
577 int** lexmaxfixes;
578 int* minfixedrowlexmin;
579 int* minfixedrowlexmax;
580 int i;
581 int j;
582 int nrows;
583 int ncols;
584 SCIP_Bool terminate;
585
587
588 assert( scip != NULL );
589 assert( conshdlr != NULL );
590 assert( cons != NULL );
591 assert( result != NULL );
592
593 consdata = SCIPconsGetData(cons);
594 assert( consdata != NULL );
595 assert( consdata->nrows > 0 );
596 assert( consdata->ncols > 0 );
597 assert( consdata->vars != NULL );
598
599 nrows = consdata->nrows;
600 ncols = consdata->ncols;
601 vars = consdata->vars;
602
603 assert( inferinfo <= consdata->nrows );
604
605 /* Initialize lexicographically minimal matrix by fixed entries at the current node.
606 * Free entries in the last column are set to 0.
607 */
608 SCIP_CALL( SCIPallocBufferArray(scip, &lexminfixes, nrows) );
609 for (i = 0; i < nrows; ++i)
610 {
611 SCIP_CALL( SCIPallocBufferArray(scip, &lexminfixes[i], ncols) ); /*lint !e866*/
612 }
613
614 /* store minimum fixed row for each column */
615 SCIP_CALL( SCIPallocBufferArray(scip, &minfixedrowlexmin, ncols) );
616 minfixedrowlexmin[ncols - 1] = -1;
617
618 for (i = 0; i < nrows; ++i)
619 {
620 for (j = 0; j < ncols; ++j)
621 {
622 if ( SCIPgetVarLbAtIndex(scip, vars[i][j], bdchgidx, FALSE) > 0.5 )
623 lexminfixes[i][j] = 1;
624 else if ( SCIPgetVarUbAtIndex(scip, vars[i][j], bdchgidx, FALSE) < 0.5 || j == ncols - 1 )
625 lexminfixes[i][j] = 0;
626 else
627 lexminfixes[i][j] = 2;
628 }
629 }
630
631 /* find lexicographically minimal face of hypercube containing lexmin fixes */
632 SCIP_CALL( findLexMinFace(vars, lexminfixes, minfixedrowlexmin, &terminate, nrows, ncols, TRUE) );
633
634 if ( terminate )
635 goto FREELEXMIN;
636
637 /* Initialize lexicographically maximal matrix by fixed entries at the current node.
638 * Free entries in the first column are set to 1.
639 */
640 SCIP_CALL( SCIPallocBufferArray(scip, &lexmaxfixes, nrows) );
641 for (i = 0; i < nrows; ++i)
642 {
643 SCIP_CALL( SCIPallocBufferArray(scip, &lexmaxfixes[i], ncols) ); /*lint !e866*/
644 }
645
646 /* store minimum fixed row for each column */
647 SCIP_CALL( SCIPallocBufferArray(scip, &minfixedrowlexmax, ncols) );
648 minfixedrowlexmax[0] = -1;
649
650 for (i = 0; i < nrows; ++i)
651 {
652 for (j = 0; j < ncols; ++j)
653 {
654 if ( SCIPgetVarUbAtIndex(scip, vars[i][j], bdchgidx, FALSE) < 0.5 )
655 lexmaxfixes[i][j] = 0;
656 else if ( SCIPgetVarLbAtIndex(scip, vars[i][j], bdchgidx, FALSE) > 0.5 || j == 0 )
657 lexmaxfixes[i][j] = 1;
658 else
659 lexmaxfixes[i][j] = 2;
660 }
661 }
662
663 /* find lexicographically maximal face of hypercube containing lexmax fixes */
664 SCIP_CALL( findLexMaxFace(vars, lexmaxfixes, minfixedrowlexmax, &terminate, nrows, ncols, TRUE) );
665
666 if ( terminate )
667 goto FREELEXMAX;
668
669 /* Find for each column j the minimal row in which lexminfixes and lexmaxfixes differ. Fix all entries above this
670 * row to the corresponding value in lexminfixes (or lexmaxfixes).
671 */
672 for (j = 0; j < ncols; ++j)
673 {
674 int ub = MAX(minfixedrowlexmin[j], minfixedrowlexmax[j]);
675
676 for (i = 0; i <= ub; ++i)
677 {
678 if ( SCIPgetVarLbAtIndex(scip, vars[i][j], bdchgidx, FALSE) > 0.5 ||
679 SCIPgetVarUbAtIndex(scip, vars[i][j], bdchgidx, FALSE) < 0.5 )
680 {
683 }
684 }
685 }
686
687 FREELEXMAX:
688 SCIPfreeBufferArray(scip, &minfixedrowlexmax);
689 for (i = nrows - 1; i >= 0; --i)
690 SCIPfreeBufferArray(scip, &lexmaxfixes[i]);
691 SCIPfreeBufferArray(scip, &lexmaxfixes);
692
693 FREELEXMIN:
694 SCIPfreeBufferArray(scip, &minfixedrowlexmin);
695 for (i = nrows - 1; i >= 0; --i)
696 SCIPfreeBufferArray(scip, &lexminfixes[i]);
697 SCIPfreeBufferArray(scip, &lexminfixes);
698
699 return SCIP_OKAY;
700}
701
702
703/** check full orbitope solution for feasibility */
704static
706 SCIP* scip, /**< SCIP data structure */
707 SCIP_CONS* cons, /**< constraint to process */
708 SCIP_SOL* sol, /**< solution to be checked */
709 SCIP_Bool printreason, /**< whether reason for infeasibility should be printed */
710 SCIP_Bool* feasible /**< memory address to store whether solution is feasible */
711 )
712{
713 SCIP_CONSDATA* consdata;
714 SCIP_VAR*** vars;
715 SCIP_VAR** vars1;
716 SCIP_VAR** vars2;
717 int nrows;
718 int ncols;
719 int j;
720 int i;
721
722 assert( scip != NULL );
723 assert( cons != NULL );
724 assert( feasible != NULL );
725
726 consdata = SCIPconsGetData(cons);
727
728 assert( consdata != NULL );
729 assert( consdata->vars != NULL );
730 assert( consdata->nrows > 0 );
731 assert( consdata->ncols > 0 );
732 assert( ! consdata->ismodelcons ); /* non-model constraints are never checked */
733
734 vars = consdata->vars;
735 nrows = consdata->nrows;
736 ncols = consdata->ncols;
737
738 SCIP_CALL( SCIPallocBufferArray(scip, &vars1, nrows) );
739 SCIP_CALL( SCIPallocBufferArray(scip, &vars2, nrows) );
740
741 /* iterate over adjacent columns of orbitope and check whether the first column in this
742 * column pair is lexicographically not smaller than the second column in the pair */
743 *feasible = TRUE;
744 for (j = 1; j < ncols && *feasible; ++j)
745 {
746 for (i = 0; i < nrows; ++i)
747 {
748 vars1[i] = vars[i][j - 1];
749 vars2[i] = vars[i][j];
750 }
751
752 SCIP_CALL( SCIPcheckSolutionOrbisack(scip, sol, vars1, vars2, nrows, printreason, feasible) );
753 }
754
755 SCIPfreeBufferArray(scip, &vars2);
756 SCIPfreeBufferArray(scip, &vars1);
757
758 return SCIP_OKAY;
759}
760
761
762/** separate orbisack cover inequalities */
763static
765 SCIP* scip, /**< SCIP data structure */
766 SCIP_CONS* cons, /**< constraint to process */
767 SCIP_SOL* sol, /**< solution to separate (NULL for the LP solution) */
768 int* ngen, /**< pointer to store number of generated cuts */
769 SCIP_Bool* infeasible /**< pointer to store whether infeasibility has been detected */
770 )
771{
772 SCIP_CONSDATA* consdata;
773 SCIP_VAR*** vars;
774 int nrows;
775 int ncols;
776 int i;
777 int j;
778 SCIP_Real rhs = 0.0;
779 SCIP_Real lhs = 0.0;
780 SCIP_Real* coeffs1;
781 SCIP_Real* coeffs2;
782
783 assert( scip != NULL );
784 assert( cons != NULL );
785 assert( ngen != NULL );
786 assert( infeasible != NULL );
787
788 *ngen = 0;
789 *infeasible = FALSE;
790
791 /* get basic data */
792 consdata = SCIPconsGetData(cons);
793 assert( consdata != NULL );
794
795 vars = consdata->vars;
796 nrows = consdata->nrows;
797 ncols = consdata->ncols;
798
799 /* allocate memory for cover inequalities */
800 SCIP_CALL( SCIPallocBufferArray(scip, &coeffs1, nrows) );
801 SCIP_CALL( SCIPallocBufferArray(scip, &coeffs2, nrows) );
802
803 /* separate orbisack cover inequalities for adjacent columns */
804 for (j = 0; j < ncols - 1 && ! *infeasible; ++j)
805 {
806 SCIP_Real rowval;
807
808 for (i = 0; i < nrows; ++i)
809 {
810 rowval = SCIPgetSolVal(scip, sol, vars[i][j + 1]) - SCIPgetSolVal(scip, sol, vars[i][j]);
811
812 /* check whether cover inequality is violated */
813 if ( SCIPisEfficacious(scip, rowval + lhs - rhs) )
814 {
815 SCIP_ROW* row;
816 int k;
817
818 /* set coefficients for current inequality */
819 coeffs1[i] = -1.0;
820 coeffs2[i] = 1.0;
821
822 /* add violated orbisack cover inequality */
823 SCIP_CALL( SCIPcreateEmptyRowCons(scip, &row, cons, "orbisackcover", -SCIPinfinity(scip), rhs,
824 FALSE, FALSE, TRUE) );
826
827 for (k = 0; k <= i; ++k)
828 {
829 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][j], coeffs1[k]) );
830 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][j + 1], coeffs2[k]) );
831 }
833
834 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
835#ifdef SCIP_DEBUG
837#endif
838 SCIP_CALL( SCIPreleaseRow(scip, &row) );
839
840 ++(*ngen);
841 if ( *infeasible )
842 break;
843
844 /* reset coefficients for next inequality */
845 coeffs1[i] = 0.0;
846 coeffs2[i] = 0.0;
847 }
848
849 /* add argmax( 1 - vals[i][0], vals[i][1] ) as coefficient and ensure that both vars1[0] and vars2[0] are
850 * contained in the LIFTED cover inequality */
851 rowval = SCIPgetSolVal(scip, sol, vars[i][j]) + SCIPgetSolVal(scip, sol, vars[i][j + 1]);
852 if ( SCIPisEfficacious(scip, 1.0 - rowval) )
853 {
854 coeffs1[i] = -1.0;
855 coeffs2[i] = 0.0;
856 lhs -= SCIPgetSolVal(scip, sol, vars[i][j]);
857
858 /* apply lifting? */
859 if ( i == 0 )
860 {
861 coeffs2[i] = 1.0;
862 lhs += SCIPgetSolVal(scip, sol, vars[i][j + 1]);
863 }
864 }
865 else
866 {
867 coeffs1[i] = 0.0;
868 coeffs2[i] = 1.0;
869 lhs += SCIPgetSolVal(scip, sol, vars[i][j]);
870 rhs += 1.0;
871
872 /* apply lifting? */
873 if ( i == 0 )
874 {
875 coeffs1[i] = -1.0;
876 lhs -= SCIPgetSolVal(scip, sol, vars[i][j]);
877 rhs -= 1.0;
878 }
879 }
880 }
881 }
882
883 SCIPfreeBufferArray(scip, &coeffs1);
884 SCIPfreeBufferArray(scip, &coeffs2);
885
886 return SCIP_OKAY;
887}
888
889
890/** separate or enforce constraints */
891static
893 SCIP* scip, /**< SCIP data structure */
894 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
895 SCIP_CONS** conss, /**< constraints to process */
896 int nconss, /**< number of constraints */
897 int nusefulconss, /**< number of useful (non-obsolete) constraints to process */
898 SCIP_SOL* sol, /**< solution to separate (NULL for the LP solution) */
899 SCIP_RESULT* result, /**< pointer to store the result (should be initialized) */
900 SCIP_Bool enforce /**< whether we enforce orbitope constraints */
901 )
902{
903 SCIP_Bool infeasible = FALSE;
904 int ncuts = 0;
905 int c;
906
907 assert( scip != NULL );
908 assert( conshdlr != NULL );
909 assert( result != NULL );
910
912
913 /* loop through constraints */
914 for (c = 0; c < nconss && ! infeasible; c++)
915 {
916 SCIP_CONSDATA* consdata;
917 int nconscuts = 0;
918
919 assert( conss[c] != NULL );
920
921 /* get data of constraint */
922 consdata = SCIPconsGetData(conss[c]);
923 assert( consdata != NULL );
924
925 /* skip non-model constraints if strong dual reductions are not permitted */
926 if ( !consdata->ismodelcons && !SCIPallowStrongDualReds(scip) )
927 continue;
928
929 /* do not enforce non-model constraints */
930 if ( enforce && !consdata->ismodelcons )
931 continue;
932
933 SCIP_CALL( separateCoversOrbisack(scip, conss[c], sol, &nconscuts, &infeasible) );
934 ncuts += nconscuts;
935
936 /* stop after the useful constraints if we found cuts */
937 if ( c >= nusefulconss && ncuts > 0 )
938 break;
939 }
940
941 if ( infeasible )
942 {
943 SCIPdebugMsg(scip, "Infeasible node.\n");
945 }
946 else if ( ncuts > 0 )
947 {
948 SCIPdebugMsg(scip, "Separated %dinequalities.\n", ncuts);
950 }
951 else
952 {
953 SCIPdebugMsg(scip, "No violated inequality found during separation.\n");
954 }
955
956 return SCIP_OKAY;
957}
958
959
960/** check whether all variables in an orbitope constraint are fixed */
961static
963 SCIP* scip, /**< SCIP data structure */
964 SCIP_CONS* cons, /**< constraint to be processed */
965 SCIP_Bool* redundant /**< pointer to store whether constraint is redundant (contains no active vars) */
966 )
967{
968 SCIP_CONSDATA* consdata;
969 SCIP_VAR*** vars;
970 int i;
971 int j;
972 int nrows;
973 int ncols;
974
975 assert( scip != NULL );
976 assert( cons != NULL );
977 assert( redundant != NULL );
978
979 *redundant = FALSE;
980
981 consdata = SCIPconsGetData(cons);
982 assert( consdata != NULL );
983 assert( consdata->vars != NULL );
984 assert( consdata->nrows > 0 );
985 assert( consdata->ncols > 0 );
986
987 vars = consdata->vars;
988 nrows = consdata->nrows;
989 ncols = consdata->ncols;
990
991 /* check whether there exists an active variable in the orbitope */
992 for (i = 0; i < nrows; ++i)
993 {
994 for (j = 0; j < ncols; ++j)
995 {
996 if ( SCIPvarIsActive(vars[i][j]) )
997 return SCIP_OKAY;
998 }
999 }
1000 *redundant = TRUE;
1001
1002 return SCIP_OKAY;
1003}
1004
1005
1006/** replace aggregated variables by active variables */
1007static
1009 SCIP* scip, /**< SCIP data structure */
1010 SCIP_CONS* cons /**< constraint to be processed */
1011 )
1012{
1013 SCIP_CONSDATA* consdata;
1014 SCIP_VAR*** vars;
1015 int i;
1016 int j;
1017 int nrows;
1018 int ncols;
1019
1020 assert( scip != NULL );
1021 assert( cons != NULL );
1022
1023 consdata = SCIPconsGetData(cons);
1024 assert( consdata != NULL );
1025 assert( consdata->vars != NULL );
1026 assert( consdata->nrows > 0 );
1027 assert( consdata->ncols > 0 );
1028
1029 vars = consdata->vars;
1030 nrows = consdata->nrows;
1031 ncols = consdata->ncols;
1032
1033 /* check whether there exists an aggregated variable in the orbitope */
1034 for (i = 0; i < nrows; ++i)
1035 {
1036 for (j = 0; j < ncols; ++j)
1037 {
1038 SCIP_VAR* var;
1039 SCIP_Bool negated;
1040
1041 assert( SCIPvarGetStatus(vars[i][j]) != SCIP_VARSTATUS_MULTAGGR ); /* variables are marked as not to be multi-aggregated */
1042
1043 SCIP_CALL( SCIPgetBinvarRepresentative(scip, vars[i][j], &var, &negated) );
1044 SCIP_UNUSED( negated );
1046 if ( var != vars[i][j] )
1047 {
1048 SCIP_CALL( SCIPunlockVarCons(scip, vars[i][j], cons, TRUE, TRUE) );
1050 vars[i][j] = var;
1051 SCIP_CALL( SCIPlockVarCons(scip, vars[i][j], cons, TRUE, TRUE) );
1053 }
1054 }
1055 }
1056
1057 return SCIP_OKAY;
1058}
1059
1060
1061/*
1062 * Callback methods of constraint handler
1063 */
1064
1065/** copy method for constraint handler plugins (called when SCIP copies plugins) */
1066static
1067SCIP_DECL_CONSHDLRCOPY(conshdlrCopyOrbitopeFull)
1068{ /*lint --e{715}*/
1069 assert(scip != NULL);
1070 assert(conshdlr != NULL);
1071 assert(valid != NULL);
1072
1074
1075 /* call inclusion method of constraint handler */
1077
1078 *valid = TRUE;
1079
1080 return SCIP_OKAY;
1081}
1082
1083/** frees constraint handler */
1084static
1085SCIP_DECL_CONSFREE(consFreeOrbitopeFull)
1086{ /*lint --e{715}*/
1087 SCIP_CONSHDLRDATA* conshdlrdata;
1088
1089 assert( scip != 0 );
1090 assert( conshdlr != 0 );
1091
1093
1094 conshdlrdata = SCIPconshdlrGetData(conshdlr);
1095 assert( conshdlrdata != NULL );
1096
1097 SCIPfreeBlockMemory(scip, &conshdlrdata);
1098
1099 return SCIP_OKAY;
1100}
1101
1102/** frees specific constraint data */
1103static
1104SCIP_DECL_CONSDELETE(consDeleteOrbitopeFull)
1105{ /*lint --e{715}*/
1106 assert(conshdlr != NULL);
1107
1109
1110 SCIP_CALL( consdataFree(scip, consdata) );
1111
1112 return SCIP_OKAY;
1113}
1114
1115/** transforms constraint data into data belonging to the transformed problem */
1116static
1117SCIP_DECL_CONSTRANS(consTransOrbitopeFull)
1118{ /*lint --e{715}*/
1119 SCIP_CONSDATA* sourcedata;
1120 SCIP_CONSDATA* targetdata;
1121
1122 assert(conshdlr != NULL);
1124 assert(sourcecons != NULL);
1125 assert(targetcons != NULL);
1126
1128
1129 sourcedata = SCIPconsGetData(sourcecons);
1130 assert(sourcedata != NULL);
1131
1132 /* create linear constraint data for target constraint */
1133 SCIP_CALL( consdataCreate(scip, &targetdata, sourcedata->vars, sourcedata->nrows, sourcedata->ncols,
1134 sourcedata->resolveprop, sourcedata->ismodelcons) );
1135
1136 /* create target constraint */
1137 SCIP_CALL( SCIPcreateCons(scip, targetcons, SCIPconsGetName(sourcecons), conshdlr, targetdata,
1138 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons), SCIPconsIsEnforced(sourcecons),
1139 SCIPconsIsChecked(sourcecons), SCIPconsIsPropagated(sourcecons),
1140 SCIPconsIsLocal(sourcecons), SCIPconsIsModifiable(sourcecons),
1141 SCIPconsIsDynamic(sourcecons), SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
1142
1143 return SCIP_OKAY;
1144}
1145
1146/** separation method of constraint handler for LP solutions */
1147static
1148SCIP_DECL_CONSSEPALP(consSepalpOrbitopeFull)
1149{ /*lint --e{715}*/
1150 assert( scip != NULL );
1151 assert( result != NULL );
1152
1153 SCIPdebugMsg(scip, "Separation of full orbitope constraint handler <%s> for LP solution.\n",
1154 SCIPconshdlrGetName(conshdlr));
1155
1157
1158 /* if solution is integer, skip separation */
1159 if ( SCIPgetNLPBranchCands(scip) <= 0 )
1160 return SCIP_OKAY;
1161
1163
1164 /* separate constraints */
1165 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, NULL, result, FALSE) );
1166
1167 return SCIP_OKAY;
1168}
1169
1170/** separation method of constraint handler for arbitrary primal solutions */
1171static
1172SCIP_DECL_CONSSEPASOL(consSepasolOrbitopeFull)
1173{ /*lint --e{715}*/
1174 assert( scip != NULL );
1175 assert( result != NULL );
1176
1177 SCIPdebugMsg(scip, "Separation of full orbitope constraint handler <%s> for primal solution.\n",
1178 SCIPconshdlrGetName(conshdlr));
1179
1181
1182 /* separate constraints */
1183 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, sol, result, FALSE) );
1184
1185 return SCIP_OKAY;
1186}
1187
1188/** constraint enforcing method of constraint handler for LP solutions */
1189static
1190SCIP_DECL_CONSENFOLP(consEnfolpOrbitopeFull)
1191{ /*lint --e{715}*/
1192 assert( scip != NULL );
1193 assert( result != NULL );
1194
1195 /* we have a negative priority, so we should come after the integrality conshdlr */
1197
1198 SCIPdebugMsg(scip, "Enforcement for full orbitope constraint handler <%s> for LP solution.\n",
1199 SCIPconshdlrGetName(conshdlr));
1200
1202
1203 /* separate constraints */
1204 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, NULL, result, TRUE) );
1205
1206 return SCIP_OKAY;
1207}
1208
1209/** constraint enforcing method of constraint handler for relaxation solutions */
1210static
1211SCIP_DECL_CONSENFORELAX(consEnforelaxOrbitopeFull)
1212{ /*lint --e{715}*/
1213 assert( result != NULL );
1214 assert( scip != NULL );
1215
1216 SCIPdebugMsg(scip, "Enforcement for full orbitope constraint handler <%s> for relaxation solution.\n",
1217 SCIPconshdlrGetName(conshdlr));
1218
1220
1221 /* separate constraints */
1222 SCIP_CALL( separateConstraints(scip, conshdlr, conss, nconss, nusefulconss, sol, result, TRUE) );
1223
1224 return SCIP_OKAY;
1225}
1226
1227/** constraint enforcing method of constraint handler for pseudo solutions */
1228static
1229SCIP_DECL_CONSENFOPS(consEnfopsOrbitopeFull)
1230{ /*lint --e{715}*/
1231 int c;
1232
1233 assert( scip != NULL );
1234 assert( conshdlr != NULL );
1235 assert( result != NULL );
1236
1238
1240 if ( objinfeasible || solinfeasible )
1241 return SCIP_OKAY;
1242
1243 /* loop through constraints */
1244 for (c = 0; c < nconss && *result == SCIP_FEASIBLE; ++c)
1245 {
1246 SCIP_CONSDATA* consdata;
1247 SCIP_Bool feasible;
1248
1249 /* get data of constraint */
1250 assert( conss[c] != NULL );
1251 consdata = SCIPconsGetData(conss[c]);
1252 assert( consdata != NULL );
1253
1254 /* do not enforce non-model constraints */
1255 if ( !consdata->ismodelcons )
1256 continue;
1257
1258 SCIP_CALL( checkFullOrbitopeSolution(scip, conss[c], NULL, FALSE, &feasible) );
1259
1260 if ( ! feasible )
1262 }
1263
1264 return SCIP_OKAY;
1265}
1266
1267
1268/** feasibility check method of constraint handler for integral solutions */
1269static
1270SCIP_DECL_CONSCHECK(consCheckOrbitopeFull)
1271{ /*lint --e{715}*/
1272 int c;
1273
1274 assert( scip != NULL );
1275 assert( conshdlr != NULL );
1276 assert( result != NULL );
1277
1279
1281
1282 /* loop through constraints */
1283 for( c = 0; c < nconss && (*result == SCIP_FEASIBLE || completely); ++c )
1284 {
1285 SCIP_CONSDATA* consdata;
1286 SCIP_Bool feasible;
1287
1288 assert( conss[c] != 0 );
1289 consdata = SCIPconsGetData(conss[c]);
1290 assert( consdata != NULL );
1291
1292 /* do not check non-model constraints */
1293 if ( !consdata->ismodelcons )
1294 continue;
1295
1296 SCIP_CALL( checkFullOrbitopeSolution(scip, conss[c], sol, printreason, &feasible) );
1297
1298 if ( ! feasible )
1300 }
1301
1302 if( *result == SCIP_FEASIBLE )
1303 {
1304 SCIPdebugMsg(scip, "Solution is feasible.\n");
1305 }
1306 else
1307 {
1308 SCIPdebugMsg(scip, "Solution is infeasible.\n");
1309 }
1310
1311 return SCIP_OKAY;
1312}
1313
1314
1315/** domain propagation method of constraint handler */
1316static
1317SCIP_DECL_CONSPROP(consPropOrbitopeFull)
1318{ /*lint --e{715}*/
1319 SCIP_Bool infeasible = FALSE;
1320 int nfixedvars = 0;
1321 int c;
1322
1323 assert( scip != NULL );
1324 assert( conshdlr != NULL );
1325 assert( result != NULL );
1326
1328
1330
1331 /* propagate all useful constraints */
1332 for (c = 0; c < nusefulconss && !infeasible; ++c)
1333 {
1334 int nfixed;
1335 assert( conss[c] != 0 );
1336
1337 SCIPdebugMsg(scip, "Propagation of full orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1338
1339 SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixed) );
1340 nfixedvars += nfixed;
1341 }
1342
1343 /* return the correct result */
1344 if ( infeasible )
1345 {
1347 SCIPdebugMsg(scip, "Propagation via orbitopal fixing proved node to be infeasible.\n");
1348 }
1349 else if ( nfixedvars > 0 )
1350 {
1352 SCIPdebugMsg(scip, "Propagated %d variables via orbitopal fixing.\n", nfixedvars);
1353 }
1354 else if ( nusefulconss > 0 )
1355 {
1357 SCIPdebugMsg(scip, "Propagation via orbitopal fixing did not find anything.\n");
1358 }
1359
1360 return SCIP_OKAY;
1361}
1362
1363
1364/** presolving method of constraint handler */
1365static
1366SCIP_DECL_CONSPRESOL(consPresolOrbitopeFull)
1367{ /*lint --e{715}*/
1368 SCIP_Bool infeasible = FALSE;
1369 int noldfixedvars;
1370 int c;
1371 SCIP_Bool redundant;
1372
1373 assert( scip != NULL );
1374 assert( conshdlr != NULL );
1375 assert( result != NULL );
1376
1378
1380 noldfixedvars = *nfixedvars;
1381
1382 /* propagate all useful constraints
1383 *
1384 * @todo use an event handler to only propagate if a variable in the orbitope has been fixed
1385 */
1386 for (c = 0; c < nconss && !infeasible; ++c)
1387 {
1388 int nfixed = 0;
1389
1390 assert( conss[c] != 0 );
1391
1392 SCIPdebugMsg(scip, "Presolving of full orbitope constraint <%s> ...\n", SCIPconsGetName(conss[c]));
1393
1394 /* first propagate */
1395 SCIP_CALL( propagateCons(scip, conss[c], &infeasible, &nfixed) );
1396 *nfixedvars += nfixed;
1397
1398 if ( ! infeasible )
1399 {
1400 SCIP_CALL( checkRedundantCons(scip, conss[c], &redundant) );
1401
1402 if ( redundant )
1403 {
1404 SCIPdebugMsg(scip, "Full orbitope constraint <%s> is redundant: it does not contain active variables\n",
1405 SCIPconsGetName(conss[c]));
1406 SCIP_CALL( SCIPdelCons(scip, conss[c]) );
1407 assert( ! SCIPconsIsActive(conss[c]) );
1408 (*ndelconss)++;
1409 continue;
1410 }
1411 }
1412 }
1413
1414 if ( infeasible )
1415 {
1417 SCIPdebugMsg(scip, "Presolving detected infeasibility.\n");
1418 }
1419 else if ( *nfixedvars > noldfixedvars )
1420 {
1422 }
1423 else if ( nconss > 0 )
1424 {
1426 SCIPdebugMsg(scip, "Presolving via orbitopal fixing did not find anything.\n");
1427 }
1428
1429 return SCIP_OKAY;
1430}
1431
1432
1433/** propagation conflict resolving method of constraint handler */
1434static
1435SCIP_DECL_CONSRESPROP(consRespropOrbitopeFull)
1436{ /*lint --e{715}*/
1437 assert( scip != NULL );
1438 assert( cons != NULL );
1439 assert( infervar != NULL );
1440 assert( bdchgidx != NULL );
1441 assert( result != NULL );
1442
1443 SCIP_CALL( resolvePropagationFullOrbitope(scip, conshdlr, cons, inferinfo, bdchgidx, result) );
1444
1445 return SCIP_OKAY;
1446}
1447
1448
1449/** presolving deinitialization method of constraint handler (called after presolving has been finished) */
1450static
1451SCIP_DECL_CONSEXITPRE(consExitpreOrbitopeFull)
1452{
1453 int c;
1454
1455 assert( scip != NULL );
1456 assert( conshdlr != NULL );
1457
1459
1460 for (c = 0; c < nconss; ++c)
1461 {
1462 /* replace aggregated variables by active variables */
1464 }
1465 return SCIP_OKAY;
1466}
1467
1468
1469/** variable rounding lock method of constraint handler */
1470static
1471SCIP_DECL_CONSLOCK(consLockOrbitopeFull)
1472{ /*lint --e{715}*/
1473 SCIP_CONSDATA* consdata;
1474 SCIP_VAR*** vars;
1475 int i;
1476 int j;
1477 int nrows;
1478 int ncols;
1479
1480 assert( scip != NULL );
1481 assert( conshdlr != NULL );
1482 assert( cons != NULL );
1483 assert( locktype == SCIP_LOCKTYPE_MODEL );
1484
1486
1487 consdata = SCIPconsGetData(cons);
1488 assert( consdata != NULL );
1489 assert( consdata->nrows > 0 );
1490 assert( consdata->ncols > 0 );
1491 assert( consdata->vars != NULL );
1492
1493 SCIPdebugMsg(scip, "Locking method for full orbitope constraint handler\n");
1494
1495 nrows = consdata->nrows;
1496 ncols = consdata->ncols;
1497 vars = consdata->vars;
1498
1499 /* add up locks and down locks on each variable */
1500 for (i = 0; i < nrows; ++i)
1501 {
1502 for (j = 0; j < ncols; ++j)
1503 {
1504 SCIP_CALL( SCIPaddVarLocksType(scip, vars[i][j], locktype, nlockspos + nlocksneg, nlockspos + nlocksneg) );
1505 }
1506 }
1507
1508 return SCIP_OKAY;
1509}
1510
1511
1512/** constraint display method of constraint handler */
1513static
1514SCIP_DECL_CONSPRINT(consPrintOrbitopeFull)
1515{
1516 SCIP_CONSDATA* consdata;
1517 SCIP_VAR*** vars;
1518 int i;
1519 int j;
1520 int nrows;
1521 int ncols;
1522
1523 assert( scip != NULL );
1524 assert( conshdlr != NULL );
1525 assert( cons != NULL );
1526
1528
1529 consdata = SCIPconsGetData(cons);
1530 assert( consdata != NULL );
1531 assert( consdata->nrows > 0 );
1532 assert( consdata->ncols > 0 );
1533 assert( consdata->vars != NULL );
1534
1535 nrows = consdata->nrows;
1536 ncols = consdata->ncols;
1537 vars = consdata->vars;
1538
1539 SCIPdebugMsg(scip, "Printing method for full orbitope constraint handler\n");
1540
1541 SCIPinfoMessage(scip, file, "fullOrbitope(");
1542
1543 for (i = 0; i < nrows; ++i)
1544 {
1545 for (j = 0; j < ncols; ++j)
1546 {
1547 if ( j > 0 )
1548 SCIPinfoMessage(scip, file, ",");
1549 SCIP_CALL( SCIPwriteVarName(scip, file, vars[i][j], TRUE) );
1550 }
1551 if ( i < nrows - 1 )
1552 SCIPinfoMessage(scip, file, ".");
1553 }
1554 SCIPinfoMessage(scip, file, ")");
1555
1556 return SCIP_OKAY;
1557}
1558
1559
1560/** constraint copying method of constraint handler */
1561static
1562SCIP_DECL_CONSCOPY(consCopyOrbitopeFull)
1563{
1564 SCIP_CONSHDLRDATA* conshdlrdata;
1565 SCIP_CONSDATA* sourcedata;
1566 SCIP_VAR*** sourcevars;
1567 SCIP_VAR*** vars;
1568 int nrows;
1569 int ncols;
1570 int i;
1571 int k;
1572 int j;
1573
1574 assert( scip != NULL );
1575 assert( cons != NULL );
1576 assert( sourcescip != NULL );
1577 assert( sourceconshdlr != NULL );
1578 assert( sourcecons != NULL );
1579 assert( varmap != NULL );
1580 assert( valid != NULL );
1581
1583
1584 *valid = TRUE;
1585
1586 SCIPdebugMsg(scip, "Copying method for full orbitope constraint handler.\n");
1587
1588 sourcedata = SCIPconsGetData(sourcecons);
1589 assert( sourcedata != NULL );
1590 assert( sourcedata->nrows > 0 );
1591 assert( sourcedata->ncols > 0 );
1592 assert( sourcedata->vars != NULL );
1593
1594 conshdlrdata = SCIPconshdlrGetData(sourceconshdlr);
1595 assert( conshdlrdata != NULL );
1596
1597 /* do not copy non-model constraints */
1598 if ( !sourcedata->ismodelcons && !conshdlrdata->forceconscopy )
1599 {
1600 *valid = FALSE;
1601
1602 return SCIP_OKAY;
1603 }
1604
1605 nrows = sourcedata->nrows;
1606 ncols = sourcedata->ncols;
1607 sourcevars = sourcedata->vars;
1608
1610 for (i = 0; i < nrows && *valid; ++i)
1611 {
1612 SCIP_CALL( SCIPallocBufferArray(scip, &(vars[i]), ncols) ); /*lint !e866*/
1613
1614 for (j = 0; j < ncols && *valid; ++j)
1615 {
1616 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[i][j], &(vars[i][j]), varmap, consmap, global, valid) );
1617 assert( !(*valid) || vars[i][j] != NULL );
1618 }
1619 }
1620
1621 /* only create the target constraint, if all variables could be copied */
1622 if ( *valid )
1623 {
1624 /* create copied constraint */
1625 if ( name == NULL )
1626 name = SCIPconsGetName(sourcecons);
1627
1628 SCIP_CALL( SCIPcreateConsOrbitopeFull(scip, cons, name, vars, nrows, ncols,
1629 sourcedata->resolveprop, sourcedata->ismodelcons,
1630 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1631 }
1632
1633 /* free space; only up to row i if copying failed */
1634 assert( 0 <= i && i <= nrows );
1635 for (k = i - 1; k >= 0; --k)
1638
1639 return SCIP_OKAY;
1640}
1641
1642
1643/** constraint parsing method of constraint handler */
1644static
1645SCIP_DECL_CONSPARSE(consParseOrbitopeFull)
1646{ /*lint --e{715}*/
1647 const char* s;
1648 char* endptr;
1649 SCIP_VAR*** vars;
1650 SCIP_VAR* var;
1651 int nrows;
1652 int maxnrows;
1653 int ncols;
1654 int maxncols;
1655 int k;
1656 int j;
1657
1658 assert( success != NULL );
1659
1660 *success = TRUE;
1661 s = str;
1662
1663 /* skip white space */
1664 SCIP_CALL( SCIPskipSpace((char**)&s) );
1665
1666 if( strncmp(s, "fullOrbitope(", 13) != 0 )
1667 {
1668 SCIPerrorMessage("Syntax error - expected \"fullOrbitope(\": %s\n", s);
1669 *success = FALSE;
1670 return SCIP_OKAY;
1671 }
1672 s += 13;
1673
1674 /* loop through string */
1675 nrows = 0;
1676 ncols = 0;
1677 maxnrows = 10;
1678 maxncols = 10;
1679
1680 SCIP_CALL( SCIPallocBufferArray(scip, &vars, maxnrows) );
1681
1682 j = 0;
1683 do
1684 {
1685 /* parse variable name */
1686 SCIP_CALL( SCIPparseVarName(scip, s, &var, &endptr) );
1687
1688 if( var == NULL )
1689 {
1690 endptr = strchr(endptr, ')');
1691
1692 if( endptr == NULL || j > 0 )
1693 {
1694 SCIPerrorMessage("not enough variables.\n");
1695 *success = FALSE;
1696 }
1697
1698 break;
1699 }
1700
1701 s = endptr;
1702 assert( s != NULL );
1703
1704 /* skip white space */
1705 SCIP_CALL( SCIPskipSpace((char**)&s) );
1706
1707 /* begin new row if required */
1708 if( j == 0 )
1709 {
1710 ++nrows;
1711
1712 if( nrows > maxnrows )
1713 {
1714 maxnrows = SCIPcalcMemGrowSize(scip, nrows);
1715 SCIP_CALL( SCIPreallocBufferArray(scip, &vars, maxnrows) );
1716 assert( nrows <= maxnrows );
1717 }
1718
1719 SCIP_CALL( SCIPallocBufferArray(scip, &(vars[nrows-1]), nrows == 1 ? maxncols : ncols) ); /*lint !e866*/
1720 }
1721
1722 /* determine number of columns */
1723 if( nrows == 1 )
1724 {
1725 ncols = j + 1;
1726
1727 if( *s == '.' || *s == ')' )
1728 SCIP_CALL( SCIPreallocBufferArray(scip, &(vars[nrows-1]), ncols) ); /*lint !e866*/
1729 else if( ncols > maxncols )
1730 {
1731 maxncols = SCIPcalcMemGrowSize(scip, ncols);
1732 SCIP_CALL( SCIPreallocBufferArray(scip, &(vars[nrows-1]), maxncols) ); /*lint !e866*/
1733 assert( ncols <= maxncols );
1734 }
1735 }
1736 else if( ( j < ncols-1 ) == ( *s == '.' || *s == ')' ) )
1737 {
1738 SCIPerrorMessage("variables per row do not match.\n");
1739 *success = FALSE;
1740 break;
1741 }
1742
1743 vars[nrows-1][j] = var;
1744
1745 if( *s == '.' )
1746 j = 0;
1747 else
1748 ++j;
1749
1750 /* skip ',' or '.' */
1751 if( *s == ',' || *s == '.' )
1752 ++s;
1753 }
1754 while( *s != ')' );
1755
1756 if( *success )
1757 {
1758 SCIP_CALL( SCIPcreateConsOrbitopeFull(scip, cons, name, vars, nrows, ncols, TRUE, TRUE,
1759 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1760 }
1761
1762 for( k = nrows - 1; k >= 0; --k )
1765
1766 return SCIP_OKAY;
1767}
1768
1769
1770/** constraint method of constraint handler which returns the variables (if possible) */
1771static
1772SCIP_DECL_CONSGETVARS(consGetVarsOrbitopeFull)
1773{ /*lint --e{715}*/
1774 SCIP_CONSDATA* consdata;
1775
1776 assert( cons != NULL );
1777 assert( success != NULL );
1778 assert( vars != NULL );
1779
1780 consdata = SCIPconsGetData(cons);
1781 assert( consdata != NULL );
1782
1783 if ( varssize < consdata->ncols * consdata->nrows )
1784 *success = FALSE;
1785 else
1786 {
1787 int cnt = 0;
1788 int i;
1789 int j;
1790
1791 for (i = 0; i < consdata->nrows; ++i)
1792 {
1793 for (j = 0; j < consdata->ncols; ++j)
1794 vars[cnt++] = consdata->vars[i][j];
1795 }
1796 *success = TRUE;
1797 }
1798
1799 return SCIP_OKAY;
1800}
1801
1802
1803/** constraint method of constraint handler which returns the number of variables (if possible) */
1804static
1805SCIP_DECL_CONSGETNVARS(consGetNVarsOrbitopeFull)
1806{ /*lint --e{715}*/
1807 SCIP_CONSDATA* consdata;
1808
1809 assert( cons != NULL );
1810
1811 consdata = SCIPconsGetData(cons);
1812 assert( consdata != NULL );
1813
1814 *nvars = consdata->ncols * consdata->nrows;
1815 *success = TRUE;
1816
1817 return SCIP_OKAY;
1818}
1819
1820
1821/*
1822 * constraint specific interface methods
1823 */
1824
1825/** creates the handler for orbitope constraints and includes it in SCIP */
1827 SCIP* scip /**< SCIP data structure */
1828 )
1829{
1830 SCIP_CONSHDLRDATA* conshdlrdata;
1831 SCIP_CONSHDLR* conshdlr;
1832
1833 /* create orbitope constraint handler data */
1834 SCIP_CALL( SCIPallocBlockMemory(scip, &conshdlrdata) );
1835
1836 /* include constraint handler */
1840 consEnfolpOrbitopeFull, consEnfopsOrbitopeFull, consCheckOrbitopeFull, consLockOrbitopeFull,
1841 conshdlrdata) );
1842 assert(conshdlr != NULL);
1843
1844 /* set non-fundamental callbacks via specific setter functions */
1845 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyOrbitopeFull, consCopyOrbitopeFull) );
1846 SCIP_CALL( SCIPsetConshdlrFree(scip, conshdlr, consFreeOrbitopeFull) );
1847 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteOrbitopeFull) );
1848 SCIP_CALL( SCIPsetConshdlrGetVars(scip, conshdlr, consGetVarsOrbitopeFull) );
1849 SCIP_CALL( SCIPsetConshdlrGetNVars(scip, conshdlr, consGetNVarsOrbitopeFull) );
1850 SCIP_CALL( SCIPsetConshdlrParse(scip, conshdlr, consParseOrbitopeFull) );
1851 SCIP_CALL( SCIPsetConshdlrPresol(scip, conshdlr, consPresolOrbitopeFull,
1853 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintOrbitopeFull) );
1854 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropOrbitopeFull, CONSHDLR_PROPFREQ, CONSHDLR_DELAYPROP,
1856 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropOrbitopeFull) );
1857 SCIP_CALL( SCIPsetConshdlrExitpre(scip, conshdlr, consExitpreOrbitopeFull) );
1858 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpOrbitopeFull, consSepasolOrbitopeFull, CONSHDLR_SEPAFREQ,
1860 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransOrbitopeFull) );
1861 SCIP_CALL( SCIPsetConshdlrEnforelax(scip, conshdlr, consEnforelaxOrbitopeFull) );
1862
1863 SCIP_CALL( SCIPaddBoolParam(scip, "constraints/" CONSHDLR_NAME "/forceconscopy",
1864 "Whether orbitope constraints should be forced to be copied to sub SCIPs.",
1865 &conshdlrdata->forceconscopy, TRUE, DEFAULT_FORCECONSCOPY, NULL, NULL) );
1866
1867 return SCIP_OKAY;
1868}
1869
1870
1871/** creates and captures a full orbitope constraint
1872 *
1873 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
1874 */
1876 SCIP* scip, /**< SCIP data structure */
1877 SCIP_CONS** cons, /**< pointer to hold the created constraint */
1878 const char* name, /**< name of constraint */
1879 SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
1880 int nrows, /**< number of set partitioning/packing constraints <=> p */
1881 int ncols, /**< number of symmetric variable blocks <=> q */
1882 SCIP_Bool resolveprop, /**< should propagation be resolved? */
1883 SCIP_Bool ismodelcons, /**< whether the orbitope is a model constraint */
1884 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP?
1885 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */
1886 SCIP_Bool separate, /**< should the constraint be separated during LP processing?
1887 * Usually set to TRUE. */
1888 SCIP_Bool enforce, /**< should the constraint be enforced during node processing?
1889 * TRUE for model constraints, FALSE for additional, redundant constraints. */
1890 SCIP_Bool check, /**< should the constraint be checked for feasibility?
1891 * TRUE for model constraints, FALSE for additional, redundant constraints. */
1892 SCIP_Bool propagate, /**< should the constraint be propagated during node processing?
1893 * Usually set to TRUE. */
1894 SCIP_Bool local, /**< is constraint only valid locally?
1895 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */
1896 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)?
1897 * Usually set to FALSE. In column generation applications, set to TRUE if pricing
1898 * adds coefficients to this constraint. */
1899 SCIP_Bool dynamic, /**< is constraint subject to aging?
1900 * Usually set to FALSE. Set to TRUE for own cuts which
1901 * are separated as constraints. */
1902 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup?
1903 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */
1904 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
1905 * if it may be moved to a more global node?
1906 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */
1907 )
1908{
1909 SCIP_CONSHDLR* conshdlr;
1910 SCIP_CONSDATA* consdata;
1911
1912 /* find the orbitope constraint handler */
1913 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
1914 if ( conshdlr == NULL )
1915 {
1916 SCIPerrorMessage("full orbitope constraint handler not found\n");
1917 return SCIP_PLUGINNOTFOUND;
1918 }
1919
1920 assert( nrows > 0 );
1921 assert( ncols > 0 );
1922
1923 /* run some checks */
1924#ifndef NDEBUG
1925 {
1926 SCIP_Real obj;
1927 int i;
1928 int j;
1929 for (i = 0; i < nrows; ++i)
1930 {
1931 /* initialize obj to infinity */
1933 for (j = 0; j < ncols; ++j)
1934 {
1935 SCIP_Bool fixedZero;
1936 SCIP_VAR* var;
1937
1938 var = vars[i][j];
1939 assert(var != NULL);
1940
1941 if ( SCIPvarIsNegated(var) )
1943
1944 /* all variables need to be binary */
1946
1947 /* fixed variables have obj = 0; for variables fixed to 0, we assume that there is no
1948 problem (but we cannot always check it, e.g., when in the original problem
1949 variables were fixed and this problem was copied.) */
1951
1952 /* @todo adapt correctness of the following check for sub-scips */
1953 if ( SCIPgetSubscipDepth(scip) == 0 )
1954 {
1955 /* check whether all variables in a row have the same objective */
1956 if ( ! fixedZero && SCIPisInfinity(scip, obj) )
1958 else
1959 {
1960 assert( fixedZero || ! SCIPvarIsActive(var) || SCIPisEQ(scip, obj, SCIPvarGetObj(var)) );
1961 }
1962 }
1963 }
1964 }
1965 }
1966#endif
1967
1968 /* create constraint data */
1969 SCIP_CALL( consdataCreate(scip, &consdata, vars, nrows, ncols, resolveprop, ismodelcons) );
1970
1971 /* create constraint */
1972 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
1973 local, modifiable, dynamic, removable, stickingatnode) );
1974
1975 return SCIP_OKAY;
1976}
1977
1978/** creates and captures a full orbitope constraint in its most basic variant, i. e., with all constraint flags set to
1979 * their default values, which can be set afterwards using SCIPsetConsFLAGNAME()
1980 *
1981 * @see SCIPcreateConsOrbitopeFull() for the default constraint flag configuration
1982 *
1983 * @note the constraint gets captured, hence at one point you have to release it using the method SCIPreleaseCons()
1984 */
1986 SCIP* scip, /**< SCIP data structure */
1987 SCIP_CONS** cons, /**< pointer to hold the created constraint */
1988 const char* name, /**< name of constraint */
1989 SCIP_VAR*** vars, /**< matrix of variables on which the symmetry acts */
1990 int nrows, /**< number of set partitioning/packing constraints <=> p */
1991 int ncols, /**< number of symmetric variable blocks <=> q */
1992 SCIP_Bool resolveprop, /**< should propagation be resolved? */
1993 SCIP_Bool ismodelcons /**< whether the orbitope is a model constraint */
1994 )
1995{
1996 SCIP_CALL( SCIPcreateConsOrbitopeFull(scip, cons, name, vars, nrows, ncols,
1997 resolveprop, ismodelcons, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
1998
1999 return SCIP_OKAY;
2000}
#define CONSHDLR_NEEDSCONS
Definition cons_and.c:96
#define CONSHDLR_SEPAFREQ
Definition cons_and.c:89
#define CONSHDLR_CHECKPRIORITY
Definition cons_and.c:88
#define CONSHDLR_DESC
Definition cons_and.c:85
#define CONSHDLR_PROP_TIMING
Definition cons_and.c:99
#define CONSHDLR_MAXPREROUNDS
Definition cons_and.c:93
#define CONSHDLR_SEPAPRIORITY
Definition cons_and.c:86
#define CONSHDLR_PROPFREQ
Definition cons_and.c:90
#define CONSHDLR_PRESOLTIMING
Definition cons_and.c:98
#define CONSHDLR_EAGERFREQ
Definition cons_and.c:91
#define CONSHDLR_ENFOPRIORITY
Definition cons_and.c:87
#define CONSHDLR_DELAYSEPA
Definition cons_and.c:94
#define CONSHDLR_NAME
Definition cons_and.c:84
#define CONSHDLR_DELAYPROP
Definition cons_and.c:95
#define DEFAULT_FORCECONSCOPY
constraint handler for orbisack constraints
static SCIP_RETCODE checkRedundantCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *redundant)
static SCIP_RETCODE checkFullOrbitopeSolution(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool *feasible)
static SCIP_RETCODE separateConstraints(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS **conss, int nconss, int nusefulconss, SCIP_SOL *sol, SCIP_RESULT *result, SCIP_Bool enforce)
static SCIP_RETCODE propagateCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *infeasible, int *nfixedvars)
static SCIP_RETCODE resolvePropagationFullOrbitope(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_CONS *cons, int inferinfo, SCIP_BDCHGIDX *bdchgidx, SCIP_RESULT *result)
static SCIP_RETCODE findLexMaxFace(SCIP_VAR ***vars, int **lexmaxfixes, int *minfixedrowlexmax, SCIP_Bool *infeasible, int nrows, int ncols, SCIP_Bool resprop)
static SCIP_RETCODE separateCoversOrbisack(SCIP *scip, SCIP_CONS *cons, SCIP_SOL *sol, int *ngen, SCIP_Bool *infeasible)
static SCIP_RETCODE consdataFree(SCIP *scip, SCIP_CONSDATA **consdata)
static SCIP_RETCODE findLexMinFace(SCIP_VAR ***vars, int **lexminfixes, int *minfixedrowlexmin, SCIP_Bool *infeasible, int nrows, int ncols, SCIP_Bool resprop)
static SCIP_RETCODE consdataCreate(SCIP *scip, SCIP_CONSDATA **consdata, SCIP_VAR ***vars, int nrows, int ncols, SCIP_Bool resolveprop, SCIP_Bool ismodelcons)
static SCIP_RETCODE replaceAggregatedVarsOrbitopeFull(SCIP *scip, SCIP_CONS *cons)
constraint handler for full orbitope constraints w.r.t. the full symmetric group
Constraint handler for the set partitioning / packing / covering constraints .
#define NULL
Definition def.h:257
#define SCIP_UNUSED(x)
Definition def.h:418
#define SCIP_Bool
Definition def.h:100
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL(x)
Definition def.h:364
SCIP_RETCODE SCIPcheckSolutionOrbisack(SCIP *scip, SCIP_SOL *sol, SCIP_VAR **vars1, SCIP_VAR **vars2, int nrows, SCIP_Bool printreason, SCIP_Bool *feasible)
SCIP_RETCODE SCIPcreateConsBasicOrbitopeFull(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, int nrows, int ncols, SCIP_Bool resolveprop, SCIP_Bool ismodelcons)
SCIP_RETCODE SCIPcreateConsOrbitopeFull(SCIP *scip, SCIP_CONS **cons, const char *name, SCIP_VAR ***vars, int nrows, int ncols, 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)
SCIP_RETCODE SCIPincludeConshdlrOrbitopeFull(SCIP *scip)
int SCIPgetSubscipDepth(SCIP *scip)
Definition scip_copy.c:2589
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:713
SCIP_Bool SCIPisTransformed(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
SCIP_RETCODE SCIPdelCons(SCIP *scip, SCIP_CONS *cons)
Definition scip_prob.c:3420
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
#define SCIPdebugMsg
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
int SCIPgetNLPBranchCands(SCIP *scip)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPsetConshdlrFree(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:372
SCIP_RETCODE SCIPsetConshdlrPresol(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRESOL((*conspresol)), int maxprerounds, SCIP_PRESOLTIMING presoltiming)
Definition scip_cons.c:540
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:235
SCIP_RETCODE SCIPsetConshdlrProp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPROP((*consprop)), int propfreq, SCIP_Bool delayprop, SCIP_PROPTIMING proptiming)
Definition scip_cons.c:281
SCIP_RETCODE SCIPsetConshdlrEnforelax(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:323
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:181
SCIP_RETCODE SCIPsetConshdlrParse(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:808
SCIP_RETCODE SCIPsetConshdlrGetVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:831
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:785
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4320
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)),)
Definition scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:578
SCIP_CONSHDLRDATA * SCIPconshdlrGetData(SCIP_CONSHDLR *conshdlr)
Definition cons.c:4340
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrExitpre(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:516
SCIP_RETCODE SCIPsetConshdlrGetNVars(SCIP *scip, SCIP_CONSHDLR *conshdlr,)
Definition scip_cons.c:854
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition cons.c:8423
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition cons.c:8652
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition cons.c:8562
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition cons.c:8592
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition cons.c:8582
SCIP_Bool SCIPconsIsActive(SCIP_CONS *cons)
Definition cons.c:8454
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:997
SCIP_Bool SCIPconsIsPropagated(SCIP_CONS *cons)
Definition cons.c:8612
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition cons.c:8632
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition cons.c:8393
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition cons.c:8642
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition cons.c:8672
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition cons.c:8572
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition cons.c:8662
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition scip_cut.c:135
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
int SCIPcalcMemGrowSize(SCIP *scip, int num)
Definition scip_mem.c:139
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition scip_mem.h:111
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
#define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
Definition scip_mem.h:105
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1581
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:1398
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1604
SCIP_RETCODE SCIPaddVarToRow(SCIP *scip, SCIP_ROW *row, SCIP_VAR *var, SCIP_Real val)
Definition scip_lp.c:1646
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
Definition scip_lp.c:2176
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5210
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition var.c:23900
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition var.c:23418
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition var.c:23932
SCIP_RETCODE SCIPparseVarName(SCIP *scip, const char *str, SCIP_VAR **var, char **endptr)
Definition scip_var.c:728
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition scip_var.c:5118
SCIP_RETCODE SCIPunlockVarCons(SCIP *scip, SCIP_VAR *var, SCIP_CONS *cons, SCIP_Bool lockdown, SCIP_Bool lockup)
Definition scip_var.c:5296
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2872
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition var.c:23475
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_RETCODE SCIPmarkDoNotMultaggrVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:11057
SCIP_Real SCIPgetVarLbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition scip_var.c:2736
SCIP_RETCODE SCIPinferBinvarCons(SCIP *scip, SCIP_VAR *var, SCIP_Bool fixedval, SCIP_CONS *infercons, int inferinfo, SCIP_Bool *infeasible, SCIP_Bool *tightened)
Definition scip_var.c:7412
SCIP_RETCODE SCIPwriteVarName(SCIP *scip, FILE *file, SCIP_VAR *var, SCIP_Bool type)
Definition scip_var.c:361
SCIP_RETCODE SCIPgetBinvarRepresentative(SCIP *scip, SCIP_VAR *var, SCIP_VAR **repvar, SCIP_Bool *negated)
Definition scip_var.c:2236
SCIP_RETCODE SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition scip_var.c:2078
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1853
SCIP_Bool SCIPallowStrongDualReds(SCIP *scip)
Definition scip_var.c:10984
SCIP_RETCODE SCIPskipSpace(char **s)
Definition misc.c:10816
return SCIP_OKAY
int c
static SCIP_SOL * sol
SCIP_Real obj
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_Bool propagate
static SCIP_VAR ** vars
memory allocation routines
public methods for managing constraints
public methods for message output
#define SCIPerrorMessage
Definition pub_message.h:64
public methods for problem variables
SCIP callable library.
public methods for branching rule plugins and branching
public methods for conflict handler plugins and conflict analysis
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for cuts and aggregation rows
general public methods
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for the probing mode
public methods for solutions
public methods for SCIP variables
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
methods for handling symmetries
#define SCIP_DECL_CONSENFOLP(x)
Definition type_cons.h:363
#define SCIP_DECL_CONSDELETE(x)
Definition type_cons.h:229
struct SCIP_Cons SCIP_CONS
Definition type_cons.h:63
#define SCIP_DECL_CONSGETVARS(x)
Definition type_cons.h:867
#define SCIP_DECL_CONSPRINT(x)
Definition type_cons.h:769
struct SCIP_ConshdlrData SCIP_CONSHDLRDATA
Definition type_cons.h:64
#define SCIP_DECL_CONSSEPALP(x)
Definition type_cons.h:288
#define SCIP_DECL_CONSENFORELAX(x)
Definition type_cons.h:388
#define SCIP_DECL_CONSPROP(x)
Definition type_cons.h:506
#define SCIP_DECL_CONSGETNVARS(x)
Definition type_cons.h:885
#define SCIP_DECL_CONSRESPROP(x)
Definition type_cons.h:612
#define SCIP_DECL_CONSENFOPS(x)
Definition type_cons.h:431
#define SCIP_DECL_CONSPARSE(x)
Definition type_cons.h:845
#define SCIP_DECL_CONSTRANS(x)
Definition type_cons.h:239
#define SCIP_DECL_CONSPRESOL(x)
Definition type_cons.h:561
#define SCIP_DECL_CONSEXITPRE(x)
Definition type_cons.h:180
#define SCIP_DECL_CONSLOCK(x)
Definition type_cons.h:676
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
#define SCIP_DECL_CONSCOPY(x)
Definition type_cons.h:810
struct SCIP_ConsData SCIP_CONSDATA
Definition type_cons.h:65
#define SCIP_DECL_CONSCHECK(x)
Definition type_cons.h:474
#define SCIP_DECL_CONSHDLRCOPY(x)
Definition type_cons.h:108
#define SCIP_DECL_CONSFREE(x)
Definition type_cons.h:116
#define SCIP_DECL_CONSSEPASOL(x)
Definition type_cons.h:320
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_FEASIBLE
Definition type_result.h:45
@ SCIP_REDUCEDDOM
Definition type_result.h:51
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_SEPARATED
Definition type_result.h:49
@ SCIP_SUCCESS
Definition type_result.h:58
@ SCIP_INFEASIBLE
Definition type_result.h:46
enum SCIP_Result SCIP_RESULT
Definition type_result.h:61
@ SCIP_PLUGINNOTFOUND
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_STAGE_TRANSFORMING
Definition type_set.h:46
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
type definitions for symmetry computations
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
struct SCIP_BdChgIdx SCIP_BDCHGIDX
Definition type_var.h:151
@ SCIP_VARSTATUS_FIXED
Definition type_var.h:54
@ SCIP_VARSTATUS_MULTAGGR
Definition type_var.h:56
@ SCIP_VARSTATUS_NEGATED
Definition type_var.h:57
@ SCIP_LOCKTYPE_MODEL
Definition type_var.h:141