Scippy

SCIP

Solving Constraint Integer Programs

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-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/**@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. */
321 SCIP_CALL( SCIPaddRow(scip, cut, TRUE, cutoff) );
322 ++(*naddedcuts);
323 if( SCIPisCertified(scip) )
324 {
327 }
328 }
329 else
330 {
331 SCIP_Bool useful;
332
333 assert(SCIPisInfinity(scip, -SCIProwGetLhs(cut)));
334 assert(!SCIPisInfinity(scip, SCIProwGetRhs(cut)));
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 */
367 SCIP_CALL( SCIPaddRow(scip, cut, FALSE, cutoff) );
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}*/
435 SCIP_SEPADATA* sepadata;
436
437 assert(strcmp(SCIPsepaGetName(sepa), SEPA_NAME) == 0);
438
439 /* free separator data */
440 sepadata = SCIPsepaGetData(sepa);
441 assert(sepadata != NULL);
442
443 SCIPfreeBlockMemory(scip, &sepadata);
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{
455 SCIP_SEPADATA* sepadata;
456
457 sepadata = SCIPsepaGetData(sepa);
458 assert(sepadata != NULL);
459
460 /* create and initialize random number generator */
461 SCIP_CALL( SCIPcreateRandom(scip, &sepadata->randnumgen, DEFAULT_RANDSEED, TRUE) );
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}*/
470 SCIP_SEPADATA* sepadata;
471
472 sepadata = SCIPsepaGetData(sepa);
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}*/
485 SCIP_SEPADATA* sepadata;
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;
505 SCIP_Bool cutoff;
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
525 *result = SCIP_DIDNOTRUN;
526
527 sepadata = SCIPsepaGetData(sepa);
528 assert(sepadata != NULL);
529
530 ncalls = SCIPsepaGetNCallsAtNode(sepa);
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 */
574 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
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 */
586 maxdepth = SCIPgetMaxDepth(scip);
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 */
609 SCIP_CALL( SCIPallocBufferArray(scip, &cutcoefs, nvars) );
610 SCIP_CALL( SCIPallocClearBufferArray(scip, &cutinds, nvars) );
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 {
640 frac = SCIPfeasFrac(scip, SCIPcolGetPrimsol(cols[c]));
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 )
802 *result = SCIP_CUTOFF;
803 else if ( naddedcuts > 0 )
804 *result = SCIP_SEPARATED;
805 else
806 *result = SCIP_DIDNOTFIND;
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
822 *result = SCIP_DIDNOTRUN;
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
833 *result = SCIP_DIDNOTRUN;
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{
843 SCIP_SEPADATA* sepadata;
844 SCIP_SEPA* sepa;
845
846 /* create separator data */
847 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
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}
methods for the aggregation rows
#define NULL
Definition: def.h:248
#define SCIP_MAXSTRLEN
Definition: def.h:269
#define SCIP_Longint
Definition: def.h:141
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
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
Definition: scip_message.h:78
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)
Definition: scip_branch.c:436
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
Definition: intervalarith.h:65
SCIP_RETCODE SCIPcreateRowExactFromRow(SCIP *scip, SCIP_ROW *fprow)
Definition: scip_lpexact.c:285
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 SCIPsetSepaExit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAEXIT((*sepaexit)))
Definition: scip_sepa.c:205
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
const char * SCIPsepaGetName(SCIP_SEPA *sepa)
Definition: sepa.c:746
int SCIPsepaGetNCallsAtNode(SCIP_SEPA *sepa)
Definition: sepa.c:893
SCIP_RETCODE SCIPsetSepaFree(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAFREE((*sepafree)))
Definition: scip_sepa.c:173
void SCIPsepaMarkExact(SCIP_SEPA *sepa)
Definition: sepa.c:811
SCIP_SEPADATA * SCIPsepaGetData(SCIP_SEPA *sepa)
Definition: sepa.c:636
void SCIPsepaSetData(SCIP_SEPA *sepa, SCIP_SEPADATA *sepadata)
Definition: sepa.c:646
void SCIPsetSepaIsParentsepa(SCIP *scip, SCIP_SEPA *sepa)
Definition: scip_sepa.c:309
SCIP_RETCODE SCIPsetSepaCopy(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPACOPY((*sepacopy)))
Definition: scip_sepa.c:157
void SCIPsetSepaParentsepa(SCIP *scip, SCIP_SEPA *sepa, SCIP_SEPA *parentsepa)
Definition: scip_sepa.c:324
SCIP_RETCODE SCIPsetSepaInit(SCIP *scip, SCIP_SEPA *sepa, SCIP_DECL_SEPAINIT((*sepainit)))
Definition: scip_sepa.c:189
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
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:10245
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
SCIP_RETCODE SCIPincludeSepaGomory(SCIP *scip)
Definition: sepa_gomory.c:839
void SCIPsortDownRealInt(SCIP_Real *realarray, int *intarray, int len)
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10827
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
Definition: sepa_gomory.c:91
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)
Definition: sepa_gomory.c:196
static SCIP_DECL_SEPAEXECLP(sepaExeclpGomory)
Definition: sepa_gomory.c:483
static SCIP_DECL_SEPAEXIT(sepaExitGomory)
Definition: sepa_gomory.c:468
#define DEFAULT_TRYSTRONGCG
Definition: sepa_gomory.c:110
#define BOUNDSWITCH
Definition: sepa_gomory.c:114
#define SEPA_DELAY
Definition: sepa_gomory.c:95
#define DEFAULT_DYNAMICCUTS
Definition: sepa_gomory.c:103
#define DEFAULT_MAKEINTEGRAL
Definition: sepa_gomory.c:105
#define POSTPROCESS
Definition: sepa_gomory.c:115
#define SEPA_DESC
Definition: sepa_gomory.c:90
#define DEFAULT_MAXRANKINTEGRAL
Definition: sepa_gomory.c:102
static SCIP_DECL_SEPAFREE(sepaFreeGomory)
Definition: sepa_gomory.c:433
#define MAKECONTINTEGRAL
Definition: sepa_gomory.c:119
#define DEFAULT_MAXROUNDSROOT
Definition: sepa_gomory.c:98
#define SEPA_USESSUBSCIP
Definition: sepa_gomory.c:94
#define DEFAULT_DELAYEDCUTS
Definition: sepa_gomory.c:108
#define VARTYPEUSEVBDS
Definition: sepa_gomory.c:116
#define DEFAULT_SIDETYPEBASIS
Definition: sepa_gomory.c:109
#define FIXINTEGRALRHS
Definition: sepa_gomory.c:118
static SCIP_DECL_SEPACOPY(sepaCopyGomory)
Definition: sepa_gomory.c:418
#define DEFAULT_MAXSEPACUTSROOT
Definition: sepa_gomory.c:100
#define DEFAULT_MAXRANK
Definition: sepa_gomory.c:101
#define SEPA_MAXBOUNDDIST
Definition: sepa_gomory.c:93
static SCIP_DECL_SEPAINIT(sepaInitGomory)
Definition: sepa_gomory.c:453
static SCIP_RETCODE evaluateCutNumerics(SCIP *scip, SCIP_SEPADATA *sepadata, SCIP_ROW *cut, SCIP_Longint maxdnom, SCIP_Real maxscale, SCIP_Bool *useful)
Definition: sepa_gomory.c:151
#define DEFAULT_AWAY
Definition: sepa_gomory.c:104
#define DEFAULT_FORCECUTS
Definition: sepa_gomory.c:106
#define SEPA_FREQ
Definition: sepa_gomory.c:92
#define DEFAULT_RANDSEED
Definition: sepa_gomory.c:112
#define MAXAGGRLEN(nvars)
Definition: sepa_gomory.c:121
static SCIP_DECL_SEPAEXECSOL(sepaExecsolDummy)
Definition: sepa_gomory.c:829
#define DEFAULT_MAXSEPACUTS
Definition: sepa_gomory.c:99
#define SEPA_NAME
Definition: sepa_gomory.c:89
#define DEFAULT_MAXROUNDS
Definition: sepa_gomory.c:97
#define DEFAULT_SEPARATEROWS
Definition: sepa_gomory.c:107
#define DEFAULT_GENBOTHGOMSCG
Definition: sepa_gomory.c:111
Gomory MIR Cuts.
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:44
@ 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_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
struct SCIP_SepaData SCIP_SEPADATA
Definition: type_sepa.h:52
@ SCIP_VARTYPE_CONTINUOUS
Definition: type_var.h:71