Scippy

SCIP

Solving Constraint Integer Programs

cons_lop.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-2025 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/* uncomment for debug output: */
26/* #define SCIP_DEBUG */
27
28/**@file cons_lop.c
29 * @brief constraint handler for linear ordering constraints
30 * @author Marc Pfetsch
31 *
32 * We handle the following system of linear constraints:
33 * - \f$ x_{ij} + x_{ji} = 1 \f$ for \f$i < j\f$ (symmetry equations - added initially)
34 * - \f$ x_{ij} + x_{jk} + x_{ki} \leq 2 \f$ for \f$i < j, i < k, j \neq k\f$ (triangle inequalities - separated)
35 */
36
37/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
38
39#include "cons_lop.h"
40
41#include <assert.h>
42#include <string.h>
43
44
45/* constraint handler properties */
46#define CONSHDLR_NAME "lop"
47#define CONSHDLR_DESC "linear ordering constraint handler"
48#define CONSHDLR_SEPAPRIORITY 100 /**< priority of the constraint handler for separation */
49#define CONSHDLR_ENFOPRIORITY -100 /**< priority of the constraint handler for constraint enforcing */
50#define CONSHDLR_CHECKPRIORITY -100 /**< priority of the constraint handler for checking feasibility */
51#define CONSHDLR_SEPAFREQ 1 /**< frequency for separating cuts; zero means to separate only in the root node */
52#define CONSHDLR_PROPFREQ 1 /**< frequency for propagating domains; zero means only preprocessing propagation */
53#define CONSHDLR_EAGERFREQ 100 /**< frequency for using all instead of only the useful constraints in separation,
54 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */
55#define CONSHDLR_DELAYSEPA FALSE /**< should separation method be delayed, if other separators found cuts? */
56#define CONSHDLR_DELAYPROP FALSE /**< should propagation method be delayed, if other propagators found reductions? */
57#define CONSHDLR_NEEDSCONS TRUE /**< should the constraint handler be skipped, if no constraints are available? */
58
59#define CONSHDLR_PROP_TIMING SCIP_PROPTIMING_BEFORELP
60
61
62/** constraint data for linear ordering constraints */
63struct SCIP_ConsData
64{
65 int n; /**< number of elements */
66 SCIP_VAR*** vars; /**< variables */
67};
68
69
70/** separate symmetry equations and triangle inequalities */
71static
73 SCIP* scip, /**< SCIP pointer */
74 SCIP_CONSHDLR* conshdlr, /**< constraint handler */
75 int n, /**< number of elements */
76 SCIP_VAR*** vars, /**< n x n matrix of variables */
77 SCIP_SOL* sol, /**< solution to be separated */
78 int* ngen, /**< output: pointer to store number of added rows */
79 SCIP_Bool* cutoff /**< output: pointer to store whether we detected a cutoff */
80 )
81{
82 char s[SCIP_MAXSTRLEN];
83 int i;
84 int j;
85 int k;
86
87 assert( scip != NULL );
88 assert( vars != NULL );
89 assert( ngen != NULL );
90 assert( cutoff != NULL );
91
92 /* Consider all (i,j,k) with i < j, i < k, j != k; since the inequalities are symmetric under cyclic shifts, we can
93 * assume i to be the smallest index. */
94 *cutoff = FALSE;
95 for (i = 0; i < n && ! (*cutoff); ++i)
96 {
97 for (j = i+1; j < n && ! (*cutoff); ++j)
98 {
99 SCIP_Real valIJ;
100
101 valIJ = SCIPgetSolVal(scip, sol, vars[i][j]);
102
103 /* if symmetry equations are violated - should not be the case, if they are added in the beginning */
104 if ( ! SCIPisFeasEQ(scip, valIJ + SCIPgetSolVal(scip, sol, vars[j][i]), 1.0) )
105 {
106 SCIP_ROW *row;
107
108 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
109
110 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, TRUE) );
112 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
113 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
115#ifdef SCIP_DEBUG
117#endif
118 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
120 ++(*ngen);
121
122 if ( *cutoff )
123 break;
124 }
125
126 /* check triangle inequalities */
127 for (k = i+1; k < n; ++k)
128 {
129 SCIP_Real sum;
130
131 if ( k == j )
132 continue;
133
134 sum = valIJ + SCIPgetSolVal(scip, sol, vars[j][k]) + SCIPgetSolVal(scip, sol, vars[k][i]);
135
136 /* if sum - 2.0 > 0, i.e., the cut is violated */
137 if ( SCIPisEfficacious(scip, sum - 2.0) )
138 {
139 SCIP_ROW *row;
140
141 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "triangle#%d#%d#%d", i, j, k);
142
143 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, -SCIPinfinity(scip), 2.0, FALSE, FALSE, TRUE) );
145 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
146 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][k], 1.0) );
147 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][i], 1.0) );
149#ifdef SCIP_DEBUG
151#endif
152 SCIP_CALL( SCIPaddRow(scip, row, FALSE, cutoff) );
154 ++(*ngen);
155
156 if ( *cutoff )
157 break;
158 }
159 }
160 }
161 }
162
163 return SCIP_OKAY;
164}
165
166
167/** copy method for constraint handler plugins (called when SCIP copies plugins) */
168static
170{ /*lint --e{715}*/
171 assert( scip != NULL );
172 assert( conshdlr != NULL );
173 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
174 assert( valid != NULL );
175
176 /* call inclusion method of constraint handler */
178
179 *valid = TRUE;
180
181 return SCIP_OKAY;
182}
183
184/** frees specific constraint data */
185static
187{ /*lint --e{715}*/
188 int i;
189 int n;
190
191 assert( scip != NULL );
192 assert( conshdlr != NULL );
193 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
194 assert( cons != NULL );
195 assert( consdata != NULL);
196 assert( *consdata != NULL);
197 assert( (*consdata)->vars != NULL );
198
199 SCIPdebugMsg(scip, "deleting linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
200
201 n = (*consdata)->n;
202 for (i = 0; i < n; ++i)
203 SCIPfreeBlockMemoryArray(scip, &((*consdata)->vars[i]), n); /*lint !e866*/
204 SCIPfreeBlockMemoryArray(scip, &((*consdata)->vars), n);
205 SCIPfreeBlockMemory(scip, consdata);
206
207 return SCIP_OKAY;
208}
209
210/** deinitialization method of constraint handler (called before transformed problem is freed)
211 *
212 * We output the final linear ordering.
213 */
214static
216{ /*lint --e{715}*/
217 SCIP_SOL* sol;
218 int c;
219 int i;
220 int j;
221 int n;
222
223 assert( scip != NULL );
224 assert( conshdlr != NULL );
225 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
226
227 SCIPdebugMsg(scip, "exiting linear ordering constraint handler <%s>.\n", SCIPconshdlrGetName(conshdlr));
228
229 /* avoid output for subscips */
230 if ( SCIPgetSubscipDepth(scip) > 0 )
231 return SCIP_OKAY;
232
233 /* get best solution */
234 sol = SCIPgetBestSol(scip);
235 if ( sol == NULL )
236 return SCIP_OKAY;
237
238 /* loop through all constraints */
239 for (c = 0; c < nconss; ++c)
240 {
241 SCIP_CONSDATA* consdata;
242 SCIP_VAR*** vars;
243 int* outdeg;
244 int* indices;
245
246 assert( conss != NULL );
247 assert( conss[c] != NULL );
248 SCIPdebugMsg(scip, "solution for for linear ordering constraint <%s>.\n", SCIPconsGetName(conss[c]));
249
250 consdata = SCIPconsGetData(conss[c]);
251 assert( consdata != NULL );
252 assert( consdata->vars != NULL );
253 n = consdata->n;
254 vars = consdata->vars;
255
256 SCIP_CALL( SCIPallocBufferArray(scip, &outdeg, n) );
257 SCIP_CALL( SCIPallocBufferArray(scip, &indices, n) );
258
259 /* compute out-degree */
260 for (i = 0; i < n; ++i)
261 {
262 int deg = 0;
263 for (j = 0; j < n; ++j)
264 {
265 SCIP_Real val;
266
267 if (j == i)
268 continue;
269
270 val = SCIPgetSolVal(scip, sol, vars[i][j]);
271 assert( SCIPisFeasIntegral(scip, val) );
272 if ( val < 0.5 )
273 ++deg;
274 }
275 outdeg[i] = deg;
276 indices[i] = i;
277 }
278
279 /* sort such that degrees are non-decreasing */
280 SCIPsortIntInt(outdeg, indices, n);
281
282 /* output */
283 SCIPinfoMessage(scip, NULL, "\nFinal order of linear ordering constraint <%s>:\n", SCIPconsGetName(conss[c]));
284 for (i = 0; i < n; ++i)
285 SCIPinfoMessage(scip, NULL, "%d ", indices[i]);
286 SCIPinfoMessage(scip, NULL, "\n");
287
288 SCIPfreeBufferArray(scip, &indices);
289 SCIPfreeBufferArray(scip, &outdeg);
290 }
291
292 return SCIP_OKAY;
293}
294
295/** transforms constraint data into data belonging to the transformed problem */
296static
298{ /*lint --e{715}*/
299 SCIP_CONSDATA* consdata;
300 SCIP_CONSDATA* sourcedata;
301 int i;
302 int j;
303 int n;
304 char s[SCIP_MAXSTRLEN];
305
306 assert( scip != NULL );
307 assert( conshdlr != NULL );
308 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
309 assert( sourcecons != NULL );
310 assert( targetcons != NULL );
311
312 SCIPdebugMsg(scip, "transforming linear ordering constraint <%s>.\n", SCIPconsGetName(sourcecons) );
313
314 /* get data of original constraint */
315 sourcedata = SCIPconsGetData(sourcecons);
316 assert( sourcedata != NULL);
317
318 /* create constraint data */
319 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
320
321 n = sourcedata->n;
322 consdata->n = n;
323
324 /* transform variables */
325 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, n) );
326 for (i = 0; i < n; ++i)
327 {
328 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->vars[i]), n) ); /*lint !e866*/
329 for (j = 0; j < n; ++j)
330 {
331 if (j != i)
332 {
333 assert( sourcedata->vars[i][j] != NULL );
334 SCIP_CALL( SCIPgetTransformedVar(scip, sourcedata->vars[i][j], &(consdata->vars[i][j])) );
335 }
336 }
337 }
338
339 /* create constraint */
340 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "t_%s", SCIPconsGetName(sourcecons));
341
342 SCIP_CALL( SCIPcreateCons(scip, targetcons, s, conshdlr, consdata,
343 SCIPconsIsInitial(sourcecons), SCIPconsIsSeparated(sourcecons),
344 SCIPconsIsEnforced(sourcecons), SCIPconsIsChecked(sourcecons),
345 SCIPconsIsPropagated(sourcecons), SCIPconsIsLocal(sourcecons),
346 SCIPconsIsModifiable(sourcecons), SCIPconsIsDynamic(sourcecons),
347 SCIPconsIsRemovable(sourcecons), SCIPconsIsStickingAtNode(sourcecons)) );
348
349 return SCIP_OKAY;
350}
351
352/** LP initialization method of constraint handler */
353static
355{ /*lint --e{715}*/
356 char s[SCIP_MAXSTRLEN];
357 int c;
358 int ngen = 0;
359
360 assert( scip != NULL );
361 assert( conshdlr != NULL );
362 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
363 assert( infeasible != NULL );
364
365 *infeasible = FALSE;
366
367 /* loop through all constraints */
368 for (c = 0; c < nconss; ++c)
369 {
370 SCIP_CONSDATA* consdata;
371 SCIP_VAR*** vars;
372 int i;
373 int j;
374 int n;
375
376 assert( conss != NULL );
377 assert( conss[c] != NULL );
378 SCIPdebugMsg(scip, "adding initial rows for linear ordering constraint <%s>.\n", SCIPconsGetName(conss[c]));
379
380 consdata = SCIPconsGetData(conss[c]);
381 assert( consdata != NULL );
382 assert( consdata->vars != NULL );
383 n = consdata->n;
384 vars = consdata->vars;
385
386 /* add symmetry equation */
387 for (i = 0; i < n; ++i)
388 {
389 for (j = i+1; j < n; ++j)
390 {
391 SCIP_ROW* row;
392
393 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
394 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, FALSE) );
396 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
397 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
399#ifdef SCIP_DEBUG
401#endif
402 SCIP_CALL( SCIPaddRow(scip, row, FALSE, infeasible) );
404 ++ngen;
405
406 /* cannot handle infeasible case here - just exit */
407 if ( *infeasible )
408 return SCIP_OKAY;
409 }
410 }
411 }
412 SCIPdebugMsg(scip, "added %d equations.\n", ngen);
413
414 return SCIP_OKAY;
415}
416
417/** separation method of constraint handler for LP solutions */
418static
420{ /*lint --e{715}*/
421 int ngen = 0;
422 int c;
423
424 assert( scip != NULL );
425 assert( conshdlr != NULL );
426 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
427 assert( conss != NULL );
428 assert( result != NULL );
429
430 *result = SCIP_DIDNOTRUN;
431
432 /* loop through all constraints */
433 for (c = 0; c < nconss; ++c)
434 {
435 SCIP_CONSDATA* consdata;
436 SCIP_CONS* cons;
437 SCIP_Bool cutoff;
438
439 cons = conss[c];
440 assert( cons != NULL );
441 SCIPdebugMsg(scip, "separating LP solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
442
443 consdata = SCIPconsGetData(cons);
444 assert( consdata != NULL );
445
446 *result = SCIP_DIDNOTFIND;
447 SCIP_CALL( LOPseparate(scip, conshdlr, consdata->n, consdata->vars, NULL, &ngen, &cutoff) );
448 if ( cutoff )
449 {
450 *result = SCIP_CUTOFF;
451 return SCIP_OKAY;
452 }
453 }
454 if ( ngen > 0 )
455 *result = SCIP_SEPARATED;
456 SCIPdebugMsg(scip, "separated %d cuts.\n", ngen);
457
458 return SCIP_OKAY;
459}
460
461/** separation method of constraint handler for arbitrary primal solutions */
462static
464{ /*lint --e{715}*/
465 int ngen = 0;
466 int c;
467
468 assert( scip != NULL );
469 assert( conshdlr != NULL );
470 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
471 assert( conss != NULL );
472 assert( result != NULL );
473
474 *result = SCIP_DIDNOTRUN;
475
476 /* loop through all constraints */
477 for (c = 0; c < nconss; ++c)
478 {
479 SCIP_CONSDATA* consdata;
480 SCIP_CONS* cons;
481 SCIP_Bool cutoff;
482
483 cons = conss[c];
484 assert( cons != NULL );
485 SCIPdebugMsg(scip, "separating solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
486
487 consdata = SCIPconsGetData(cons);
488 assert( consdata != NULL );
489
490 *result = SCIP_DIDNOTFIND;
491 SCIP_CALL( LOPseparate(scip, conshdlr, consdata->n, consdata->vars, sol, &ngen, &cutoff) );
492 if ( cutoff )
493 {
494 *result = SCIP_CUTOFF;
495 return SCIP_OKAY;
496 }
497 }
498 if ( ngen > 0 )
499 *result = SCIP_SEPARATED;
500
501 return SCIP_OKAY;
502}
503
504/** constraint enforcing method of constraint handler for LP solutions */
505static
507{ /*lint --e{715}*/
508 char s[SCIP_MAXSTRLEN];
509 int ngen = 0;
510 int c;
511
512 assert( scip != NULL );
513 assert( conshdlr != NULL );
514 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
515 assert( conss != NULL );
516 assert( result != NULL );
517
518 *result = SCIP_DIDNOTRUN;
519
520 /* loop through all constraints */
521 for (c = 0; c < nconss; ++c)
522 {
523 SCIP_CONSDATA* consdata;
524 SCIP_CONS* cons;
525 SCIP_VAR*** vars;
526 int i;
527 int j;
528 int k;
529 int n;
530
531 cons = conss[c];
532 assert( cons != NULL );
533 SCIPdebugMsg(scip, "enforcing lp solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
534
535 consdata = SCIPconsGetData(cons);
536 assert( consdata != NULL );
537
538 n = consdata->n;
539 vars = consdata->vars;
540 assert( vars != NULL );
541
542 for (i = 0; i < n; ++i)
543 {
544 for (j = i + 1; j < n; ++j)
545 {
546 SCIP_Real valIJ;
547
548 valIJ = SCIPgetSolVal(scip, NULL, vars[i][j]);
549
550 /* if symmetry equations are violated - should not be the case, if they are added in the beginning */
551 if ( ! SCIPisFeasEQ(scip, 1.0 - valIJ, SCIPgetSolVal(scip, NULL, vars[j][i])) )
552 {
553 SCIP_ROW *row;
554 SCIP_Bool infeasible;
555
556 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "sym#%d#%d", i, j);
557
558 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, 1.0, 1.0, FALSE, FALSE, TRUE) );
560 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
561 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][i], 1.0) );
563#ifdef SCIP_DEBUG
565#endif
566 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
568 ++ngen;
569
570 if ( infeasible )
571 {
572 *result = SCIP_CUTOFF;
573 return SCIP_OKAY;
574 }
575 }
576
577 /* enforce triangle inequalities */
578 for (k = i + 1; k < n; ++k)
579 {
580 SCIP_Real sum;
581
582 if ( k == j )
583 continue;
584
585 sum = valIJ + SCIPgetSolVal(scip, NULL, vars[j][k]) + SCIPgetSolVal(scip, NULL, vars[k][i]);
586
587 /* if sum > 2.0, i.e., the cut is violated */
588 if ( SCIPisFeasGT(scip, sum, 2.0) ) /* this is the only difference to the separation call */
589 {
590 SCIP_ROW *row;
591 SCIP_Bool infeasible;
592
593 (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "triangle#%d#%d#%d", i, j, k);
594
595 SCIP_CALL( SCIPcreateEmptyRowConshdlr(scip, &row, conshdlr, s, -SCIPinfinity(scip), 2.0, FALSE, FALSE, TRUE) );
597 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[i][j], 1.0) );
598 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[j][k], 1.0) );
599 SCIP_CALL( SCIPaddVarToRow(scip, row, vars[k][i], 1.0) );
601#ifdef SCIP_DEBUG
603#endif
604 SCIP_CALL( SCIPaddRow(scip, row, FALSE, &infeasible) );
606 ++ngen;
607
608 if ( infeasible )
609 {
610 *result = SCIP_CUTOFF;
611 return SCIP_OKAY;
612 }
613 }
614 }
615 }
616 }
617
618 if ( ngen > 0 )
619 {
620 *result = SCIP_SEPARATED;
621 return SCIP_OKAY;
622 }
623
624 }
625 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
626 *result = SCIP_FEASIBLE;
627
628 return SCIP_OKAY;
629}
630
631/** constraint enforcing method of constraint handler for pseudo solutions */
632static
634{ /*lint --e{715}*/
635 int c;
636
637 assert( scip != NULL );
638 assert( conshdlr != NULL );
639 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
640 assert( conss != NULL );
641 assert( result != NULL );
642
643 /* loop through all constraints */
644 for (c = 0; c < nconss; ++c)
645 {
646 SCIP_CONSDATA* consdata;
647 SCIP_CONS* cons;
648 SCIP_VAR*** vars;
649 int i;
650 int j;
651 int k;
652 int n;
653
654 cons = conss[c];
655 assert( cons != NULL );
656 SCIPdebugMsg(scip, "enforcing pseudo solution for linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
657
658 consdata = SCIPconsGetData(cons);
659 assert( consdata != NULL );
660 assert( consdata->vars != NULL );
661 vars = consdata->vars;
662 n = consdata->n;
663
664 /* check triangle inequalities */
665 for (i = 0; i < n; ++i)
666 {
667 for (j = i + 1; j < n; ++j)
668 {
669 SCIP_Bool oneIJ;
670 SCIP_Bool oneJI;
671
672 /* the priorities should ensure that the solution is integral */
673 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[i][j])) );
674 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[j][i])) );
675
676 oneIJ = SCIPgetSolVal(scip, NULL, vars[i][j]) > 0.5 ? TRUE : FALSE;
677 oneJI = SCIPgetSolVal(scip, NULL, vars[j][i]) > 0.5 ? TRUE : FALSE;
678
679 if ( oneIJ == oneJI )
680 {
681 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated equation).\n", SCIPconsGetName(cons));
682 *result = SCIP_INFEASIBLE;
683 return SCIP_OKAY;
684 }
685
686 for (k = i + 1; k < n; ++k)
687 {
688 SCIP_Bool oneJK;
689 SCIP_Bool oneKI;
690
691 if ( k == j )
692 continue;
693
694 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[j][k])) );
695 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, vars[k][i])) );
696
697 oneJK = SCIPgetSolVal(scip, NULL, vars[j][k]) > 0.5 ? TRUE : FALSE;
698 oneKI = SCIPgetSolVal(scip, NULL, vars[k][i]) > 0.5 ? TRUE : FALSE;
699
700 /* if triangle inequality is violated */
701 if ( oneIJ && oneJK && oneKI )
702 {
703 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated triangle ineq.).\n", SCIPconsGetName(cons));
704 *result = SCIP_INFEASIBLE;
705 return SCIP_OKAY;
706 }
707 }
708 }
709 }
710 }
711 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
712 *result = SCIP_FEASIBLE;
713
714 return SCIP_OKAY;
715}
716
717/** feasibility check method of constraint handler for integral solutions */
718static
720{ /*lint --e{715}*/
721 int c;
722
723 assert( scip != NULL );
724 assert( conshdlr != NULL );
725 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
726 assert( conss != NULL );
727 assert( result != NULL );
728
729 /* loop through all constraints */
730 for (c = 0; c < nconss; ++c)
731 {
732 SCIP_CONSDATA* consdata;
733 SCIP_CONS* cons;
734 SCIP_VAR*** vars;
735 int i;
736 int j;
737 int k;
738 int n;
739
740 cons = conss[c];
741 assert( cons != NULL );
742 SCIPdebugMsg(scip, "checking linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
743
744 consdata = SCIPconsGetData(cons);
745 assert( consdata != NULL );
746 assert( consdata->vars != NULL );
747 vars = consdata->vars;
748 n = consdata->n;
749
750 /* check triangle inequalities and symmetry equations */
751 for (i = 0; i < n; ++i)
752 {
753 for (j = i + 1; j < n; ++j)
754 {
755 SCIP_Bool oneIJ;
756 SCIP_Bool oneJI;
757
758 /* the priorities should ensure that the solution is integral */
759 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[i][j])) );
760 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[j][i])) );
761
762 oneIJ = SCIPgetSolVal(scip, sol, vars[i][j]) > 0.5 ? TRUE : FALSE;
763 oneJI = SCIPgetSolVal(scip, sol, vars[j][i]) > 0.5 ? TRUE : FALSE;
764
765 /* check symmetry equations */
766 if ( oneIJ == oneJI )
767 {
768 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated equation).\n", SCIPconsGetName(cons));
769 *result = SCIP_INFEASIBLE;
770 if( printreason )
771 {
772 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
773 SCIPinfoMessage(scip, NULL, "violation: symmetry equation violated <%s> = %.15g and <%s> = %.15g\n",
774 SCIPvarGetName(vars[i][j]), SCIPgetSolVal(scip, sol, vars[i][j]),
775 SCIPvarGetName(vars[j][i]), SCIPgetSolVal(scip, sol, vars[j][i]));
776 }
777 return SCIP_OKAY;
778 }
779
780 for (k = i + 1; k < n; ++k)
781 {
782 SCIP_Bool oneJK;
783 SCIP_Bool oneKI;
784
785 if ( k == j )
786 continue;
787
788 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[j][k])) );
789 assert( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, sol, vars[k][i])) );
790
791 oneJK = SCIPisGT(scip, SCIPgetSolVal(scip, sol, vars[j][k]), 0.5);
792 oneKI = SCIPisGT(scip, SCIPgetSolVal(scip, sol, vars[k][i]), 0.5);
793
794 /* if triangle inequality is violated */
795 if ( oneIJ && oneJK && oneKI )
796 {
797 SCIPdebugMsg(scip, "constraint <%s> infeasible (violated triangle ineq.).\n", SCIPconsGetName(cons));
798 *result = SCIP_INFEASIBLE;
799 if( printreason )
800 {
801 SCIP_CALL( SCIPprintCons(scip, cons, NULL) );
803 "violation: triangle inequality violated <%s> = %.15g, <%s> = %.15g, <%s> = %.15g\n",
804 SCIPvarGetName(vars[i][j]), SCIPgetSolVal(scip, sol, vars[i][j]),
805 SCIPvarGetName(vars[j][k]), SCIPgetSolVal(scip, sol, vars[j][k]),
806 SCIPvarGetName(vars[k][i]), SCIPgetSolVal(scip, sol, vars[k][i]));
807 }
808 return SCIP_OKAY;
809 }
810 }
811 }
812 }
813 }
814 SCIPdebugMsg(scip, "all linear ordering constraints are feasible.\n");
815 *result = SCIP_FEASIBLE;
816
817 return SCIP_OKAY;
818}
819
820/** domain propagation method of constraint handler */
821static
823{ /*lint --e{715}*/
824 int c;
825 int ngen = 0;
826
827 assert( scip != NULL );
828 assert( conshdlr != NULL );
829 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
830 assert( conss != NULL );
831 assert( result != NULL );
832
833 *result = SCIP_DIDNOTRUN;
834
835 /* loop through all constraints */
836 for (c = 0; c < nconss; ++c)
837 {
838 SCIP_CONSDATA* consdata;
839 SCIP_CONS* cons;
840 SCIP_VAR*** vars;
841 int i;
842 int j;
843 int k;
844 int n;
845
846 cons = conss[c];
847 assert( cons != NULL );
848 SCIPdebugMsg(scip, "propagating linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
849
850 *result = SCIP_DIDNOTFIND;
851
852 consdata = SCIPconsGetData(cons);
853 assert( consdata != NULL );
854 assert( consdata->vars != NULL );
855
856 vars = consdata->vars;
857 n = consdata->n;
858
859 /* check triangle inequalities */
860 for (i = 0; i < n; ++i)
861 {
862 for (j = i + 1; j < n; ++j)
863 {
864 SCIP_Bool infeasible;
865 SCIP_Bool tightened;
866
867 /* for consistency make sure that the complementarity constraints are satisfied */
868
869 /* if x[i][j] == 1 then x[j][i] = 0 */
870 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
871 {
872 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][i], FALSE, cons, i*n + j, &infeasible, &tightened) );
873 if ( infeasible )
874 {
875 SCIPdebugMsg(scip, " -> node infeasible.\n");
877 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
878 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][i]) );
880 *result = SCIP_CUTOFF;
881 return SCIP_OKAY;
882 }
883 if ( tightened )
884 ++ngen;
885 }
886
887 /* if x[i][j] == 0 then x[j][i] = 1 */
888 if ( SCIPvarGetUbLocal(vars[i][j]) < 0.5 )
889 {
890 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][i], TRUE, cons, i*n + j, &infeasible, &tightened) );
891 if ( infeasible )
892 {
893 SCIPdebugMsg(scip, " -> node infeasible.\n");
895 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
896 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][i]) );
898 *result = SCIP_CUTOFF;
899 return SCIP_OKAY;
900 }
901 if ( tightened )
902 ++ngen;
903 }
904
905 /* check whether triangle inequality allows to fix variables */
906 for (k = i + 1; k < n; ++k)
907 {
908 if ( k == j )
909 continue;
910
911 if ( SCIPvarGetLbLocal(vars[i][j]) > 0.5 )
912 {
913 if ( SCIPvarGetLbLocal(vars[j][k]) > 0.5 )
914 {
915 /* if x[i][j] == 1 and x[j][k] == 1 then x[k][i] = 0 */
916 SCIP_CALL( SCIPinferBinvarCons(scip, vars[k][i], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
917 if ( infeasible )
918 {
919 SCIPdebugMsg(scip, " -> node infeasible.\n");
921 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
922 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
923 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
925 *result = SCIP_CUTOFF;
926 return SCIP_OKAY;
927 }
928 if ( tightened )
929 ++ngen;
930 }
931
932 if ( SCIPvarGetLbLocal(vars[k][i]) > 0.5 )
933 {
934 /* if x[k][i] == 1 and x[i][j] = 1 then x[j][k] = 0 */
935 SCIP_CALL( SCIPinferBinvarCons(scip, vars[j][k], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
936 if ( infeasible )
937 {
938 SCIPdebugMsg(scip, " -> node infeasible.\n");
940 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
941 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
942 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
944 *result = SCIP_CUTOFF;
945 return SCIP_OKAY;
946 }
947 if ( tightened )
948 ++ngen;
949 }
950 }
951
952 /* if x[j][k] == 1 and x[k][i] == 1 then x[i][j] = 0 */
953 if ( SCIPvarGetLbLocal(vars[j][k]) > 0.5 && SCIPvarGetLbLocal(vars[k][i]) > 0.5 )
954 {
955 SCIP_CALL( SCIPinferBinvarCons(scip, vars[i][j], FALSE, cons, n*n + i*n*n + j*n + k, &infeasible, &tightened) );
956 if ( infeasible )
957 {
958 SCIPdebugMsg(scip, " -> node infeasible.\n");
960 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[i][j]) );
961 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[j][k]) );
962 SCIP_CALL( SCIPaddConflictBinvar(scip, vars[k][i]) );
964 *result = SCIP_CUTOFF;
965 return SCIP_OKAY;
966 }
967 if ( tightened )
968 ++ngen;
969 }
970
971 /* all other implications occur with other indices i, j, k */
972 }
973 }
974 }
975 }
976 SCIPdebugMsg(scip, "propagated %d domains.\n", ngen);
977 if ( ngen > 0 )
978 *result = SCIP_REDUCEDDOM;
979
980 return SCIP_OKAY;
981}
982
983/** propagation conflict resolving method of constraint handler */
984static
986{ /*lint --e{715}*/
987 SCIP_CONSDATA* consdata;
988 SCIP_VAR*** vars;
989 int n;
990 int nsqrd;
991
992 assert( scip != NULL );
993 assert( conshdlr != NULL );
994 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
995 assert( cons != NULL );
996 assert( infervar != NULL );
997 assert( bdchgidx != NULL );
998 assert( result != NULL );
999
1000 SCIPdebugMsg(scip, "Propagation resolution of constraint <%s>.\n", SCIPconsGetName(cons));
1001 *result = SCIP_DIDNOTFIND;
1002
1003 consdata = SCIPconsGetData(cons);
1004 assert( consdata != NULL);
1005 assert( consdata->vars != NULL );
1006
1007 n = consdata->n;
1008 nsqrd = n * n;
1009 vars = consdata->vars;
1010
1011 assert( 0 <= inferinfo && inferinfo < n*n + n*n*n );
1012
1013 /* if the conflict came from an equation */
1014 if ( inferinfo < nsqrd )
1015 {
1016 int index1;
1017 int index2;
1018
1019 index1 = inferinfo/n;
1020 index2 = inferinfo % n;
1021 assert( 0 <= index1 && index1 < n );
1022 assert( 0 <= index2 && index2 < n );
1023 assert( vars[index2][index1] == infervar );
1024
1025 /* if the variable was fixed to 0 */
1026 if ( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 )
1027 {
1028 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = 1.\n", index2, index1, index1, index2);
1029 /* the reason was that x[i][j] was fixed to 1 */
1030 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
1031 *result = SCIP_SUCCESS;
1032 return SCIP_OKAY;
1033 }
1034
1035 /* if the variable was fixed to 1 */
1036 if ( SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, FALSE) < 0.5 && SCIPgetVarLbAtIndex(scip, infervar, bdchgidx, TRUE) > 0.5 )
1037 {
1038 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 1 was x[%d][%d] = 0.\n", index2, index1, index1, index2);
1039 /* the reason was that x[i][j] was fixed to 0 */
1040 SCIP_CALL( SCIPaddConflictUb(scip, vars[index1][index2], bdchgidx) );
1041 *result = SCIP_SUCCESS;
1042 return SCIP_OKAY;
1043 }
1044 }
1045 else
1046 {
1047 /* otherwise the conflict came from a triangle inequality */
1048 int index1;
1049 int index2;
1050 int index3;
1051
1052 index1 = (inferinfo - nsqrd) / nsqrd;
1053 index2 = (inferinfo - nsqrd - index1 * nsqrd) / n;
1054 index3 = (inferinfo - nsqrd) % n;
1055
1056 assert( 0 <= index1 && index1 < n );
1057 assert( 0 <= index2 && index2 < n );
1058 assert( 0 <= index3 && index3 < n );
1059 assert( index1 < index2 );
1060 assert( index1 < index3 );
1061 assert( index2 != index3 );
1062
1063 if ( vars[index3][index1] == infervar )
1064 {
1065 /* the variable should have been fixed to 0 */
1066 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
1067
1068 /* the reason was that x[index1][index2] and x[index2][index3] were fixed to 1 */
1069 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index3, index1, index1, index2, index2, index3);
1070 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
1071 SCIP_CALL( SCIPaddConflictLb(scip, vars[index2][index3], bdchgidx) );
1072 *result = SCIP_SUCCESS;
1073 }
1074 else if ( vars[index2][index3] == infervar )
1075 {
1076 /* the variable should have been fixed to 0 */
1077 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
1078
1079 /* the reason was that x[index1][index2] and x[index3][index1] were fixed to 1 */
1080 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index2, index3, index1, index2, index3, index1);
1081 SCIP_CALL( SCIPaddConflictLb(scip, vars[index1][index2], bdchgidx) );
1082 SCIP_CALL( SCIPaddConflictLb(scip, vars[index3][index1], bdchgidx) );
1083 *result = SCIP_SUCCESS;
1084 }
1085 else if ( vars[index1][index2] == infervar )
1086 {
1087 /* the variable should have been fixed to 0 */
1088 assert( SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, FALSE) > 0.5 && SCIPgetVarUbAtIndex(scip, infervar, bdchgidx, TRUE) < 0.5 );
1089
1090 /* the reason was that x[index2][index3] and x[index3][index1] were fixed to 1 */
1091 SCIPdebugMsg(scip, " -> reason for x[%d][%d] == 0 was x[%d][%d] = x[%d][%d] = 1.\n", index1, index2, index2, index3, index3, index1);
1092 SCIP_CALL( SCIPaddConflictLb(scip, vars[index2][index3], bdchgidx) );
1093 SCIP_CALL( SCIPaddConflictLb(scip, vars[index3][index1], bdchgidx) );
1094 *result = SCIP_SUCCESS;
1095 }
1096 else
1097 {
1098 /* should not happen */
1099 SCIPABORT();
1100 }
1101 }
1102
1103 return SCIP_OKAY;
1104}
1105
1106/** variable rounding lock method of constraint handler */
1107static
1109{ /*lint --e{715}*/
1110 int i;
1111 int j;
1112 SCIP_CONSDATA* consdata;
1113 SCIP_VAR*** vars;
1114 int n;
1115
1116 assert( scip != NULL );
1117 assert( conshdlr != NULL );
1118 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1119 assert( cons != NULL );
1120
1121 SCIPdebugMsg(scip, "Locking linear ordering constraint <%s>.\n", SCIPconsGetName(cons));
1122
1123 /* get data of constraint */
1124 consdata = SCIPconsGetData(cons);
1125 assert( consdata != NULL);
1126 assert( consdata->vars != NULL );
1127 n = consdata->n;
1128 vars = consdata->vars;
1129
1130 for (i = 0; i < n; ++i)
1131 {
1132 for (j = 0; j < n; ++j)
1133 {
1134 if ( i != j )
1135 {
1136 /* the constraint may be violated in any way */
1137 SCIP_CALL( SCIPaddVarLocksType(scip, vars[i][j], SCIP_LOCKTYPE_MODEL, nlockspos + nlocksneg, nlockspos + nlocksneg) );
1138 }
1139 }
1140 }
1141
1142 return SCIP_OKAY;
1143}
1144
1145/** constraint display method of constraint handler */
1146static
1148{ /*lint --e{715}*/
1149 SCIP_CONSDATA* consdata;
1150 SCIP_VAR*** vars;
1151 int i;
1152 int j;
1153 int n;
1154
1155 assert( scip != NULL );
1156 assert( conshdlr != NULL );
1157 assert( strcmp(SCIPconshdlrGetName(conshdlr), CONSHDLR_NAME) == 0 );
1158 assert( cons != NULL );
1159
1160 consdata = SCIPconsGetData(cons);
1161 assert( consdata != NULL );
1162 assert( consdata->vars != NULL );
1163 n = consdata->n;
1164 vars = consdata->vars;
1165
1166 SCIPinfoMessage(scip, file, "LOP[");
1167 for (i = 0; i < n; ++i)
1168 {
1169 if ( i > 0 )
1170 SCIPinfoMessage(scip, file, ", ");
1171 SCIPinfoMessage(scip, file, "(");
1172 for (j = 0; j < n; ++j)
1173 {
1174 if ( j != i )
1175 {
1176 if ( j > 0 && (i > 0 || j > 1) )
1177 SCIPinfoMessage(scip, file, ",");
1178 SCIPinfoMessage(scip, file, "%s", SCIPvarGetName(vars[i][j]));
1179 }
1180 }
1181 SCIPinfoMessage(scip, file, ")");
1182 }
1183 SCIPinfoMessage(scip, file, "]\n");
1184
1185 return SCIP_OKAY;
1186}
1187
1188/** constraint copying method of constraint handler */
1189static
1191{ /*lint --e{715}*/
1192 SCIP_CONSDATA* sourcedata;
1193 SCIP_VAR*** sourcevars;
1194 SCIP_VAR*** vars;
1195 int i;
1196 int j;
1197 int n;
1198
1199 assert( scip != NULL );
1200 assert( sourceconshdlr != NULL );
1201 assert( strcmp(SCIPconshdlrGetName(sourceconshdlr), CONSHDLR_NAME) == 0 );
1202 assert( cons != NULL );
1203 assert( sourcescip != NULL );
1204 assert( sourcecons != NULL );
1205 assert( varmap != NULL );
1206 assert( valid != NULL );
1207
1208 *valid = TRUE;
1209
1210 SCIPdebugMsg(scip, "Copying method for linear ordering constraint handler.\n");
1211
1212 sourcedata = SCIPconsGetData(sourcecons);
1213 assert( sourcedata != NULL );
1214
1215 n = sourcedata->n;
1216 sourcevars = sourcedata->vars;
1217 assert( sourcevars != NULL );
1218
1219 SCIP_CALL( SCIPallocBufferArray(scip, &vars, n) );
1220 BMSclearMemoryArray(vars, n);
1221
1222 for (i = 0; i < n; ++i)
1223 {
1224 SCIP_CALL( SCIPallocBufferArray(scip, &(vars[i]), n) ); /*lint !e866*/
1225
1226 for (j = 0; j < n && *valid; ++j)
1227 {
1228 if ( i != j )
1229 {
1230 SCIP_CALL( SCIPgetVarCopy(sourcescip, scip, sourcevars[i][j], &vars[i][j], varmap, consmap, global, valid) );
1231 assert( !(*valid) || vars[i][j] != NULL );
1232 }
1233 }
1234 }
1235
1236 if ( *valid )
1237 {
1238 /* create copied constraint */
1239 if ( name == 0 )
1240 name = SCIPconsGetName(sourcecons);
1241
1242 SCIP_CALL( SCIPcreateConsLOP(scip, cons, name, n, vars,
1243 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode) );
1244 }
1245
1246 /* free memory in reverse order */
1247 for (i = n-1; i >= 0; --i)
1248 SCIPfreeBufferArrayNull(scip, &vars[i]);
1249 SCIPfreeBufferArray(scip, &vars);
1250
1251 return SCIP_OKAY;
1252}
1253
1254/** creates the handler for linear ordering constraints and includes it in SCIP */
1256 SCIP* scip /**< SCIP data structure */
1257 )
1258{
1259 SCIP_CONSHDLR* conshdlr = NULL;
1260
1261 /* include constraint handler */
1264 consEnfolpLOP, consEnfopsLOP, consCheckLOP, consLockLOP, NULL) );
1265 assert( conshdlr != NULL );
1266
1267 SCIP_CALL( SCIPsetConshdlrDelete(scip, conshdlr, consDeleteLOP) );
1268 SCIP_CALL( SCIPsetConshdlrExit(scip, conshdlr, consExitLOP) );
1269 SCIP_CALL( SCIPsetConshdlrCopy(scip, conshdlr, conshdlrCopyLOP, consCopyLOP) );
1270 SCIP_CALL( SCIPsetConshdlrTrans(scip, conshdlr, consTransLOP) );
1271 SCIP_CALL( SCIPsetConshdlrInitlp(scip, conshdlr, consInitlpLOP) );
1272 SCIP_CALL( SCIPsetConshdlrSepa(scip, conshdlr, consSepalpLOP, consSepasolLOP,
1274 SCIP_CALL( SCIPsetConshdlrProp(scip, conshdlr, consPropLOP, CONSHDLR_PROPFREQ,
1276 SCIP_CALL( SCIPsetConshdlrResprop(scip, conshdlr, consRespropLOP) );
1277 SCIP_CALL( SCIPsetConshdlrPrint(scip, conshdlr, consPrintLOP) );
1278
1279 return SCIP_OKAY;
1280}
1281
1282/** creates and captures a linear ordering constraint */
1284 SCIP* scip, /**< SCIP data structure */
1285 SCIP_CONS** cons, /**< pointer to hold the created constraint */
1286 const char* name, /**< name of constraint */
1287 int n, /**< number of elements */
1288 SCIP_VAR*** vars, /**< n x n matrix of binary variables */
1289 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */
1290 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */
1291 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */
1292 SCIP_Bool check, /**< should the constraint be checked for feasibility? */
1293 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */
1294 SCIP_Bool local, /**< is constraint only valid locally? */
1295 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */
1296 SCIP_Bool dynamic, /**< is constraint subject to aging? */
1297 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */
1298 SCIP_Bool stickingatnode /**< should the constraint always be kept at the node where it was added, even
1299 * if it may be moved to a more global node? */
1300 )
1301{
1302 SCIP_CONSHDLR* conshdlr;
1303 SCIP_CONSDATA* consdata;
1304 int i;
1305 int j;
1306
1307 /* find the linear ordering constraint handler */
1308 conshdlr = SCIPfindConshdlr(scip, CONSHDLR_NAME);
1309 if (conshdlr == NULL)
1310 {
1311 SCIPerrorMessage("linear ordering constraint handler not found\n");
1312 return SCIP_PLUGINNOTFOUND;
1313 }
1314
1315 /* create constraint data */
1316 SCIP_CALL( SCIPallocBlockMemory(scip, &consdata) );
1317
1318 consdata->n = n;
1319 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &consdata->vars, n) );
1320 for (i = 0; i < n; ++i)
1321 {
1322 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(consdata->vars[i]), n) ); /*lint !e866*/
1323 for (j = 0; j < n; ++j)
1324 {
1325 if ( j != i )
1326 {
1327 assert( vars[i][j] != NULL );
1328 consdata->vars[i][j] = vars[i][j];
1329 }
1330 }
1331 }
1332
1333 /* create constraint */
1334 SCIP_CALL( SCIPcreateCons(scip, cons, name, conshdlr, consdata, initial, separate, enforce, check, propagate,
1335 local, modifiable, dynamic, removable, stickingatnode) );
1336
1337 return SCIP_OKAY;
1338}
static SCIP_DECL_CONSRESPROP(consRespropLOP)
Definition: cons_lop.c:985
SCIP_RETCODE SCIPincludeConshdlrLOP(SCIP *scip)
Definition: cons_lop.c:1255
#define CONSHDLR_NEEDSCONS
Definition: cons_lop.c:57
#define CONSHDLR_SEPAFREQ
Definition: cons_lop.c:51
#define CONSHDLR_CHECKPRIORITY
Definition: cons_lop.c:50
static SCIP_DECL_CONSENFOPS(consEnfopsLOP)
Definition: cons_lop.c:633
#define CONSHDLR_DESC
Definition: cons_lop.c:47
#define CONSHDLR_PROP_TIMING
Definition: cons_lop.c:59
static SCIP_DECL_CONSENFOLP(consEnfolpLOP)
Definition: cons_lop.c:506
static SCIP_DECL_CONSEXIT(consExitLOP)
Definition: cons_lop.c:215
static SCIP_DECL_CONSINITLP(consInitlpLOP)
Definition: cons_lop.c:354
SCIP_RETCODE SCIPcreateConsLOP(SCIP *scip, SCIP_CONS **cons, const char *name, int n, SCIP_VAR ***vars, 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: cons_lop.c:1283
#define CONSHDLR_SEPAPRIORITY
Definition: cons_lop.c:48
static SCIP_DECL_CONSPROP(consPropLOP)
Definition: cons_lop.c:822
static SCIP_DECL_CONSTRANS(consTransLOP)
Definition: cons_lop.c:297
static SCIP_DECL_CONSCOPY(consCopyLOP)
Definition: cons_lop.c:1190
static SCIP_DECL_CONSHDLRCOPY(conshdlrCopyLOP)
Definition: cons_lop.c:169
static SCIP_RETCODE LOPseparate(SCIP *scip, SCIP_CONSHDLR *conshdlr, int n, SCIP_VAR ***vars, SCIP_SOL *sol, int *ngen, SCIP_Bool *cutoff)
Definition: cons_lop.c:72
#define CONSHDLR_PROPFREQ
Definition: cons_lop.c:52
static SCIP_DECL_CONSSEPALP(consSepalpLOP)
Definition: cons_lop.c:419
#define CONSHDLR_EAGERFREQ
Definition: cons_lop.c:53
static SCIP_DECL_CONSPRINT(consPrintLOP)
Definition: cons_lop.c:1147
#define CONSHDLR_ENFOPRIORITY
Definition: cons_lop.c:49
#define CONSHDLR_DELAYSEPA
Definition: cons_lop.c:55
#define CONSHDLR_NAME
Definition: cons_lop.c:46
static SCIP_DECL_CONSSEPASOL(consSepasolLOP)
Definition: cons_lop.c:463
#define CONSHDLR_DELAYPROP
Definition: cons_lop.c:56
static SCIP_DECL_CONSCHECK(consCheckLOP)
Definition: cons_lop.c:719
static SCIP_DECL_CONSLOCK(consLockLOP)
Definition: cons_lop.c:1108
static SCIP_DECL_CONSDELETE(consDeleteLOP)
Definition: cons_lop.c:186
constraint handler for linear ordering constraints
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIPABORT()
Definition: def.h:327
#define SCIP_CALL(x)
Definition: def.h:355
int SCIPgetSubscipDepth(SCIP *scip)
Definition: scip_copy.c:2588
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
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip_message.c:208
#define SCIPdebugMsg
Definition: scip_message.h:78
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPaddConflictBinvar(SCIP *scip, SCIP_VAR *var)
SCIP_RETCODE SCIPanalyzeConflictCons(SCIP *scip, SCIP_CONS *cons, SCIP_Bool *success)
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 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 SCIPsetConshdlrDelete(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSDELETE((*consdelete)))
Definition: scip_cons.c:578
const char * SCIPconshdlrGetName(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4316
SCIP_RETCODE SCIPsetConshdlrExit(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSEXIT((*consexit)))
Definition: scip_cons.c:420
SCIP_RETCODE SCIPsetConshdlrCopy(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), SCIP_DECL_CONSCOPY((*conscopy)))
Definition: scip_cons.c:347
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip_cons.c:940
SCIP_RETCODE SCIPsetConshdlrInitlp(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSINITLP((*consinitlp)))
Definition: scip_cons.c:624
SCIP_RETCODE SCIPsetConshdlrTrans(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSTRANS((*constrans)))
Definition: scip_cons.c:601
SCIP_RETCODE SCIPsetConshdlrResprop(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSRESPROP((*consresprop)))
Definition: scip_cons.c:647
SCIP_RETCODE SCIPsetConshdlrPrint(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_DECL_CONSPRINT((*consprint)))
Definition: scip_cons.c:785
SCIP_CONSDATA * SCIPconsGetData(SCIP_CONS *cons)
Definition: cons.c:8419
SCIP_Bool SCIPconsIsDynamic(SCIP_CONS *cons)
Definition: cons.c:8648
SCIP_Bool SCIPconsIsInitial(SCIP_CONS *cons)
Definition: cons.c:8558
SCIP_RETCODE SCIPprintCons(SCIP *scip, SCIP_CONS *cons, FILE *file)
Definition: scip_cons.c:2536
SCIP_Bool SCIPconsIsChecked(SCIP_CONS *cons)
Definition: cons.c:8588
SCIP_Bool SCIPconsIsEnforced(SCIP_CONS *cons)
Definition: cons.c:8578
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:8608
SCIP_Bool SCIPconsIsLocal(SCIP_CONS *cons)
Definition: cons.c:8628
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8389
SCIP_Bool SCIPconsIsModifiable(SCIP_CONS *cons)
Definition: cons.c:8638
SCIP_Bool SCIPconsIsStickingAtNode(SCIP_CONS *cons)
Definition: cons.c:8668
SCIP_Bool SCIPconsIsSeparated(SCIP_CONS *cons)
Definition: cons.c:8568
SCIP_Bool SCIPconsIsRemovable(SCIP_CONS *cons)
Definition: cons.c:8658
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
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#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 SCIPfreeBufferArrayNull(scip, ptr)
Definition: scip_mem.h:137
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1581
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition: scip_lp.c:1604
SCIP_RETCODE SCIPcreateEmptyRowConshdlr(SCIP *scip, SCIP_ROW **row, SCIP_CONSHDLR *conshdlr, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition: scip_lp.c:1367
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_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2981
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1765
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:24268
SCIP_RETCODE SCIPaddVarLocksType(SCIP *scip, SCIP_VAR *var, SCIP_LOCKTYPE locktype, int nlocksdown, int nlocksup)
Definition: scip_var.c:5118
SCIP_Real SCIPgetVarUbAtIndex(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: scip_var.c:2872
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:23267
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:24234
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 SCIPgetTransformedVar(SCIP *scip, SCIP_VAR *var, SCIP_VAR **transvar)
Definition: scip_var.c:2078
void SCIPsortIntInt(int *intarray1, int *intarray2, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
static SCIP_RETCODE separate(SCIP *scip, SCIP_SEPA *sepa, SCIP_SOL *sol, SCIP_RESULT *result)
Main separation function.
Definition: sepa_flower.c:1221
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:62
struct SCIP_ConsData SCIP_CONSDATA
Definition: type_cons.h:65
@ 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
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_LOCKTYPE_MODEL
Definition: type_var.h:141