SCIP Doxygen Documentation
Loading...
Searching...
No Matches
sepa_gomory.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 sepa_gomory.c
26 * @ingroup DEFPLUGINS_SEPA
27 * @brief Gomory MIR Cuts
28 * @author Tobias Achterberg
29 * @author Stefan Heinz
30 * @author Domenico Salvagnin
31 * @author Marc Pfetsch
32 * @author Leona Gottwald
33 */
34
35/**@todo try k-Gomory-cuts (s. Cornuejols: K-Cuts: A Variation of Gomory Mixed Integer Cuts from the LP Tableau)
36 *
37 * @todo Try cuts on the objective tableau row.
38 *
39 * @todo Also try negative basis inverse row?
40 *
41 * @todo It happens that the SCIPcalcMIR() function returns with the same cut for different calls. Check if this is a
42 * bug or do not use it for the MIP below and turn off presolving and all heuristics:
43 *
44 * Max y
45 * Subject to
46 * c1: -x + y <= 1
47 * c2: 2x + 3y <= 12
48 * c3: 3x + 2y <= 12
49 * Bounds
50 * 0 <= x
51 * 0 <= y
52 * General
53 * x
54 * y
55 * END
56 */
57
58/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
59
61#include "scip/cuts.h"
62#include "scip/pub_lp.h"
63#include "scip/pub_lpexact.h"
64#include "scip/pub_message.h"
65#include "scip/pub_misc.h"
66#include "scip/pub_misc_sort.h"
67#include "scip/pub_sepa.h"
68#include "scip/pub_var.h"
69#include "scip/scip_branch.h"
71#include "scip/scip_cut.h"
72#include "scip/scip_exact.h"
73#include "scip/scip_general.h"
74#include "scip/scip_lp.h"
75#include "scip/scip_lpexact.h"
76#include "scip/scip_mem.h"
77#include "scip/scip_message.h"
78#include "scip/scip_numerics.h"
79#include "scip/scip_param.h"
80#include "scip/scip_prob.h"
82#include "scip/scip_sepa.h"
84#include "scip/scip_tree.h"
85#include "scip/scip_var.h"
86#include "scip/sepa_gomory.h"
87
88
89#define SEPA_NAME "gomory"
90#define SEPA_DESC "separator for Gomory mixed-integer and strong CG cuts from LP tableau rows"
91#define SEPA_PRIORITY -1000
92#define SEPA_FREQ 10
93#define SEPA_MAXBOUNDDIST 1.0
94#define SEPA_USESSUBSCIP FALSE /**< does the separator use a secondary SCIP instance? */
95#define SEPA_DELAY FALSE /**< should separation method be delayed, if other separators found cuts? */
96
97#define DEFAULT_MAXROUNDS 5 /**< maximal number of gomory separation rounds per node (-1: unlimited) */
98#define DEFAULT_MAXROUNDSROOT 10 /**< maximal number of gomory separation rounds in the root node (-1: unlimited) */
99#define DEFAULT_MAXSEPACUTS 50 /**< maximal number of gomory cuts separated per separation round */
100#define DEFAULT_MAXSEPACUTSROOT 200 /**< maximal number of gomory cuts separated per separation round in root node */
101#define DEFAULT_MAXRANK -1 /**< maximal rank of a gomory cut that could not be scaled to integral coefficients (-1: unlimited) */
102#define DEFAULT_MAXRANKINTEGRAL -1 /**< maximal rank of a gomory cut that could be scaled to integral coefficients (-1: unlimited) */
103#define DEFAULT_DYNAMICCUTS TRUE /**< should generated cuts be removed from the LP if they are no longer tight? */
104#define DEFAULT_AWAY 0.01 /**< minimal integrality violation of a basis variable in order to try Gomory cut */
105#define DEFAULT_MAKEINTEGRAL FALSE /**< try to scale all cuts to integral coefficients */
106#define DEFAULT_FORCECUTS TRUE /**< if conversion to integral coefficients failed still consider the cut */
107#define DEFAULT_SEPARATEROWS TRUE /**< separate rows with integral slack */
108#define DEFAULT_DELAYEDCUTS FALSE /**< should cuts be added to the delayed cut pool? */
109#define DEFAULT_SIDETYPEBASIS TRUE /**< choose side types of row (lhs/rhs) based on basis information? */
110#define DEFAULT_TRYSTRONGCG TRUE /**< try to generate strengthened Chvatal-Gomory cuts? */
111#define DEFAULT_GENBOTHGOMSCG TRUE /**< should both Gomory and strong CG cuts be generated (otherwise take best) */
112#define DEFAULT_RANDSEED 53 /**< initial random seed */
113
114#define BOUNDSWITCH 0.9999 /**< threshold for bound switching - see SCIPcalcMIR() */
115#define POSTPROCESS TRUE /**< apply postprocessing after MIR calculation - see SCIPcalcMIR() */
116#define VARTYPEUSEVBDS 2 /**< We allow variable bound substitution for variables with continuous vartype only.
117 * See SCIPcalcMIR() for more information. */
118#define FIXINTEGRALRHS FALSE /**< try to generate an integral rhs - see SCIPcalcMIR() */
119#define MAKECONTINTEGRAL FALSE /**< convert continuous variable to integral variables in SCIPmakeRowIntegral() */
120
121#define MAXAGGRLEN(nvars) (0.1*(nvars)+1000) /**< maximal length of base inequality */
122
123
124/** separator data */
125struct SCIP_SepaData
126{
127 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
128 SCIP_SEPA* strongcg; /**< strong CG cut separator */
129 SCIP_SEPA* gomory; /**< gomory cut separator */
130 SCIP_Real away; /**< minimal integrality violation of a basis variable in order to try Gomory cut */
131 int maxrounds; /**< maximal number of gomory separation rounds per node (-1: unlimited) */
132 int maxroundsroot; /**< maximal number of gomory separation rounds in the root node (-1: unlimited) */
133 int maxsepacuts; /**< maximal number of gomory cuts separated per separation round */
134 int maxsepacutsroot; /**< maximal number of gomory cuts separated per separation round in root node */
135 int maxrank; /**< maximal rank of a gomory cut that could not be scaled to integral coefficients (-1: unlimited) */
136 int maxrankintegral; /**< maximal rank of a gomory cut that could be scaled to integral coefficients (-1: unlimited) */
137 int lastncutsfound; /**< total number of cuts found after last call of separator */
138 SCIP_Bool dynamiccuts; /**< should generated cuts be removed from the LP if they are no longer tight? */
139 SCIP_Bool makeintegral; /**< try to scale all cuts to integral coefficients */
140 SCIP_Bool forcecuts; /**< if conversion to integral coefficients failed still consider the cut */
141 SCIP_Bool separaterows; /**< separate rows with integral slack */
142 SCIP_Bool delayedcuts; /**< should cuts be added to the delayed cut pool? */
143 SCIP_Bool sidetypebasis; /**< choose side types of row (lhs/rhs) based on basis information? */
144 SCIP_Bool trystrongcg; /**< try to generate strengthened Chvatal-Gomory cuts? */
145 SCIP_Bool genbothgomscg; /**< should both Gomory and strong CG cuts be generated (otherwise take best) */
146};
147
148
149/** returns TRUE if the cut can be taken, otherwise FALSE if there some numerical evidences */
150static
152 SCIP* scip, /**< SCIP data structure */
153 SCIP_SEPADATA* sepadata, /**< data of the separator */
154 SCIP_ROW* cut, /**< cut to check */
155 SCIP_Longint maxdnom, /**< maximal denominator to use for scaling */
156 SCIP_Real maxscale, /**< maximal scaling factor */
157 SCIP_Bool* useful /**< pointer to store if the cut is useful */
158 )
159{
160 SCIP_Bool madeintegral = FALSE;
161
162 assert(useful != NULL);
163
164 *useful = FALSE;
165
166 if( sepadata->makeintegral && SCIPgetRowNumIntCols(scip, cut) == SCIProwGetNNonz(cut) )
167 {
168 /* try to scale the cut to integral values */
170 maxdnom, maxscale, MAKECONTINTEGRAL, &madeintegral) );
171
172 if( !madeintegral && !sepadata->forcecuts )
173 return SCIP_OKAY;
174
175 /* in case the right hand side is plus infinity (due to scaling) the cut is useless so we are not taking it at all */
176 if( madeintegral && SCIPisInfinity(scip, SCIProwGetRhs(cut)) )
177 return SCIP_OKAY;
178 }
179
180 /* discard integral cut if the rank is too high */
181 if( madeintegral && sepadata->maxrankintegral != -1 && (SCIProwGetRank(cut) > sepadata->maxrankintegral) )
182 return SCIP_OKAY;
183
184 /* discard cut if the rank is too high */
185 if( !madeintegral && (sepadata->maxrank != -1) && (SCIProwGetRank(cut) > sepadata->maxrank) )
186 return SCIP_OKAY;
187
188 *useful = TRUE;
189
190 return SCIP_OKAY;
191}
192
193
194/** add cut */
195static
197 SCIP* scip, /**< SCIP instance */
198 SCIP_SEPADATA* sepadata, /**< separator data */
199 SCIP_VAR** vars, /**< array of variables */
200 int c, /**< index of basic variable (< 0 for slack variables) */
201 SCIP_Longint maxdnom, /**< maximal denominator to use for scaling */
202 SCIP_Real maxscale, /**< maximal scaling factor */
203 int cutnnz, /**< number of nonzeros in cut */
204 int* cutinds, /**< variable indices in cut */
205 SCIP_Real* cutcoefs, /**< cut cofficients */
206 SCIP_Real cutefficacy, /**< cut efficacy */
207 SCIP_Real cutrhs, /**< rhs of cut */
208 SCIP_Bool cutislocal, /**< whether cut is local */
209 int cutrank, /**< rank of cut */
210 SCIP_Bool strongcg, /**< whether the cut arises from the strong-CG procedure */
211 SCIP_Bool* cutoff, /**< pointer to store whether a cutoff appeared */
212 int* naddedcuts /**< pointer to store number of added cuts */
213 )
214{
215 int j;
216
217 assert(scip != NULL);
218 assert(cutoff != NULL);
219 assert(naddedcuts != NULL);
220
221 if( cutnnz == 0 && SCIPisFeasNegative(scip, cutrhs) && !SCIPisExact(scip) ) /*lint !e644*/
222 {
223 SCIPdebugMsg(scip, " -> gomory cut detected infeasibility with cut 0 <= %g.\n", cutrhs);
224 *cutoff = TRUE;
225 return SCIP_OKAY;
226 }
227
228 /* Only take efficient cuts, except for cuts with one non-zero coefficient (= bound
229 * changes); the latter cuts will be handled internally in sepastore. */
230 if( SCIPisEfficacious(scip, cutefficacy) || ( cutnnz == 1 && SCIPisFeasPositive(scip, cutefficacy) ) )
231 {
232 SCIP_ROW* cut;
233 SCIP_SEPA* cutsepa;
234 char cutname[SCIP_MAXSTRLEN];
235 int v;
236
237 /* construct cut name */
238 if( strongcg )
239 {
240 cutsepa = sepadata->strongcg;
241
242 if( c >= 0 )
243 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "scg%" SCIP_LONGINT_FORMAT "_x%d", SCIPgetNLPs(scip), c);
244 else
245 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "scg%" SCIP_LONGINT_FORMAT "_s%d", SCIPgetNLPs(scip), -c-1);
246 }
247 else
248 {
249 cutsepa = sepadata->gomory;
250
251 if( c >= 0 )
252 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "gom%" SCIP_LONGINT_FORMAT "_x%d", SCIPgetNLPs(scip), c);
253 else
254 (void) SCIPsnprintf(cutname, SCIP_MAXSTRLEN, "gom%" SCIP_LONGINT_FORMAT "_s%d", SCIPgetNLPs(scip), -c-1);
255 }
256
257 if( SCIPisExact(scip) )
258 {
259 SCIP_ROUNDMODE roundmode;
260
261 roundmode = SCIPintervalGetRoundingMode();
263 /* postprocess cut for exact solving, i.e. change almost integer values to integer by weakening side */
264 for( j = 0; j < cutnnz; j++ )
265 {
266 if( SCIPisIntegral(scip, cutcoefs[j]) )
267 {
268 SCIP_Real roundedval = SCIPround(scip, cutcoefs[j]);
269 SCIP_Real delta = roundedval - cutcoefs[j];
270 SCIP_VAR* var = vars[cutinds[j]];
271 SCIP_Real sideval;
272
273 if( delta == 0 )
274 continue;
275
276 if( cutislocal )
277 sideval = delta > 0 ? SCIPvarGetUbLocal(var) : SCIPvarGetLbLocal(var);
278 else
279 sideval = delta > 0 ? SCIPvarGetUbGlobal(var) : SCIPvarGetLbGlobal(var);
280
281 if( SCIPisInfinity(scip, REALABS(sideval)) )
282 continue;
283
284 cutcoefs[j]= roundedval;
285 cutrhs += delta * sideval;
286 }
287 }
289 }
290
291 /* create empty cut */
292 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &cut, cutsepa, cutname, -SCIPinfinity(scip), cutrhs,
293 cutislocal, FALSE, sepadata->dynamiccuts) );
294
295 /* set cut rank */
296 SCIProwChgRank(cut, cutrank); /*lint !e644*/
297
298 /* cache the row extension and only flush them if the cut gets added */
300
301 /* collect all non-zero coefficients */
302 for( v = 0; v < cutnnz; ++v )
303 {
304 SCIP_CALL( SCIPaddVarToRow(scip, cut, vars[cutinds[v]], cutcoefs[v]) );
305 }
306
307 /* flush all changes before adding the cut */
309
310 if( SCIProwGetNNonz(cut) == 0 && !SCIPisExact(scip) )
311 {
312 assert( SCIPisFeasNegative(scip, cutrhs) );
313 SCIPdebugMsg(scip, " -> gomory cut detected infeasibility with cut 0 <= %g.\n", cutrhs);
314 *cutoff = TRUE;
315 return SCIP_OKAY;
316 }
317 else if( SCIProwGetNNonz(cut) == 1 )
318 {
319 /* Add the bound change as cut to avoid that the LP gets modified. This would mean that the LP is not flushed
320 * and the method SCIPgetLPBInvRow() fails; SCIP internally will apply this bound change automatically. */
322 ++(*naddedcuts);
323 if( SCIPisCertified(scip) )
324 {
327 }
328 }
329 else
330 {
331 SCIP_Bool useful;
332
335
336 SCIPdebugMsg(scip, " -> %s cut <%s>: rhs=%f, eff=%f\n", strongcg ? "strong-CG" : "gomory", cutname, cutrhs, cutefficacy);
337
338 SCIP_CALL( evaluateCutNumerics(scip, sepadata, cut, maxdnom, maxscale, &useful) );
339
340 if( useful )
341 {
342 SCIPdebugMsg(scip, " -> found %s cut <%s>: act=%f, rhs=%f, norm=%f, eff=%f, min=%f, max=%f (range=%f)\n",
343 strongcg ? "strong-CG" : "gomory", cutname, SCIPgetRowLPActivity(scip, cut), SCIProwGetRhs(cut),
347
349
350 if( SCIPisCutNew(scip, cut) )
351 {
352 /* add global cuts which are not implicit bound changes to the cut pool */
353 if( !cutislocal )
354 {
355 if( sepadata->delayedcuts )
356 {
358 }
359 else
360 {
362 }
363 }
364 else
365 {
366 /* local cuts we add to the sepastore */
368 }
369
370 ++(*naddedcuts);
371
372 /* For certification we need to create the exact representation of the row; we need to perform this here
373 * because the certificate uses the current variable bounds; if certification is not active, we delay the
374 * creation of the exact row until the cut is actually selected to enter the LP, see sepastore.c.
375 *
376 * Note that this can lead to different solving paths when solving with/without certification, because
377 * the floating-point coefficients can change slightly during the creation of the exact row (if rational
378 * coefficients are rounded to smaller denominators) and this may affect cut selection.
379 */
380 if( SCIPisCertified(scip) )
381 {
384
385 if( SCIProwGetRowExact(cut) == NULL )
386 {
387 /**@todo delay creation of exact row for globally valid cuts */
388 if( !cutislocal )
389 {
393 }
394 else
395 {
397 }
398 }
399
401 }
402 }
403 }
404 }
405 /* release the row */
406 SCIP_CALL( SCIPreleaseRow(scip, &cut) );
407 }
408
409 return SCIP_OKAY;
410}
411
412/*
413 * Callback methods
414 */
415
416/** copy method for separator plugins (called when SCIP copies plugins) */
417static
418SCIP_DECL_SEPACOPY(sepaCopyGomory)
419{ /*lint --e{715}*/
420 assert(scip != NULL);
421 assert(sepa != NULL);
422
424
425 /* call inclusion method of separator */
427
428 return SCIP_OKAY;
429}
430
431/** destructor of separator to free user data (called when SCIP is exiting) */
432/**! [SnippetSepaFreeGomory] */
433static
434SCIP_DECL_SEPAFREE(sepaFreeGomory)
435{ /*lint --e{715}*/
437
439
440 /* free separator data */
442 assert(sepadata != NULL);
443
445
446 SCIPsepaSetData(sepa, NULL);
447
448 return SCIP_OKAY;
449}
450/**! [SnippetSepaFreeGomory] */
451
452/** initialization method of separator (called after problem was transformed) */
453static
454SCIP_DECL_SEPAINIT(sepaInitGomory)
455{
457
459 assert(sepadata != NULL);
460
461 /* create and initialize random number generator */
463
464 return SCIP_OKAY;
465}
466
467/** deinitialization method of separator (called before transformed problem is freed) */
468static
469SCIP_DECL_SEPAEXIT(sepaExitGomory)
470{ /*lint --e{715}*/
472
474 assert(sepadata != NULL);
475
476 SCIPfreeRandom(scip, &sepadata->randnumgen);
477
478 return SCIP_OKAY;
479}
480
481
482/** LP solution separation method of separator */
483static
484SCIP_DECL_SEPAEXECLP(sepaExeclpGomory)
485{ /*lint --e{715}*/
487 SCIP_VAR** vars;
488 SCIP_COL** cols;
489 SCIP_ROW** rows;
490 SCIP_AGGRROW* aggrrow;
491 SCIP_VAR* var;
492 SCIP_Real* binvrow;
493 SCIP_Real* cutcoefs;
494 SCIP_Real* basisfrac;
495 SCIP_Real* cutefficacies;
496 int* basisind;
497 int* basisperm;
498 int* inds;
499 int* cutinds;
500 int* colindsproducedcut;
501 SCIP_Real maxscale;
502 SCIP_Real minfrac;
503 SCIP_Real maxfrac;
504 SCIP_Real maxcutefficacy;
505 SCIP_Longint maxdnom;
507 SCIP_Bool separatescg;
508 SCIP_Bool separategmi;
509 int naddedcuts;
510 int nvars;
511 int ncols;
512 int nrows;
513 int ncalls;
514 int maxdepth;
515 int maxsepacuts;
516 int freq;
517 int c;
518 int i;
519 int j;
520
521 assert(sepa != NULL);
522 assert(scip != NULL);
523 assert(result != NULL);
524
526
528
530 assert(sepadata != NULL);
531
533
534 minfrac = sepadata->away;
535 maxfrac = 1.0 - sepadata->away;
536
537 /* only call separator, if we are not close to terminating */
538 if( SCIPisStopped(scip) )
539 return SCIP_OKAY;
540
541 /* only call the gomory cut separator a given number of times at each node */
542 if( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
543 || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
544 return SCIP_OKAY;
545
546 /* only call separator, if an optimal LP solution is at hand */
548 return SCIP_OKAY;
549
550 /* only call separator, if the LP solution is basic */
551 if( !SCIPisLPSolBasic(scip) )
552 return SCIP_OKAY;
553
554 /* only call separator, if there are fractional variables */
555 if( SCIPgetNLPBranchCands(scip) == 0 )
556 return SCIP_OKAY;
557
558 /* check whether strong CG cuts should be separated */
559 freq = SCIPsepaGetFreq(sepadata->strongcg);
560 if( freq > 0 )
561 separatescg = (depth % freq == 0);
562 else
563 separatescg = (freq == depth);
564
565 /* check whether Gomory MI cuts should be separated */
566 freq = SCIPsepaGetFreq(sepadata->gomory);
567 if( freq > 0 )
568 separategmi = (depth % freq == 0);
569 else
570 separategmi = (freq == depth);
571
572 if( !separatescg && !separategmi )
573 return SCIP_OKAY;
574
575 /* get variables data */
577
578 /* get LP data */
579 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
580 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
581 if( ncols == 0 || nrows == 0 )
582 return SCIP_OKAY;
583
584 /* set the maximal denominator in rational representation of gomory cut and the maximal scale factor to
585 * scale resulting cut to integral values to avoid numerical instabilities
586 */
587 /**@todo find better but still stable gomory cut settings: look at dcmulti, gesa3, khb0525, misc06, p2756 */
589 if( depth == 0 )
590 {
591 maxdnom = 1000;
592 maxscale = 1000.0;
593 }
594 else if( depth <= maxdepth/4 )
595 {
596 maxdnom = 1000;
597 maxscale = 1000.0;
598 }
599 else if( depth <= maxdepth/2 )
600 {
601 maxdnom = 100;
602 maxscale = 100.0;
603 }
604 else
605 {
606 maxdnom = 10;
607 maxscale = 10.0;
608 }
609
610 /* allocate temporary memory */
613 SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
614 SCIP_CALL( SCIPallocBufferArray(scip, &basisperm, nrows) );
615 SCIP_CALL( SCIPallocBufferArray(scip, &basisfrac, nrows) );
616 SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
617 SCIP_CALL( SCIPallocBufferArray(scip, &inds, nrows) );
618 SCIP_CALL( SCIPallocBufferArray(scip, &cutefficacies, nrows) );
619 SCIP_CALL( SCIPallocBufferArray(scip, &colindsproducedcut, nrows) );
620 SCIP_CALL( SCIPaggrRowCreate(scip, &aggrrow) );
621
622 /* get basis indices */
623 SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
624
625 for( i = 0; i < nrows; ++i )
626 {
627 SCIP_Real frac = 0.0;
628
629 c = basisind[i];
630 cutefficacies[i] = 0.0;
631
632 basisperm[i] = i;
633
634 colindsproducedcut[i] = -1;
635
636 if( c >= 0 )
637 {
638 assert(c < ncols);
639 var = SCIPcolGetVar(cols[c]);
641 {
643 frac = MIN(frac, 1.0 - frac);
644 }
645 }
646 else if( sepadata->separaterows )
647 {
648 SCIP_ROW* row;
649
650 assert(0 <= -c-1 && -c-1 < nrows);
651 row = rows[-c-1];
652 /* We allow separating on rows with a 'slack' implied integral variable */
654 {
656 frac = MIN(frac, 1.0 - frac);
657 }
658 }
659
660 if( frac >= minfrac )
661 {
662 /* slightly change fractionality to have random order for equal fractions */
663 basisfrac[i] = frac + SCIPrandomGetReal(sepadata->randnumgen, -1e-6, 1e-6);
664 }
665 else
666 {
667 basisfrac[i] = 0.0;
668 }
669 }
670
671 /* sort basis indices by fractionality */
672 SCIPsortDownRealInt(basisfrac, basisperm, nrows);
673
674 /* get the maximal number of cuts allowed in a separation round */
675 if( depth == 0 )
676 maxsepacuts = sepadata->maxsepacutsroot;
677 else
678 maxsepacuts = sepadata->maxsepacuts;
679
680 SCIPdebugMsg(scip, "searching gomory cuts: %d cols, %d rows, maxdnom=%" SCIP_LONGINT_FORMAT ", maxscale=%g, maxcuts=%d\n",
681 ncols, nrows, maxdnom, maxscale, maxsepacuts);
682
683 cutoff = FALSE;
684 naddedcuts = 0;
685
686 /* for all basic columns belonging to integer variables, try to generate a gomory cut */
687 for( i = 0; i < nrows && naddedcuts < maxsepacuts && !SCIPisStopped(scip) && !cutoff; ++i )
688 {
689 SCIP_Real cutrhs;
690 SCIP_Real cutefficacy = 0.0;
691 SCIP_Bool success;
692 SCIP_Bool cutislocal;
693 SCIP_Bool strongcgsuccess = FALSE;
694 int ninds = -1;
695 int cutnnz;
696 int cutrank;
697
698 if( basisfrac[i] == 0.0 )
699 break;
700
701 j = basisperm[i];
702 c = basisind[j];
703
704 /* get the row of B^-1 for this basic integer variable with fractional solution value */
705 SCIP_CALL( SCIPgetLPBInvRow(scip, j, binvrow, inds, &ninds) );
706
707 SCIP_CALL( SCIPaggrRowSumRows(scip, aggrrow, binvrow, inds, ninds,
708 sepadata->sidetypebasis, allowlocal, SCIPallowNegSlack(scip) ? 2 : 0, (int) MAXAGGRLEN(nvars), &success) );
709
710 if( !success )
711 continue;
712
713 /* try to create a strong CG cut out of the aggregation row */
714 if( separatescg && !SCIPisExact(scip) )
715 {
716 SCIP_CALL( SCIPcalcStrongCG(scip, NULL, POSTPROCESS, BOUNDSWITCH, VARTYPEUSEVBDS, allowlocal, minfrac, maxfrac,
717 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, &cutrank, &cutislocal, &strongcgsuccess) );
718
719 /* if we want to generate both cuts, add cut and reset cutefficacy and strongcgsuccess */
720 if( strongcgsuccess && sepadata->genbothgomscg )
721 {
722 assert(allowlocal || !cutislocal); /*lint !e644*/
723 SCIP_CALL( addCut(scip, sepadata, vars, c, maxdnom, maxscale, cutnnz, cutinds, cutcoefs, cutefficacy, cutrhs,
724 cutislocal, cutrank, TRUE, &cutoff, &naddedcuts) );
725 if( c >= 0 )
726 {
727 cutefficacies[i] = cutefficacy;
728 colindsproducedcut[i] = c;
729 }
730 cutefficacy = 0.0;
731 strongcgsuccess = FALSE;
732 if( cutoff )
733 break;
734 }
735 }
736 /* try to create Gomory cut out of the aggregation row */
737 if( separategmi )
738 {
739 /* SCIPcalcMIR will only override the cut if its efficacy is larger than the one of the strongcg cut */
741 minfrac, maxfrac, 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, &cutrank, &cutislocal, &success) );
742
743 if( success || strongcgsuccess )
744 {
745 assert(allowlocal || !cutislocal); /*lint !e644*/
746 if( success )
747 strongcgsuccess = FALSE; /* Set strongcgsuccess to FALSE, since the MIR cut has overriden the strongcg cut. */
748
749 SCIP_CALL( addCut(scip, sepadata, vars, c, maxdnom, maxscale, cutnnz, cutinds, cutcoefs, cutefficacy, cutrhs,
750 cutislocal, cutrank, strongcgsuccess, &cutoff, &naddedcuts) );
751 if( c >= 0 )
752 {
753 cutefficacies[i] = cutefficacy;
754 colindsproducedcut[i] = c;
755 }
756 }
757 }
758 if( SCIPisCertified(scip) )
759 {
762 }
763 }
764
765 /* Add normalized efficacy GMI statistics to history */
766 maxcutefficacy = 0.0;
767 for( i = 0; i < nrows; ++i )
768 {
769 if( cutefficacies[i] > maxcutefficacy && colindsproducedcut[i] >= 0 )
770 {
771 maxcutefficacy = cutefficacies[i];
772 }
773 }
774
775 for( i = 0; i < nrows; ++i )
776 {
777 if( colindsproducedcut[i] >= 0 && SCIPisEfficacious(scip, cutefficacies[i]) )
778 {
779 assert( maxcutefficacy > 0.0 );
780 var = SCIPcolGetVar(cols[colindsproducedcut[i]]);
781 SCIP_CALL( SCIPsetVarLastGMIScore(scip, var, cutefficacies[i] / maxcutefficacy) );
782 SCIP_CALL( SCIPincVarGMISumScore(scip, var, cutefficacies[i] / maxcutefficacy) );
783 }
784 }
785
786 /* free temporary memory */
787 SCIPaggrRowFree(scip, &aggrrow);
788 SCIPfreeBufferArray(scip, &colindsproducedcut);
789 SCIPfreeBufferArray(scip, &cutefficacies);
791 SCIPfreeBufferArray(scip, &binvrow);
792 SCIPfreeBufferArray(scip, &basisfrac);
793 SCIPfreeBufferArray(scip, &basisperm);
794 SCIPfreeBufferArray(scip, &basisind);
795 SCIPfreeBufferArray(scip, &cutinds);
796 SCIPfreeBufferArray(scip, &cutcoefs);
797
798 SCIPdebugMsg(scip, "end searching gomory cuts: found %d cuts\n", naddedcuts);
799
800 sepadata->lastncutsfound = SCIPgetNCutsFound(scip);
801
802 /* evaluate the result of the separation */
803 if( cutoff )
805 else if ( naddedcuts > 0 )
807 else
809
810 return SCIP_OKAY;
811}
812
813
814/*
815 * separator specific interface methods
816 */
817
818/** LP solution separation method of dummy separator */
819static
820SCIP_DECL_SEPAEXECLP(sepaExeclpDummy)
821{ /*lint --e{715}*/
822 assert( result != NULL );
823
825
826 return SCIP_OKAY;
827}
828
829/** arbitrary primal solution separation method of dummy separator */
830static
831SCIP_DECL_SEPAEXECSOL(sepaExecsolDummy)
832{ /*lint --e{715}*/
833 assert( result != NULL );
834
836
837 return SCIP_OKAY;
838}
839
840/** creates the Gomory MIR cut separator and includes it in SCIP */
842 SCIP* scip /**< SCIP data structure */
843 )
844{
846 SCIP_SEPA* sepa;
847
848 /* create separator data */
850 sepadata->lastncutsfound = 0;
851
852 /* include separator */
855 sepaExeclpGomory, NULL,
856 sepadata) );
857
858 assert(sepa != NULL);
859
860 /* gomory is safe to use in exact solving mode */
861 SCIPsepaMarkExact(sepa);
862
863 SCIP_CALL( SCIPincludeSepaBasic(scip, &sepadata->strongcg, "strongcg", "separator for strong CG cuts", -100000, SEPA_FREQ, 0.0,
864 SEPA_USESSUBSCIP, FALSE, sepaExeclpDummy, sepaExecsolDummy, NULL) );
865 assert(sepadata->strongcg != NULL);
866
867 SCIP_CALL( SCIPincludeSepaBasic(scip, &sepadata->gomory, "gomorymi", "separator for Gomory mixed-integer cuts", -100000, SEPA_FREQ, 0.0,
868 SEPA_USESSUBSCIP, FALSE, sepaExeclpDummy, sepaExecsolDummy, NULL) );
869 assert(sepadata->gomory != NULL);
870
871 /* set non-NULL pointers to callback methods */
872 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyGomory) );
873 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGomory) );
874 SCIP_CALL( SCIPsetSepaInit(scip, sepa, sepaInitGomory) );
875 SCIP_CALL( SCIPsetSepaExit(scip, sepa, sepaExitGomory) );
876
877 /* mark main separator as a parent */
879
880 /* set pointer from child separators to main separator */
881 SCIPsetSepaParentsepa(scip, sepadata->strongcg, sepa);
882 SCIPsetSepaParentsepa(scip, sepadata->gomory, sepa);
883
884 /* add separator parameters */
886 "separating/gomory/maxrounds",
887 "maximal number of gomory separation rounds per node (-1: unlimited)",
888 &sepadata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
890 "separating/gomory/maxroundsroot",
891 "maximal number of gomory separation rounds in the root node (-1: unlimited)",
892 &sepadata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
894 "separating/gomory/maxsepacuts",
895 "maximal number of gomory cuts separated per separation round",
896 &sepadata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
898 "separating/gomory/maxsepacutsroot",
899 "maximal number of gomory cuts separated per separation round in the root node",
900 &sepadata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
902 "separating/gomory/maxrank",
903 "maximal rank of a gomory cut that could not be scaled to integral coefficients (-1: unlimited)",
904 &sepadata->maxrank, FALSE, DEFAULT_MAXRANK, -1, INT_MAX, NULL, NULL) );
906 "separating/gomory/maxrankintegral",
907 "maximal rank of a gomory cut that could be scaled to integral coefficients (-1: unlimited)",
908 &sepadata->maxrankintegral, FALSE, DEFAULT_MAXRANKINTEGRAL, -1, INT_MAX, NULL, NULL) );
910 "separating/gomory/away",
911 "minimal integrality violation of a basis variable in order to try Gomory cut",
912 &sepadata->away, FALSE, DEFAULT_AWAY, 1e-4, 0.5, NULL, NULL) );
914 "separating/gomory/dynamiccuts",
915 "should generated cuts be removed from the LP if they are no longer tight?",
916 &sepadata->dynamiccuts, FALSE, DEFAULT_DYNAMICCUTS, NULL, NULL) );
918 "separating/gomory/makeintegral",
919 "try to scale cuts to integral coefficients",
920 &sepadata->makeintegral, TRUE, DEFAULT_MAKEINTEGRAL, NULL, NULL) );
922 "separating/gomory/forcecuts",
923 "if conversion to integral coefficients failed still consider the cut",
924 &sepadata->forcecuts, TRUE, DEFAULT_FORCECUTS, NULL, NULL) );
926 "separating/gomory/separaterows",
927 "separate rows with integral slack",
928 &sepadata->separaterows, TRUE, DEFAULT_SEPARATEROWS, NULL, NULL) );
930 "separating/gomory/delayedcuts",
931 "should cuts be added to the delayed cut pool?",
932 &sepadata->delayedcuts, TRUE, DEFAULT_DELAYEDCUTS, NULL, NULL) );
934 "separating/gomory/sidetypebasis",
935 "choose side types of row (lhs/rhs) based on basis information?",
936 &sepadata->sidetypebasis, TRUE, DEFAULT_SIDETYPEBASIS, NULL, NULL) );
938 "separating/gomory/trystrongcg",
939 "try to generate strengthened Chvatal-Gomory cuts?",
940 &sepadata->trystrongcg, TRUE, DEFAULT_TRYSTRONGCG, NULL, NULL) );
942 "separating/gomory/genbothgomscg",
943 "Should both Gomory and strong CG cuts be generated (otherwise take best)?",
944 &sepadata->genbothgomscg, TRUE, DEFAULT_GENBOTHGOMSCG, NULL, NULL) );
945
946 return SCIP_OKAY;
947}
#define BOUNDSWITCH
#define POSTPROCESS
#define VARTYPEUSEVBDS
#define FIXINTEGRALRHS
#define DEFAULT_MAXROUNDSROOT
#define DEFAULT_MAXSEPACUTSROOT
#define DEFAULT_MAXSEPACUTS
#define DEFAULT_MAXROUNDS
#define DEFAULT_RANDSEED
methods for the aggregation rows
#define NULL
Definition def.h:257
#define SCIP_MAXSTRLEN
Definition def.h:278
#define SCIP_Longint
Definition def.h:150
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#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 SCIP_LONGINT_FORMAT
Definition def.h:157
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition scip_prob.c:2115
#define SCIPdebugMsg
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:139
SCIP_RETCODE 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 SCIPfreeCertificateActiveMirInfo(SCIP *scip)
SCIP_RETCODE SCIPstoreCertificateActiveAggrInfo(SCIP *scip, SCIP_ROW *row)
SCIP_Bool SCIPisCertified(SCIP *scip)
SCIP_RETCODE SCIPfreeCertificateActiveAggrInfo(SCIP *scip)
SCIP_RETCODE SCIPcertifyMirCut(SCIP *scip, SCIP_ROW *row)
SCIP_RETCODE SCIPstoreCertificateActiveMirInfo(SCIP *scip, SCIP_ROW *row)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition lp.c:17425
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition lp.c:17379
SCIP_RETCODE SCIPaddPoolCut(SCIP *scip, SCIP_ROW *row)
Definition scip_cut.c:336
SCIP_Real SCIPgetCutEfficacy(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition scip_cut.c:94
SCIP_RETCODE SCIPcalcMIR(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, int vartypeusevbds, SCIP_Bool allowlocal, SCIP_Bool fixintegralrhs, int *boundsfortrans, SCIP_BOUNDTYPE *boundtypesfortrans, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
Definition cuts.c:7934
SCIP_RETCODE SCIPaggrRowCreate(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition cuts.c:2679
SCIP_Bool SCIPisCutNew(SCIP *scip, SCIP_ROW *row)
Definition scip_cut.c:318
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition scip_cut.c:135
SCIP_RETCODE SCIPcalcStrongCG(SCIP *scip, SCIP_SOL *sol, SCIP_Bool postprocess, SCIP_Real boundswitch, int vartypeusevbds, SCIP_Bool allowlocal, SCIP_Real minfrac, SCIP_Real maxfrac, SCIP_Real scale, SCIP_AGGRROW *aggrrow, SCIP_Real *cutcoefs, SCIP_Real *cutrhs, int *cutinds, int *cutnnz, SCIP_Real *cutefficacy, int *cutrank, SCIP_Bool *cutislocal, SCIP_Bool *success)
Definition cuts.c:13313
void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition cuts.c:2711
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition scip_cut.c:225
SCIP_RETCODE SCIPaggrRowSumRows(SCIP *scip, SCIP_AGGRROW *aggrrow, SCIP_Real *weights, int *rowinds, int nrowinds, SCIP_Bool sidetypebasis, SCIP_Bool allowlocal, int negslack, int maxaggrlen, SCIP_Bool *valid)
Definition cuts.c:3534
SCIP_RETCODE SCIPdelPoolCut(SCIP *scip, SCIP_ROW *row)
Definition scip_cut.c:356
SCIP_RETCODE SCIPaddDelayedPoolCut(SCIP *scip, SCIP_ROW *row)
Definition scip_cut.c:616
SCIP_Bool SCIPallowNegSlack(SCIP *scip)
Definition scip_exact.c:212
SCIP_Bool SCIPisExact(SCIP *scip)
Definition scip_exact.c:193
void SCIPintervalSetRoundingModeUpwards(void)
SCIP_ROUNDMODE SCIPintervalGetRoundingMode(void)
void SCIPintervalSetRoundingMode(SCIP_ROUNDMODE roundmode)
int SCIP_ROUNDMODE
SCIP_RETCODE SCIPcreateRowExactFromRow(SCIP *scip, SCIP_ROW *fprow)
SCIP_RETCODE SCIPgetLPBasisInd(SCIP *scip, int *basisind)
Definition scip_lp.c:692
SCIP_RETCODE SCIPgetLPColsData(SCIP *scip, SCIP_COL ***cols, int *ncols)
Definition scip_lp.c:477
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition scip_lp.c:576
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition scip_lp.c:174
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition scip_lp.c:673
SCIP_RETCODE SCIPgetLPBInvRow(SCIP *scip, int r, SCIP_Real *coefs, int *inds, int *ninds)
Definition scip_lp.c:720
#define SCIPallocClearBufferArray(scip, ptr, num)
Definition scip_mem.h:126
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
#define SCIPfreeBlockMemory(scip, ptr)
Definition scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition scip_mem.h:89
SCIP_Bool SCIProwIsIntegral(SCIP_ROW *row)
Definition lp.c:17785
SCIP_Real SCIPgetRowMaxCoef(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1886
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition lp.c:17686
SCIP_Real SCIPgetRowMinCoef(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1868
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition lp.c:17805
SCIP_RETCODE SCIPcacheRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1581
int SCIProwGetNNonz(SCIP_ROW *row)
Definition lp.c:17607
SCIP_Real SCIPgetRowLPActivity(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1957
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition lp.c:17696
SCIP_Real SCIProwGetNorm(SCIP_ROW *row)
Definition lp.c:17662
SCIP_RETCODE SCIPflushRowExtensions(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1604
int SCIPgetRowNumImpliedIntCols(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1850
SCIP_RETCODE SCIPmakeRowIntegral(SCIP *scip, SCIP_ROW *row, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool usecontvars, SCIP_Bool *success)
Definition scip_lp.c:1790
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_Real SCIPgetRowActivity(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:2068
SCIP_RETCODE SCIPreleaseRow(SCIP *scip, SCIP_ROW **row)
Definition scip_lp.c:1508
SCIP_RETCODE SCIPcreateEmptyRowSepa(SCIP *scip, SCIP_ROW **row, SCIP_SEPA *sepa, const char *name, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool removable)
Definition scip_lp.c:1429
int SCIProwGetRank(SCIP_ROW *row)
Definition lp.c:17775
void SCIProwChgRank(SCIP_ROW *row, int rank)
Definition lp.c:17928
SCIP_ROWEXACT * SCIProwGetRowExact(SCIP_ROW *row)
Definition lp.c:17959
int SCIPgetRowNumIntCols(SCIP *scip, SCIP_ROW *row)
Definition scip_lp.c:1832
SCIP_RETCODE SCIPincludeSepaBasic(SCIP *scip, SCIP_SEPA **sepa, const char *name, const char *desc, int priority, int freq, SCIP_Real maxbounddist, SCIP_Bool usessubscip, SCIP_Bool delay, SCIP_DECL_SEPAEXECLP((*sepaexeclp)), SCIP_DECL_SEPAEXECSOL((*sepaexecsol)), SCIP_SEPADATA *sepadata)
Definition scip_sepa.c:115
int SCIPsepaGetFreq(SCIP_SEPA *sepa)
Definition sepa.c:790
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:173
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition sepa.c:746
int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
Definition sepa.c:893
void SCIPsepaMarkExact(SCIP_SEPA *sepa)
Definition sepa.c:811
SCIP_RETCODE SCIPsetSepaExit(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:205
SCIP_RETCODE SCIPsetSepaInit(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:189
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition sepa.c:636
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition sepa.c:646
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa,)
Definition scip_sepa.c:157
void SCIPsetSepaIsParentsepa(SCIP *scip, SCIP_SEPA *sepa)
Definition scip_sepa.c:309
void SCIPsetSepaParentsepa(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPA *parentsepa)
Definition scip_sepa.c:324
int SCIPgetMaxDepth(SCIP *scip)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
int SCIPgetNCutsFound(SCIP *scip)
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFrac(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPround(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Real SCIPsumepsilon(SCIP *scip)
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
SCIP_RETCODE SCIPincVarGMISumScore(SCIP *scip, SCIP_VAR *var, SCIP_Real gmieff)
Definition scip_var.c:12375
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23485
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24174
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
SCIP_RETCODE SCIPsetVarLastGMIScore(SCIP *scip, SCIP_VAR *var, SCIP_Real gmieff)
Definition scip_var.c:12429
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition misc.c:10245
SCIP_RETCODE SCIPincludeSepaGomory(SCIP *scip)
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition misc.c:10827
return SCIP_OKAY
SCIPfreeRandom(scip, &heurdata->randnumgen)
SCIP_Longint ncalls
int c
int maxdepth
int depth
SCIP_Bool cutoff
SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE))
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
SCIP_Real frac
static SCIP_VAR ** vars
memory allocation routines
public methods for LP management
public methods for LP management
public methods for message output
#define SCIPdebug(x)
Definition pub_message.h:93
public data structures and miscellaneous methods
methods for sorting joint arrays of various types
public methods for separators
public methods for problem variables
public methods for branching rule plugins and branching
public methods for certified solving
public methods for cuts and aggregation rows
public methods for exact solving
general public methods
public methods for the LP relaxation, rows and columns
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 random numbers
public methods for separator plugins
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
#define SEPA_PRIORITY
#define SEPA_DELAY
#define DEFAULT_DYNAMICCUTS
#define SEPA_DESC
#define MAKECONTINTEGRAL
#define SEPA_USESSUBSCIP
#define SEPA_MAXBOUNDDIST
#define SEPA_FREQ
#define SEPA_NAME
#define DEFAULT_MAXRANKINTEGRAL
#define DEFAULT_MAXRANK
static SCIP_RETCODE addCut(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_VAR **vars, int c, SCIP_Longint maxdnom, SCIP_Real maxscale, int cutnnz, int *cutinds, SCIP_Real *cutcoefs, SCIP_Real cutefficacy, SCIP_Real cutrhs, SCIP_Bool cutislocal, int cutrank, SCIP_Bool strongcg, SCIP_Bool *cutoff, int *naddedcuts)
#define DEFAULT_TRYSTRONGCG
#define DEFAULT_MAKEINTEGRAL
#define DEFAULT_DELAYEDCUTS
#define DEFAULT_SIDETYPEBASIS
static SCIP_RETCODE evaluateCutNumerics(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_ROW *cut, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool *useful)
#define DEFAULT_AWAY
#define DEFAULT_FORCECUTS
#define MAXAGGRLEN(nvars)
#define DEFAULT_SEPARATEROWS
#define DEFAULT_GENBOTHGOMSCG
Gomory MIR Cuts.
struct SCIP_AggrRow SCIP_AGGRROW
Definition type_cuts.h:37
struct SCIP_Row SCIP_ROW
Definition type_lp.h:105
struct SCIP_Col SCIP_COL
Definition type_lp.h:99
@ SCIP_LPSOLSTAT_OPTIMAL
Definition type_lp.h:44
struct SCIP_RandNumGen SCIP_RANDNUMGEN
Definition type_misc.h:127
@ SCIP_DIDNOTRUN
Definition type_result.h:42
@ SCIP_CUTOFF
Definition type_result.h:48
@ SCIP_DIDNOTFIND
Definition type_result.h:44
@ SCIP_SEPARATED
Definition type_result.h:49
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_SepaData SCIP_SEPADATA
Definition type_sepa.h:52
#define SCIP_DECL_SEPAEXECSOL(x)
Definition type_sepa.h:166
#define SCIP_DECL_SEPAEXECLP(x)
Definition type_sepa.h:136
#define SCIP_DECL_SEPAFREE(x)
Definition type_sepa.h:69
#define SCIP_DECL_SEPAEXIT(x)
Definition type_sepa.h:85
struct SCIP_Sepa SCIP_SEPA
Definition type_sepa.h:51
#define SCIP_DECL_SEPACOPY(x)
Definition type_sepa.h:61
#define SCIP_DECL_SEPAINIT(x)
Definition type_sepa.h:77
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_VARTYPE_CONTINUOUS
Definition type_var.h:71