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