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