Scippy

SCIP

Solving Constraint Integer Programs

scip_cut.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 scip_cut.c
26 * @ingroup OTHER_CFILES
27 * @brief public methods for cuts and aggregation rows
28 * @author Tobias Achterberg
29 * @author Timo Berthold
30 * @author Gerald Gamrath
31 * @author Leona Gottwald
32 * @author Stefan Heinz
33 * @author Gregor Hendel
34 * @author Thorsten Koch
35 * @author Alexander Martin
36 * @author Marc Pfetsch
37 * @author Michael Winkler
38 * @author Kati Wolter
39 *
40 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
41 */
42
43/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44
45#include "scip/cutpool.h"
46#include "scip/debug.h"
47#include "scip/lp.h"
48#include "scip/prob.h"
49#include "scip/pub_cutpool.h"
50#include "scip/pub_lp.h"
51#include "scip/pub_message.h"
52#include "scip/scip_conflict.h"
53#include "scip/scip_cut.h"
54#include "scip/scip_numerics.h"
55#include "scip/scip_tree.h"
56#include "scip/sepastore.h"
57#include "scip/set.h"
58#include "scip/solve.h"
59#include "scip/struct_lp.h"
60#include "scip/struct_mem.h"
61#include "scip/struct_scip.h"
62#include "scip/struct_set.h"
63#include "scip/tree.h"
64
65/** returns row's cutoff distance in the direction of the given primal solution
66 *
67 * @return the cutoff distance of the cut with respect to the LP solution in the direction of the given primal solution
68 *
69 * @pre This method can be called if @p scip is in one of the following stages:
70 * - \ref SCIP_STAGE_SOLVING
71 */
73 SCIP* scip, /**< SCIP data structure */
74 SCIP_SOL* sol, /**< solution to compute direction for cutoff distance; must not be NULL */
75 SCIP_ROW* cut /**< separated cut */
76 )
77{
78 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetCutLPSolCutoffDistance", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
79
80 assert(sol != NULL);
81
82 return SCIProwGetLPSolCutoffDistance(cut, scip->set, scip->stat, sol, scip->lp);
83}
84
85/** returns efficacy of the cut with respect to the given primal solution or the current LP solution:
86 * e = -feasibility/norm
87 *
88 * @return the efficacy of the cut with respect to the given primal solution or the current LP solution:
89 * e = -feasibility/norm
90 *
91 * @pre This method can be called if @p scip is in one of the following stages:
92 * - \ref SCIP_STAGE_SOLVING
93 */
95 SCIP* scip, /**< SCIP data structure */
96 SCIP_SOL* sol, /**< primal CIP solution, or NULL for current LP solution */
97 SCIP_ROW* cut /**< separated cut */
98 )
99{
101
102 if( sol == NULL )
103 return SCIProwGetLPEfficacy(cut, scip->set, scip->stat, scip->lp);
104 else
105 return SCIProwGetSolEfficacy(cut, scip->set, scip->stat, sol);
106}
107
108/** returns whether the cut's efficacy with respect to the given primal solution or the current LP solution is greater
109 * than the minimal cut efficacy
110 *
111 * @return TRUE if the cut's efficacy with respect to the given primal solution or the current LP solution is greater
112 * than the minimal cut efficacy, otherwise FALSE
113 *
114 * @pre This method can be called if @p scip is in one of the following stages:
115 * - \ref SCIP_STAGE_SOLVING
116 */
118 SCIP* scip, /**< SCIP data structure */
119 SCIP_SOL* sol, /**< primal CIP solution, or NULL for current LP solution */
120 SCIP_ROW* cut /**< separated cut */
121 )
122{
124
125 if( sol == NULL )
126 return SCIProwIsLPEfficacious(cut, scip->set, scip->stat, scip->lp, (SCIPtreeGetCurrentDepth(scip->tree) == 0));
127 else
128 return SCIProwIsSolEfficacious(cut, scip->set, scip->stat, sol, (SCIPtreeGetCurrentDepth(scip->tree) == 0));
129}
130
131/** checks if the given cut's efficacy is larger than the minimal cut efficacy
132 *
133 * @return TRUE if the given cut's efficacy is larger than the minimal cut efficacy, otherwise FALSE
134 */
136 SCIP* scip, /**< SCIP data structure */
137 SCIP_Real efficacy /**< efficacy of the cut */
138 )
139{
140 assert(scip != NULL);
141
142 return SCIPsetIsEfficacious(scip->set, (SCIPtreeGetCurrentDepth(scip->tree) == 0), efficacy);
143}
144
145/** calculates the efficacy norm of the given vector, which depends on the "separating/efficacynorm" parameter
146 *
147 * @return the efficacy norm of the given vector, which depends on the "separating/efficacynorm" parameter
148 */
150 SCIP* scip, /**< SCIP data structure */
151 SCIP_Real* vals, /**< array of values */
152 int nvals /**< number of values */
153 )
154{
155 SCIP_Real norm;
156 int i;
157
158 assert(scip != NULL);
159 assert(scip->set != NULL);
160
161 norm = 0.0;
162 switch( scip->set->sepa_efficacynorm )
163 {
164 case 'e':
165 for( i = 0; i < nvals; ++i )
166 norm += SQR(vals[i]);
167 norm = sqrt(norm);
168 break;
169 case 'm':
170 for( i = 0; i < nvals; ++i )
171 {
172 SCIP_Real absval;
173
174 absval = REALABS(vals[i]);
175 norm = MAX(norm, absval);
176 }
177 break;
178 case 's':
179 for( i = 0; i < nvals; ++i )
180 norm += REALABS(vals[i]);
181 break;
182 case 'd':
183 for( i = 0; i < nvals; ++i )
184 {
185 if( !SCIPisZero(scip, vals[i]) )
186 {
187 norm = 1.0;
188 break;
189 }
190 }
191 break;
192 default:
193 SCIPerrorMessage("invalid efficacy norm parameter '%c'\n", scip->set->sepa_efficacynorm);
194 assert(FALSE); /*lint !e506*/
195 }
196
197 return norm;
198}
199
200/** indicates whether a cut is applicable, i.e., will modify the LP when applied
201 *
202 * @pre This method can be called if @p scip is in one of the following stages:
203 * - \ref SCIP_STAGE_SOLVING
204 *
205 * @return whether the cut is modifiable, not a bound change, or a bound change that changes bounds by at least epsilon
206 */
208 SCIP* scip, /**< SCIP data structure */
209 SCIP_ROW* cut /**< separated cut */
210 )
211{
213
214 return SCIPsepastoreIsCutApplicable(scip->set, cut);
215}
216
217/** adds row to separation storage
218 *
219 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
220 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
221 *
222 * @pre This method can be called if @p scip is in one of the following stages:
223 * - \ref SCIP_STAGE_SOLVING
224 */
226 SCIP* scip, /**< SCIP data structure */
227 SCIP_ROW* row, /**< row */
228 SCIP_Bool forcecut, /**< should the row be forced to enter the LP? */
229 SCIP_Bool* infeasible /**< pointer to store whether row has been detected to be infeasible for local bounds */
230 )
231{
233
234 assert(SCIPtreeGetCurrentNode(scip->tree) != NULL);
235
236 SCIP_CALL( SCIPsepastoreAddCut(scip->sepastore, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue,
237 scip->eventfilter, scip->lp, row, forcecut, (SCIPtreeGetCurrentDepth(scip->tree) == 0), infeasible) );
238
239 /* possibly run conflict analysis */
240 if ( *infeasible && SCIPprobAllColsInLP(scip->transprob, scip->set, scip->lp) && SCIPisConflictAnalysisApplicable(scip) )
241 {
242 SCIP_Real act;
243 SCIP_VAR* var;
244 SCIP_Real val;
245 int ncols;
246 int j;
247
248 /* initialize conflict analysis */
250
251 if ( ! SCIPisInfinity(scip, -row->lhs) )
252 {
253 act = SCIProwGetMaxActivity(row, scip->set, scip->stat);
254 if ( SCIPisLT(scip, act, row->lhs) )
255 {
256 ncols = SCIProwGetNNonz(row);
257 for (j = 0; j < ncols; ++j)
258 {
259 val = row->vals[j];
260 if ( ! SCIPisZero(scip, val) )
261 {
262 var = SCIPcolGetVar(row->cols[j]);
263 assert( var != NULL );
264
265 if ( val > 0.0 )
266 {
268 }
269 else
270 {
272 }
273 }
274 }
275 }
276 }
277 else if ( ! SCIPisInfinity(scip, row->rhs) )
278 {
279 act = SCIProwGetMinActivity(row, scip->set, scip->stat);
280 if ( SCIPisGT(scip, act, row->rhs) )
281 {
282 ncols = SCIProwGetNNonz(row);
283 for (j = 0; j < ncols; ++j)
284 {
285 val = row->vals[j];
286 if ( ! SCIPisZero(scip, val) )
287 {
288 var = SCIPcolGetVar(row->cols[j]);
289 assert( var != NULL );
290
291 if ( val > 0.0 )
292 {
294 }
295 else
296 {
298 }
299 }
300 }
301 }
302 }
303
304 /* analyze the conflict */
306 }
307
308 return SCIP_OKAY;
309}
310
311/** checks if cut is already existing in global cutpool
312 *
313 * @return TRUE is returned if the cut is not already existing in the global cutpool, FALSE otherwise
314 *
315 * @pre This method can be called if @p scip is in one of the following stages:
316 * - \ref SCIP_STAGE_SOLVING
317 */
319 SCIP* scip, /**< SCIP data structure */
320 SCIP_ROW* row /**< cutting plane to add */
321 )
322{
324
325 return SCIPcutpoolIsCutNew(scip->cutpool, scip->set, row);
326}
327
328/** if not already existing, adds row to global cut pool
329 *
330 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
331 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
332 *
333 * @pre This method can be called if @p scip is in one of the following stages:
334 * - \ref SCIP_STAGE_SOLVING
335 */
337 SCIP* scip, /**< SCIP data structure */
338 SCIP_ROW* row /**< row to remove */
339 )
340{
342
343 SCIP_CALL( SCIPcutpoolAddRow(scip->cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) );
344
345 return SCIP_OKAY;
346}
347
348/** removes the row from the global cut pool
349 *
350 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
351 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
352 *
353 * @pre This method can be called if @p scip is in one of the following stages:
354 * - \ref SCIP_STAGE_SOLVING
355 */
357 SCIP* scip, /**< SCIP data structure */
358 SCIP_ROW* row /**< cutting plane to add */
359 )
360{
362
363 SCIP_CALL( SCIPcutpoolDelRow(scip->cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) );
364
365 return SCIP_OKAY;
366}
367
368/** gets current cuts in the global cut pool
369 *
370 * @return the current cuts in the global cut pool
371 *
372 * @pre This method can be called if @p scip is in one of the following stages:
373 * - \ref SCIP_STAGE_SOLVING
374 * - \ref SCIP_STAGE_SOLVED
375 * - \ref SCIP_STAGE_EXITSOLVE
376 */
378 SCIP* scip /**< SCIP data structure */
379 )
380{
382
383 return SCIPcutpoolGetCuts(scip->cutpool);
384}
385
386/** gets current number of rows in the global cut pool
387 *
388 * @return the current number of rows in the global cut pool
389 *
390 * @pre This method can be called if @p scip is in one of the following stages:
391 * - \ref SCIP_STAGE_SOLVING
392 * - \ref SCIP_STAGE_SOLVED
393 * - \ref SCIP_STAGE_EXITSOLVE
394 */
396 SCIP* scip /**< SCIP data structure */
397 )
398{
400
401 return SCIPcutpoolGetNCuts(scip->cutpool);
402}
403
404/** gets the global cut pool used by SCIP
405 *
406 * @return the global cut pool used by SCIP
407 *
408 * @pre This method can be called if @p scip is in one of the following stages:
409 * - \ref SCIP_STAGE_SOLVING
410 * - \ref SCIP_STAGE_SOLVED
411 * - \ref SCIP_STAGE_EXITSOLVE
412 */
414 SCIP* scip /**< SCIP data structure */
415 )
416{
418
419 return scip->cutpool;
420}
421
422/** creates a cut pool
423 *
424 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
425 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
426 *
427 * @pre This method can be called if @p scip is in one of the following stages:
428 * - \ref SCIP_STAGE_TRANSFORMING
429 * - \ref SCIP_STAGE_TRANSFORMED
430 * - \ref SCIP_STAGE_INITPRESOLVE
431 * - \ref SCIP_STAGE_PRESOLVING
432 * - \ref SCIP_STAGE_EXITPRESOLVE
433 * - \ref SCIP_STAGE_PRESOLVED
434 * - \ref SCIP_STAGE_INITSOLVE
435 * - \ref SCIP_STAGE_SOLVING
436 */
438 SCIP* scip, /**< SCIP data structure */
439 SCIP_CUTPOOL** cutpool, /**< pointer to store cut pool */
440 int agelimit /**< maximum age a cut can reach before it is deleted from the pool */
441 )
442{
443 SCIP_CALL( SCIPcheckStage(scip, "SCIPcreateCutpool", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
444
445 SCIP_CALL( SCIPcutpoolCreate(cutpool, scip->mem->probmem, scip->set, agelimit, FALSE) );
446
447 return SCIP_OKAY;
448}
449
450/** frees a cut pool
451 *
452 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
453 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
454 *
455 * @pre This method can be called if @p scip is in one of the following stages:
456 * - \ref SCIP_STAGE_TRANSFORMING
457 * - \ref SCIP_STAGE_TRANSFORMED
458 * - \ref SCIP_STAGE_INITPRESOLVE
459 * - \ref SCIP_STAGE_PRESOLVING
460 * - \ref SCIP_STAGE_EXITPRESOLVE
461 * - \ref SCIP_STAGE_PRESOLVED
462 * - \ref SCIP_STAGE_INITSOLVE
463 * - \ref SCIP_STAGE_SOLVING
464 * - \ref SCIP_STAGE_SOLVED
465 * - \ref SCIP_STAGE_EXITSOLVE
466 * - \ref SCIP_STAGE_FREETRANS
467 */
469 SCIP* scip, /**< SCIP data structure */
470 SCIP_CUTPOOL** cutpool /**< pointer to store cut pool */
471 )
472{
473 SCIP_CALL( SCIPcheckStage(scip, "SCIPfreeCutpool", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
474
475 SCIP_CALL( SCIPcutpoolFree(cutpool, scip->mem->probmem, scip->set, scip->lp) );
476
477 return SCIP_OKAY;
478}
479
480/** if not already existing, adds row to a cut pool and captures it
481 *
482 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
483 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
484 *
485 * @pre This method can be called if @p scip is in one of the following stages:
486 * - \ref SCIP_STAGE_INITSOLVE
487 * - \ref SCIP_STAGE_SOLVING
488 */
490 SCIP* scip, /**< SCIP data structure */
491 SCIP_CUTPOOL* cutpool, /**< cut pool */
492 SCIP_ROW* row /**< cutting plane to add */
493 )
494{
496
497 SCIP_CALL( SCIPcutpoolAddRow(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) );
498
499 return SCIP_OKAY;
500}
501
502/** adds row to a cut pool and captures it; doesn't check for multiple cuts
503 *
504 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
505 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
506 *
507 * @pre This method can be called if @p scip is in one of the following stages:
508 * - \ref SCIP_STAGE_INITSOLVE
509 * - \ref SCIP_STAGE_SOLVING
510 */
512 SCIP* scip, /**< SCIP data structure */
513 SCIP_CUTPOOL* cutpool, /**< cut pool */
514 SCIP_ROW* row /**< cutting plane to add */
515 )
516{
517 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddNewRowCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) );
518
519 SCIP_CALL( SCIPcutpoolAddNewRow(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) );
520
521 return SCIP_OKAY;
522}
523
524/** removes the LP row from a cut pool
525 *
526 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
527 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
528 *
529 * @pre This method can be called if @p scip is in one of the following stages:
530 * - \ref SCIP_STAGE_INITSOLVE
531 * - \ref SCIP_STAGE_SOLVING
532 * - \ref SCIP_STAGE_SOLVED
533 */
535 SCIP* scip, /**< SCIP data structure */
536 SCIP_CUTPOOL* cutpool, /**< cut pool */
537 SCIP_ROW* row /**< row to remove */
538 )
539{
541
542 SCIP_CALL( SCIPcutpoolDelRow(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) );
543
544 return SCIP_OKAY;
545}
546
547/** separates cuts from a cut pool
548 *
549 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
550 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
551 *
552 * @pre This method can be called if @p scip is in one of the following stages:
553 * - \ref SCIP_STAGE_SOLVING
554 */
556 SCIP* scip, /**< SCIP data structure */
557 SCIP_CUTPOOL* cutpool, /**< cut pool */
558 SCIP_RESULT* result /**< pointer to store the result of the separation call */
559 )
560{
562
563 assert(SCIPtreeGetCurrentNode(scip->tree) != NULL);
564
565 if( !SCIPtreeHasCurrentNodeLP(scip->tree) )
566 {
567 SCIPerrorMessage("cannot add cuts, because node LP is not processed\n");
568 return SCIP_INVALIDCALL;
569 }
570
571 SCIP_CALL( SCIPcutpoolSeparate(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, scip->eventfilter,
572 scip->lp, scip->sepastore, NULL, FALSE, (SCIPtreeGetCurrentDepth(scip->tree) == 0), result) );
573
574 return SCIP_OKAY;
575}
576
577/** separates cuts w.r.t. given solution from a cut pool
578 *
579 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
580 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
581 *
582 * @pre This method can be called if @p scip is in one of the following stages:
583 * - \ref SCIP_STAGE_SOLVING
584 */
586 SCIP* scip, /**< SCIP data structure */
587 SCIP_CUTPOOL* cutpool, /**< cut pool */
588 SCIP_SOL* sol, /**< solution to be separated */
589 SCIP_Bool pretendroot, /**< should the cut separators be called as if we are at the root node? */
590 SCIP_RESULT* result /**< pointer to store the result of the separation call */
591 )
592{
593 SCIP_CALL( SCIPcheckStage(scip, "SCIPseparateSolCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
594
595 assert(SCIPtreeGetCurrentNode(scip->tree) != NULL);
596
597 if( !SCIPtreeHasCurrentNodeLP(scip->tree) )
598 {
599 SCIPerrorMessage("cannot add cuts, because node LP is not processed\n");
600 return SCIP_INVALIDCALL;
601 }
602
603 SCIP_CALL( SCIPcutpoolSeparate(cutpool, scip->mem->probmem, scip->set, scip->stat, scip->eventqueue, scip->eventfilter,
604 scip->lp, scip->sepastore, sol, FALSE, pretendroot, result) );
605
606 return SCIP_OKAY;
607}
608
609/** if not already existing, adds row to delayed global cut pool
610 *
611 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
612 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
613 *
614 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING
615 */
617 SCIP* scip, /**< SCIP data structure */
618 SCIP_ROW* row /**< cutting plane to add */
619 )
620{
621 SCIP_CALL( SCIPcheckStage(scip, "SCIPaddDelayedPoolCut", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
622
623 SCIP_CALL( SCIPcutpoolAddRow(scip->delayedcutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) );
624
625 return SCIP_OKAY;
626}
627
628/** removes the row from the delayed global cut pool
629 *
630 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
631 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
632 *
633 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING
634 */
636 SCIP* scip, /**< SCIP data structure */
637 SCIP_ROW* row /**< cutting plane to add */
638 )
639{
640 SCIP_CALL( SCIPcheckStage(scip, "SCIPdelDelayedPoolCut", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
641
642 SCIP_CALL( SCIPcutpoolDelRow(scip->delayedcutpool, scip->mem->probmem, scip->set, scip->stat, scip->lp, row) );
643
644 return SCIP_OKAY;
645}
646
647/** gets current cuts in the delayed global cut pool
648 *
649 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
650 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
651 *
652 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING
653 */
655 SCIP* scip /**< SCIP data structure */
656 )
657{
659
660 return SCIPcutpoolGetCuts(scip->delayedcutpool);
661}
662
663/** gets current number of rows in the delayed global cut pool
664 *
665 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
666 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
667 *
668 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING
669 */
671 SCIP* scip /**< SCIP data structure */
672 )
673{
674 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetNDelayedPoolCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) );
675
676 return SCIPcutpoolGetNCuts(scip->delayedcutpool);
677}
678
679/** gets the delayed global cut pool used by SCIP
680 *
681 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
682 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
683 *
684 * @pre This method can be called if @p scip is the stages \ref SCIP_STAGE_SOLVING
685 */
687 SCIP* scip /**< SCIP data structure */
688 )
689{
690 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetDelayedGlobalCutpool", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE) );
691
692 return scip->delayedcutpool;
693}
694
695/** separates the given primal solution or the current LP solution by calling the separators and constraint handlers'
696 * separation methods;
697 * the generated cuts are stored in the separation storage and can be accessed with the methods SCIPgetCuts() and
698 * SCIPgetNCuts();
699 * after evaluating the cuts, you have to call SCIPclearCuts() in order to remove the cuts from the
700 * separation storage;
701 * it is possible to call SCIPseparateSol() multiple times with different solutions and evaluate the found cuts
702 * afterwards
703 *
704 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
705 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
706 *
707 * @pre This method can be called if @p scip is in one of the following stages:
708 * - \ref SCIP_STAGE_SOLVING
709 */
711 SCIP* scip, /**< SCIP data structure */
712 SCIP_SOL* sol, /**< primal solution that should be separated, or NULL for LP solution */
713 SCIP_Bool pretendroot, /**< should the cut separators be called as if we are at the root node? */
714 SCIP_Bool allowlocal, /**< should the separator be asked to separate local cuts */
715 SCIP_Bool onlydelayed, /**< should only separators be called that were delayed in the previous round? */
716 SCIP_Bool* delayed, /**< pointer to store whether a separator was delayed */
717 SCIP_Bool* cutoff /**< pointer to store whether the node can be cut off */
718 )
719{
720 int actdepth;
721
723
724 /* get current depth */
725 actdepth = (pretendroot ? 0 : SCIPtreeGetCurrentDepth(scip->tree));
726
727 /* apply separation round */
728 SCIP_CALL( SCIPseparationRound(scip->mem->probmem, scip->set, scip->messagehdlr, scip->stat, scip->eventqueue,
729 scip->eventfilter, scip->transprob, scip->primal, scip->tree, scip->lp, scip->sepastore,
730 sol, actdepth, allowlocal, onlydelayed, delayed, cutoff) );
731
732 return SCIP_OKAY;
733}
734
735/** gets the array of cuts currently stored in the separation storage
736 *
737 * @return the array of cuts currently stored in the separation storage
738 *
739 * @pre This method can be called if @p scip is in one of the following stages:
740 * - \ref SCIP_STAGE_PRESOLVED
741 * - \ref SCIP_STAGE_SOLVING
742 * - \ref SCIP_STAGE_SOLVED
743 */
745 SCIP* scip /**< SCIP data structure */
746 )
747{
749
750 return SCIPsepastoreGetCuts(scip->sepastore);
751}
752
753/** get current number of cuts in the separation storage
754 *
755 * @return the current number of cuts in the separation storage
756 *
757 * @pre This method can be called if @p scip is in one of the following stages:
758 * - \ref SCIP_STAGE_PRESOLVED
759 * - \ref SCIP_STAGE_SOLVING
760 * - \ref SCIP_STAGE_SOLVED
761 */
763 SCIP* scip /**< SCIP data structure */
764 )
765{
767
768 return SCIPsepastoreGetNCuts(scip->sepastore);
769}
770
771/** clears the separation storage
772 *
773 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
774 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
775 *
776 * @pre This method can be called if @p scip is in one of the following stages:
777 * - \ref SCIP_STAGE_SOLVING
778 */
780 SCIP* scip /**< SCIP data structure */
781 )
782{
784
785 SCIP_CALL( SCIPsepastoreClearCuts(scip->sepastore, scip->mem->probmem, scip->set, scip->eventqueue, scip->eventfilter, scip->lp) );
786
787 return SCIP_OKAY;
788}
789
790/** removes cuts that are inefficacious w.r.t. the current LP solution from separation storage without adding the cuts to the LP
791 *
792 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
793 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
794 *
795 * @pre This method can be called if @p scip is in one of the following stages:
796 * - \ref SCIP_STAGE_SOLVING
797 */
799 SCIP* scip /**< SCIP data structure */
800 )
801{
802 SCIP_Bool isroot = FALSE;
803
804 SCIP_CALL( SCIPcheckStage(scip, "SCIPremoveInefficaciousCuts", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
805
806 if( SCIPtreeGetCurrentDepth(scip->tree) == 0 )
807 isroot = TRUE;
808
809 SCIP_CALL( SCIPsepastoreRemoveInefficaciousCuts(scip->sepastore, scip->mem->probmem, scip->set, scip->stat,
810 scip->eventqueue, scip->eventfilter, scip->lp, isroot, SCIP_EFFICIACYCHOICE_LP) );
811
812 return SCIP_OKAY;
813}
SCIP_RETCODE SCIPcutpoolSeparate(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, SCIP_Bool cutpoolisdelayed, SCIP_Bool root, SCIP_RESULT *result)
Definition: cutpool.c:827
SCIP_RETCODE SCIPcutpoolDelRow(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_ROW *row)
Definition: cutpool.c:798
SCIP_RETCODE SCIPcutpoolCreate(SCIP_CUTPOOL **cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, int agelimit, SCIP_Bool globalcutpool)
Definition: cutpool.c:427
SCIP_RETCODE SCIPcutpoolAddRow(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_ROW *row)
Definition: cutpool.c:656
SCIP_RETCODE SCIPcutpoolAddNewRow(SCIP_CUTPOOL *cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_ROW *row)
Definition: cutpool.c:729
SCIP_RETCODE SCIPcutpoolFree(SCIP_CUTPOOL **cutpool, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: cutpool.c:468
SCIP_Bool SCIPcutpoolIsCutNew(SCIP_CUTPOOL *cutpool, SCIP_SET *set, SCIP_ROW *row)
Definition: cutpool.c:593
internal methods for storing cuts in a cut pool
methods for debugging
#define SCIPcheckStage(scip, method, init, problem, transforming, transformed, initpresolve, presolving, exitpresolve, presolved, initsolve, solving, solved, exitsolve, freetrans, freescip)
Definition: debug.h:364
#define NULL
Definition: def.h:248
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:156
#define SQR(x)
Definition: def.h:199
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define REALABS(x)
Definition: def.h:182
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:17425
SCIP_RETCODE SCIPaddConflictLb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPinitConflictAnalysis(SCIP *scip, SCIP_CONFTYPE conftype, SCIP_Bool iscutoffinvolved)
SCIP_RETCODE SCIPaddConflictUb(SCIP *scip, SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx)
SCIP_RETCODE SCIPanalyzeConflict(SCIP *scip, int validdepth, SCIP_Bool *success)
SCIP_Bool SCIPisConflictAnalysisApplicable(SCIP *scip)
SCIP_RETCODE SCIPseparateSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool pretendroot, SCIP_Bool allowlocal, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *cutoff)
Definition: scip_cut.c:710
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_CUT ** SCIPcutpoolGetCuts(SCIP_CUTPOOL *cutpool)
Definition: cutpool.c:1067
SCIP_RETCODE SCIPdelDelayedPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip_cut.c:635
SCIP_Real SCIPgetCutLPSolCutoffDistance(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip_cut.c:72
SCIP_RETCODE SCIPdelRowCutpool(SCIP *scip, SCIP_CUTPOOL *cutpool, SCIP_ROW *row)
Definition: scip_cut.c:534
SCIP_RETCODE SCIPremoveInefficaciousCuts(SCIP *scip)
Definition: scip_cut.c:798
SCIP_RETCODE SCIPseparateCutpool(SCIP *scip, SCIP_CUTPOOL *cutpool, SCIP_RESULT *result)
Definition: scip_cut.c:555
SCIP_CUT ** SCIPgetDelayedPoolCuts(SCIP *scip)
Definition: scip_cut.c:654
SCIP_RETCODE SCIPaddRowCutpool(SCIP *scip, SCIP_CUTPOOL *cutpool, SCIP_ROW *row)
Definition: scip_cut.c:489
SCIP_Bool SCIPisCutNew(SCIP *scip, SCIP_ROW *row)
Definition: scip_cut.c:318
SCIP_Bool SCIPisCutEfficacious(SCIP *scip, SCIP_SOL *sol, SCIP_ROW *cut)
Definition: scip_cut.c:117
SCIP_CUTPOOL * SCIPgetGlobalCutpool(SCIP *scip)
Definition: scip_cut.c:413
SCIP_RETCODE SCIPseparateSolCutpool(SCIP *scip, SCIP_CUTPOOL *cutpool, SCIP_SOL *sol, SCIP_Bool pretendroot, SCIP_RESULT *result)
Definition: scip_cut.c:585
SCIP_Bool SCIPisEfficacious(SCIP *scip, SCIP_Real efficacy)
Definition: scip_cut.c:135
SCIP_Bool SCIPisCutApplicable(SCIP *scip, SCIP_ROW *cut)
Definition: scip_cut.c:207
SCIP_CUTPOOL * SCIPgetDelayedGlobalCutpool(SCIP *scip)
Definition: scip_cut.c:686
SCIP_RETCODE SCIPaddRow(SCIP *scip, SCIP_ROW *row, SCIP_Bool forcecut, SCIP_Bool *infeasible)
Definition: scip_cut.c:225
int SCIPgetNPoolCuts(SCIP *scip)
Definition: scip_cut.c:395
int SCIPcutpoolGetNCuts(SCIP_CUTPOOL *cutpool)
Definition: cutpool.c:1077
SCIP_ROW ** SCIPgetCuts(SCIP *scip)
Definition: scip_cut.c:744
SCIP_CUT ** SCIPgetPoolCuts(SCIP *scip)
Definition: scip_cut.c:377
SCIP_RETCODE SCIPclearCuts(SCIP *scip)
Definition: scip_cut.c:779
SCIP_RETCODE SCIPcreateCutpool(SCIP *scip, SCIP_CUTPOOL **cutpool, int agelimit)
Definition: scip_cut.c:437
SCIP_Real SCIPgetVectorEfficacyNorm(SCIP *scip, SCIP_Real *vals, int nvals)
Definition: scip_cut.c:149
int SCIPgetNDelayedPoolCuts(SCIP *scip)
Definition: scip_cut.c:670
int SCIPgetNCuts(SCIP *scip)
Definition: scip_cut.c:762
SCIP_RETCODE SCIPdelPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip_cut.c:356
SCIP_RETCODE SCIPfreeCutpool(SCIP *scip, SCIP_CUTPOOL **cutpool)
Definition: scip_cut.c:468
SCIP_RETCODE SCIPaddNewRowCutpool(SCIP *scip, SCIP_CUTPOOL *cutpool, SCIP_ROW *row)
Definition: scip_cut.c:511
SCIP_RETCODE SCIPaddDelayedPoolCut(SCIP *scip, SCIP_ROW *row)
Definition: scip_cut.c:616
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:17607
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6849
SCIP_Bool SCIProwIsLPEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool root)
Definition: lp.c:7095
SCIP_Real SCIProwGetSolEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol)
Definition: lp.c:7111
SCIP_Real SCIProwGetLPSolCutoffDistance(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_LP *lp)
Definition: lp.c:6997
SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:7054
SCIP_Bool SCIProwIsSolEfficacious(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_SOL *sol, SCIP_Bool root)
Definition: lp.c:7154
SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6828
internal methods for LP management
SCIP_Bool SCIPprobAllColsInLP(SCIP_PROB *prob, SCIP_SET *set, SCIP_LP *lp)
Definition: prob.c:2825
internal methods for storing and manipulating the main problem
public methods for storing cuts in a cut pool
public methods for LP management
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
public methods for conflict handler plugins and conflict analysis
public methods for cuts and aggregation rows
public methods for numerical tolerances
public methods for the branch-and-bound tree
SCIP_RETCODE SCIPsepastoreClearCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
Definition: sepastore.c:1061
int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1183
SCIP_RETCODE SCIPsepastoreAddCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool root, SCIP_Bool *infeasible)
Definition: sepastore.c:439
SCIP_RETCODE SCIPsepastoreRemoveInefficaciousCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_Bool root, SCIP_EFFICIACYCHOICE efficiacychoice)
Definition: sepastore.c:1107
SCIP_ROW ** SCIPsepastoreGetCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1173
SCIP_Bool SCIPsepastoreIsCutApplicable(SCIP_SET *set, SCIP_ROW *cut)
Definition: sepastore.c:1164
internal methods for storing separated cuts
SCIP_Bool SCIPsetIsEfficacious(SCIP_SET *set, SCIP_Bool root, SCIP_Real efficacy)
Definition: set.c:7447
internal methods for global SCIP settings
SCIP_RETCODE SCIPseparationRound(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_LP *lp, SCIP_SEPASTORE *sepastore, SCIP_SOL *sol, int actdepth, SCIP_Bool allowlocal, SCIP_Bool onlydelayed, SCIP_Bool *delayed, SCIP_Bool *cutoff)
Definition: solve.c:2158
internal methods for main solving loop and node processing
SCIP_Real rhs
Definition: struct_lp.h:208
SCIP_Real * vals
Definition: struct_lp.h:232
SCIP_Real lhs
Definition: struct_lp.h:207
SCIP_COL ** cols
Definition: struct_lp.h:230
data structures for LP management
datastructures for block memory pools and memory buffers
SCIP main data structure.
datastructures for global SCIP settings
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:9462
SCIP_Bool SCIPtreeHasCurrentNodeLP(SCIP_TREE *tree)
Definition: tree.c:9496
int SCIPtreeGetCurrentDepth(SCIP_TREE *tree)
Definition: tree.c:9479
internal methods for branch and bound tree
@ SCIP_CONFTYPE_PROPAGATION
Definition: type_conflict.h:62
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_OKAY
Definition: type_retcode.h:42
@ SCIP_INVALIDCALL
Definition: type_retcode.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63
@ SCIP_EFFICIACYCHOICE_LP