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#include <string.h>
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 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
423
424 /* call inclusion method of separator */
426
427 return SCIP_OKAY;
428}
429
430/** destructor of separator to free user data (called when SCIP is exiting) */
431/**! [SnippetSepaFreeGomory] */
432static
433SCIP_DECL_SEPAFREE(sepaFreeGomory)
434{ /*lint --e{715}*/
436
437 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
438
439 /* free separator data */
441 assert(sepadata != NULL);
442
444
445 SCIPsepaSetData(sepa, NULL);
446
447 return SCIP_OKAY;
448}
449/**! [SnippetSepaFreeGomory] */
450
451/** initialization method of separator (called after problem was transformed) */
452static
453SCIP_DECL_SEPAINIT(sepaInitGomory)
454{
456
458 assert(sepadata != NULL);
459
460 /* create and initialize random number generator */
462
463 return SCIP_OKAY;
464}
465
466/** deinitialization method of separator (called before transformed problem is freed) */
467static
468SCIP_DECL_SEPAEXIT(sepaExitGomory)
469{ /*lint --e{715}*/
471
473 assert(sepadata != NULL);
474
475 SCIPfreeRandom(scip, &sepadata->randnumgen);
476
477 return SCIP_OKAY;
478}
479
480
481/** LP solution separation method of separator */
482static
483SCIP_DECL_SEPAEXECLP(sepaExeclpGomory)
484{ /*lint --e{715}*/
486 SCIP_VAR** vars;
487 SCIP_COL** cols;
488 SCIP_ROW** rows;
489 SCIP_AGGRROW* aggrrow;
490 SCIP_VAR* var;
491 SCIP_Real* binvrow;
492 SCIP_Real* cutcoefs;
493 SCIP_Real* basisfrac;
494 SCIP_Real* cutefficacies;
495 int* basisind;
496 int* basisperm;
497 int* inds;
498 int* cutinds;
499 int* colindsproducedcut;
500 SCIP_Real maxscale;
501 SCIP_Real minfrac;
502 SCIP_Real maxfrac;
503 SCIP_Real maxcutefficacy;
504 SCIP_Longint maxdnom;
506 SCIP_Bool separatescg;
507 SCIP_Bool separategmi;
508 int naddedcuts;
509 int nvars;
510 int ncols;
511 int nrows;
512 int ncalls;
513 int maxdepth;
514 int maxsepacuts;
515 int freq;
516 int c;
517 int i;
518 int j;
519
520 assert(sepa != NULL);
521 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
522 assert(scip != NULL);
523 assert(result != NULL);
524
526
528 assert(sepadata != NULL);
529
531
532 minfrac = sepadata->away;
533 maxfrac = 1.0 - sepadata->away;
534
535 /* only call separator, if we are not close to terminating */
536 if( SCIPisStopped(scip) )
537 return SCIP_OKAY;
538
539 /* only call the gomory cut separator a given number of times at each node */
540 if( (depth == 0 && sepadata->maxroundsroot >= 0 && ncalls >= sepadata->maxroundsroot)
541 || (depth > 0 && sepadata->maxrounds >= 0 && ncalls >= sepadata->maxrounds) )
542 return SCIP_OKAY;
543
544 /* only call separator, if an optimal LP solution is at hand */
546 return SCIP_OKAY;
547
548 /* only call separator, if the LP solution is basic */
549 if( !SCIPisLPSolBasic(scip) )
550 return SCIP_OKAY;
551
552 /* only call separator, if there are fractional variables */
553 if( SCIPgetNLPBranchCands(scip) == 0 )
554 return SCIP_OKAY;
555
556 /* check whether strong CG cuts should be separated */
557 freq = SCIPsepaGetFreq(sepadata->strongcg);
558 if( freq > 0 )
559 separatescg = (depth % freq == 0);
560 else
561 separatescg = (freq == depth);
562
563 /* check whether Gomory MI cuts should be separated */
564 freq = SCIPsepaGetFreq(sepadata->gomory);
565 if( freq > 0 )
566 separategmi = (depth % freq == 0);
567 else
568 separategmi = (freq == depth);
569
570 if( !separatescg && !separategmi )
571 return SCIP_OKAY;
572
573 /* get variables data */
575
576 /* get LP data */
577 SCIP_CALL( SCIPgetLPColsData(scip, &cols, &ncols) );
578 SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
579 if( ncols == 0 || nrows == 0 )
580 return SCIP_OKAY;
581
582 /* set the maximal denominator in rational representation of gomory cut and the maximal scale factor to
583 * scale resulting cut to integral values to avoid numerical instabilities
584 */
585 /**@todo find better but still stable gomory cut settings: look at dcmulti, gesa3, khb0525, misc06, p2756 */
587 if( depth == 0 )
588 {
589 maxdnom = 1000;
590 maxscale = 1000.0;
591 }
592 else if( depth <= maxdepth/4 )
593 {
594 maxdnom = 1000;
595 maxscale = 1000.0;
596 }
597 else if( depth <= maxdepth/2 )
598 {
599 maxdnom = 100;
600 maxscale = 100.0;
601 }
602 else
603 {
604 maxdnom = 10;
605 maxscale = 10.0;
606 }
607
608 /* allocate temporary memory */
611 SCIP_CALL( SCIPallocBufferArray(scip, &basisind, nrows) );
612 SCIP_CALL( SCIPallocBufferArray(scip, &basisperm, nrows) );
613 SCIP_CALL( SCIPallocBufferArray(scip, &basisfrac, nrows) );
614 SCIP_CALL( SCIPallocBufferArray(scip, &binvrow, nrows) );
615 SCIP_CALL( SCIPallocBufferArray(scip, &inds, nrows) );
616 SCIP_CALL( SCIPallocBufferArray(scip, &cutefficacies, nrows) );
617 SCIP_CALL( SCIPallocBufferArray(scip, &colindsproducedcut, nrows) );
618 SCIP_CALL( SCIPaggrRowCreate(scip, &aggrrow) );
619
620 /* get basis indices */
621 SCIP_CALL( SCIPgetLPBasisInd(scip, basisind) );
622
623 for( i = 0; i < nrows; ++i )
624 {
625 SCIP_Real frac = 0.0;
626
627 c = basisind[i];
628 cutefficacies[i] = 0.0;
629
630 basisperm[i] = i;
631
632 colindsproducedcut[i] = -1;
633
634 if( c >= 0 )
635 {
636 assert(c < ncols);
637 var = SCIPcolGetVar(cols[c]);
639 {
641 frac = MIN(frac, 1.0 - frac);
642 }
643 }
644 else if( sepadata->separaterows )
645 {
646 SCIP_ROW* row;
647
648 assert(0 <= -c-1 && -c-1 < nrows);
649 row = rows[-c-1];
650 /* We allow separating on rows with a 'slack' implied integral variable */
652 {
654 frac = MIN(frac, 1.0 - frac);
655 }
656 }
657
658 if( frac >= minfrac )
659 {
660 /* slightly change fractionality to have random order for equal fractions */
661 basisfrac[i] = frac + SCIPrandomGetReal(sepadata->randnumgen, -1e-6, 1e-6);
662 }
663 else
664 {
665 basisfrac[i] = 0.0;
666 }
667 }
668
669 /* sort basis indices by fractionality */
670 SCIPsortDownRealInt(basisfrac, basisperm, nrows);
671
672 /* get the maximal number of cuts allowed in a separation round */
673 if( depth == 0 )
674 maxsepacuts = sepadata->maxsepacutsroot;
675 else
676 maxsepacuts = sepadata->maxsepacuts;
677
678 SCIPdebugMsg(scip, "searching gomory cuts: %d cols, %d rows, maxdnom=%" SCIP_LONGINT_FORMAT ", maxscale=%g, maxcuts=%d\n",
679 ncols, nrows, maxdnom, maxscale, maxsepacuts);
680
681 cutoff = FALSE;
682 naddedcuts = 0;
683
684 /* for all basic columns belonging to integer variables, try to generate a gomory cut */
685 for( i = 0; i < nrows && naddedcuts < maxsepacuts && !SCIPisStopped(scip) && !cutoff; ++i )
686 {
687 SCIP_Real cutrhs;
688 SCIP_Real cutefficacy = 0.0;
689 SCIP_Bool success;
690 SCIP_Bool cutislocal;
691 SCIP_Bool strongcgsuccess = FALSE;
692 int ninds = -1;
693 int cutnnz;
694 int cutrank;
695
696 if( basisfrac[i] == 0.0 )
697 break;
698
699 j = basisperm[i];
700 c = basisind[j];
701
702 /* get the row of B^-1 for this basic integer variable with fractional solution value */
703 SCIP_CALL( SCIPgetLPBInvRow(scip, j, binvrow, inds, &ninds) );
704
705 SCIP_CALL( SCIPaggrRowSumRows(scip, aggrrow, binvrow, inds, ninds,
706 sepadata->sidetypebasis, allowlocal, SCIPallowNegSlack(scip) ? 2 : 0, (int) MAXAGGRLEN(nvars), &success) );
707
708 if( !success )
709 continue;
710
711 /* try to create a strong CG cut out of the aggregation row */
712 if( separatescg && !SCIPisExact(scip) )
713 {
714 SCIP_CALL( SCIPcalcStrongCG(scip, NULL, POSTPROCESS, BOUNDSWITCH, VARTYPEUSEVBDS, allowlocal, minfrac, maxfrac,
715 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, &cutrank, &cutislocal, &strongcgsuccess) );
716
717 /* if we want to generate both cuts, add cut and reset cutefficacy and strongcgsuccess */
718 if( strongcgsuccess && sepadata->genbothgomscg )
719 {
720 assert(allowlocal || !cutislocal); /*lint !e644*/
721 SCIP_CALL( addCut(scip, sepadata, vars, c, maxdnom, maxscale, cutnnz, cutinds, cutcoefs, cutefficacy, cutrhs,
722 cutislocal, cutrank, TRUE, &cutoff, &naddedcuts) );
723 if( c >= 0 )
724 {
725 cutefficacies[i] = cutefficacy;
726 colindsproducedcut[i] = c;
727 }
728 cutefficacy = 0.0;
729 strongcgsuccess = FALSE;
730 if( cutoff )
731 break;
732 }
733 }
734 /* try to create Gomory cut out of the aggregation row */
735 if( separategmi )
736 {
737 /* SCIPcalcMIR will only override the cut if its efficacy is larger than the one of the strongcg cut */
739 minfrac, maxfrac, 1.0, aggrrow, cutcoefs, &cutrhs, cutinds, &cutnnz, &cutefficacy, &cutrank, &cutislocal, &success) );
740
741 if( success || strongcgsuccess )
742 {
743 assert(allowlocal || !cutislocal); /*lint !e644*/
744 if( success )
745 strongcgsuccess = FALSE; /* Set strongcgsuccess to FALSE, since the MIR cut has overriden the strongcg cut. */
746
747 SCIP_CALL( addCut(scip, sepadata, vars, c, maxdnom, maxscale, cutnnz, cutinds, cutcoefs, cutefficacy, cutrhs,
748 cutislocal, cutrank, strongcgsuccess, &cutoff, &naddedcuts) );
749 if( c >= 0 )
750 {
751 cutefficacies[i] = cutefficacy;
752 colindsproducedcut[i] = c;
753 }
754 }
755 }
756 if( SCIPisCertified(scip) )
757 {
760 }
761 }
762
763 /* Add normalized efficacy GMI statistics to history */
764 maxcutefficacy = 0.0;
765 for( i = 0; i < nrows; ++i )
766 {
767 if( cutefficacies[i] > maxcutefficacy && colindsproducedcut[i] >= 0 )
768 {
769 maxcutefficacy = cutefficacies[i];
770 }
771 }
772
773 for( i = 0; i < nrows; ++i )
774 {
775 if( colindsproducedcut[i] >= 0 && SCIPisEfficacious(scip, cutefficacies[i]) )
776 {
777 assert( maxcutefficacy > 0.0 );
778 var = SCIPcolGetVar(cols[colindsproducedcut[i]]);
779 SCIP_CALL( SCIPsetVarLastGMIScore(scip, var, cutefficacies[i] / maxcutefficacy) );
780 SCIP_CALL( SCIPincVarGMISumScore(scip, var, cutefficacies[i] / maxcutefficacy) );
781 }
782 }
783
784 /* free temporary memory */
785 SCIPaggrRowFree(scip, &aggrrow);
786 SCIPfreeBufferArray(scip, &colindsproducedcut);
787 SCIPfreeBufferArray(scip, &cutefficacies);
789 SCIPfreeBufferArray(scip, &binvrow);
790 SCIPfreeBufferArray(scip, &basisfrac);
791 SCIPfreeBufferArray(scip, &basisperm);
792 SCIPfreeBufferArray(scip, &basisind);
793 SCIPfreeBufferArray(scip, &cutinds);
794 SCIPfreeBufferArray(scip, &cutcoefs);
795
796 SCIPdebugMsg(scip, "end searching gomory cuts: found %d cuts\n", naddedcuts);
797
798 sepadata->lastncutsfound = SCIPgetNCutsFound(scip);
799
800 /* evaluate the result of the separation */
801 if( cutoff )
803 else if ( naddedcuts > 0 )
805 else
807
808 return SCIP_OKAY;
809}
810
811
812/*
813 * separator specific interface methods
814 */
815
816/** LP solution separation method of dummy separator */
817static
818SCIP_DECL_SEPAEXECLP(sepaExeclpDummy)
819{ /*lint --e{715}*/
820 assert( result != NULL );
821
823
824 return SCIP_OKAY;
825}
826
827/** arbitrary primal solution separation method of dummy separator */
828static
829SCIP_DECL_SEPAEXECSOL(sepaExecsolDummy)
830{ /*lint --e{715}*/
831 assert( result != NULL );
832
834
835 return SCIP_OKAY;
836}
837
838/** creates the Gomory MIR cut separator and includes it in SCIP */
840 SCIP* scip /**< SCIP data structure */
841 )
842{
844 SCIP_SEPA* sepa;
845
846 /* create separator data */
848 sepadata->lastncutsfound = 0;
849
850 /* include separator */
853 sepaExeclpGomory, NULL,
854 sepadata) );
855
856 assert(sepa != NULL);
857
858 /* gomory is safe to use in exact solving mode */
859 SCIPsepaMarkExact(sepa);
860
861 SCIP_CALL( SCIPincludeSepaBasic(scip, &sepadata->strongcg, "strongcg", "separator for strong CG cuts", -100000, SEPA_FREQ, 0.0,
862 SEPA_USESSUBSCIP, FALSE, sepaExeclpDummy, sepaExecsolDummy, NULL) );
863 assert(sepadata->strongcg != NULL);
864
865 SCIP_CALL( SCIPincludeSepaBasic(scip, &sepadata->gomory, "gomorymi", "separator for Gomory mixed-integer cuts", -100000, SEPA_FREQ, 0.0,
866 SEPA_USESSUBSCIP, FALSE, sepaExeclpDummy, sepaExecsolDummy, NULL) );
867 assert(sepadata->gomory != NULL);
868
869 /* set non-NULL pointers to callback methods */
870 SCIP_CALL( SCIPsetSepaCopy(scip, sepa, sepaCopyGomory) );
871 SCIP_CALL( SCIPsetSepaFree(scip, sepa, sepaFreeGomory) );
872 SCIP_CALL( SCIPsetSepaInit(scip, sepa, sepaInitGomory) );
873 SCIP_CALL( SCIPsetSepaExit(scip, sepa, sepaExitGomory) );
874
875 /* mark main separator as a parent */
877
878 /* set pointer from child separators to main separator */
879 SCIPsetSepaParentsepa(scip, sepadata->strongcg, sepa);
880 SCIPsetSepaParentsepa(scip, sepadata->gomory, sepa);
881
882 /* add separator parameters */
884 "separating/gomory/maxrounds",
885 "maximal number of gomory separation rounds per node (-1: unlimited)",
886 &sepadata->maxrounds, FALSE, DEFAULT_MAXROUNDS, -1, INT_MAX, NULL, NULL) );
888 "separating/gomory/maxroundsroot",
889 "maximal number of gomory separation rounds in the root node (-1: unlimited)",
890 &sepadata->maxroundsroot, FALSE, DEFAULT_MAXROUNDSROOT, -1, INT_MAX, NULL, NULL) );
892 "separating/gomory/maxsepacuts",
893 "maximal number of gomory cuts separated per separation round",
894 &sepadata->maxsepacuts, FALSE, DEFAULT_MAXSEPACUTS, 0, INT_MAX, NULL, NULL) );
896 "separating/gomory/maxsepacutsroot",
897 "maximal number of gomory cuts separated per separation round in the root node",
898 &sepadata->maxsepacutsroot, FALSE, DEFAULT_MAXSEPACUTSROOT, 0, INT_MAX, NULL, NULL) );
900 "separating/gomory/maxrank",
901 "maximal rank of a gomory cut that could not be scaled to integral coefficients (-1: unlimited)",
902 &sepadata->maxrank, FALSE, DEFAULT_MAXRANK, -1, INT_MAX, NULL, NULL) );
904 "separating/gomory/maxrankintegral",
905 "maximal rank of a gomory cut that could be scaled to integral coefficients (-1: unlimited)",
906 &sepadata->maxrankintegral, FALSE, DEFAULT_MAXRANKINTEGRAL, -1, INT_MAX, NULL, NULL) );
908 "separating/gomory/away",
909 "minimal integrality violation of a basis variable in order to try Gomory cut",
910 &sepadata->away, FALSE, DEFAULT_AWAY, 1e-4, 0.5, NULL, NULL) );
912 "separating/gomory/dynamiccuts",
913 "should generated cuts be removed from the LP if they are no longer tight?",
914 &sepadata->dynamiccuts, FALSE, DEFAULT_DYNAMICCUTS, NULL, NULL) );
916 "separating/gomory/makeintegral",
917 "try to scale cuts to integral coefficients",
918 &sepadata->makeintegral, TRUE, DEFAULT_MAKEINTEGRAL, NULL, NULL) );
920 "separating/gomory/forcecuts",
921 "if conversion to integral coefficients failed still consider the cut",
922 &sepadata->forcecuts, TRUE, DEFAULT_FORCECUTS, NULL, NULL) );
924 "separating/gomory/separaterows",
925 "separate rows with integral slack",
926 &sepadata->separaterows, TRUE, DEFAULT_SEPARATEROWS, NULL, NULL) );
928 "separating/gomory/delayedcuts",
929 "should cuts be added to the delayed cut pool?",
930 &sepadata->delayedcuts, TRUE, DEFAULT_DELAYEDCUTS, NULL, NULL) );
932 "separating/gomory/sidetypebasis",
933 "choose side types of row (lhs/rhs) based on basis information?",
934 &sepadata->sidetypebasis, TRUE, DEFAULT_SIDETYPEBASIS, NULL, NULL) );
936 "separating/gomory/trystrongcg",
937 "try to generate strengthened Chvatal-Gomory cuts?",
938 &sepadata->trystrongcg, TRUE, DEFAULT_TRYSTRONGCG, NULL, NULL) );
940 "separating/gomory/genbothgomscg",
941 "Should both Gomory and strong CG cuts be generated (otherwise take best)?",
942 &sepadata->genbothgomscg, TRUE, DEFAULT_GENBOTHGOMSCG, NULL, NULL) );
943
944 return SCIP_OKAY;
945}
#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:255
#define SCIP_MAXSTRLEN
Definition def.h:276
#define SCIP_Longint
Definition def.h:148
#define SCIP_Bool
Definition def.h:98
#define MIN(x, y)
Definition def.h:231
#define SCIP_Real
Definition def.h:163
#define TRUE
Definition def.h:100
#define FALSE
Definition def.h:101
#define SCIP_LONGINT_FORMAT
Definition def.h:155
#define REALABS(x)
Definition def.h:189
#define SCIP_CALL(x)
Definition def.h:362
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:7923
SCIP_RETCODE SCIPaggrRowCreate(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition cuts.c:2668
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:13281
void SCIPaggrRowFree(SCIP *scip, SCIP_AGGRROW **aggrrow)
Definition cuts.c:2700
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:3523
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:24268
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition var.c:23453
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition var.c:24142
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24234
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24120
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
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