Scippy

SCIP

Solving Constraint Integer Programs

sepastore.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-2015 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 email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file sepastore.c
17  * @brief methods for storing separated cuts
18  * @author Tobias Achterberg
19  * @author Marc Pfetsch
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <assert.h>
25 
26 #include "scip/def.h"
27 #include "scip/set.h"
28 #include "scip/stat.h"
29 #include "scip/lp.h"
30 #include "scip/var.h"
31 #include "scip/tree.h"
32 #include "scip/reopt.h"
33 #include "scip/sepastore.h"
34 #include "scip/event.h"
35 #include "scip/sepa.h"
36 #include "scip/cons.h"
37 #include "scip/debug.h"
38 
39 #include "scip/struct_sepastore.h"
40 
41 
42 
43 /*
44  * dynamic memory arrays
45  */
46 
47 /** resizes cuts and score arrays to be able to store at least num entries */
48 static
50  SCIP_SEPASTORE* sepastore, /**< separation storage */
51  SCIP_SET* set, /**< global SCIP settings */
52  int num /**< minimal number of slots in array */
53  )
54 {
55  assert(sepastore != NULL);
56  assert(set != NULL);
57 
58  if( num > sepastore->cutssize )
59  {
60  int newsize;
61 
62  newsize = SCIPsetCalcMemGrowSize(set, num);
63  SCIP_ALLOC( BMSreallocMemoryArray(&sepastore->cuts, newsize) );
64  SCIP_ALLOC( BMSreallocMemoryArray(&sepastore->efficacies, newsize) );
65  SCIP_ALLOC( BMSreallocMemoryArray(&sepastore->objparallelisms, newsize) );
66  SCIP_ALLOC( BMSreallocMemoryArray(&sepastore->orthogonalities, newsize) );
67  SCIP_ALLOC( BMSreallocMemoryArray(&sepastore->scores, newsize) );
68  sepastore->cutssize = newsize;
69  }
70  assert(num <= sepastore->cutssize);
71 
72  return SCIP_OKAY;
73 }
74 
75 
76 
77 
78 /** creates separation storage */
80  SCIP_SEPASTORE** sepastore /**< pointer to store separation storage */
81  )
82 {
83  assert(sepastore != NULL);
84 
85  SCIP_ALLOC( BMSallocMemory(sepastore) );
86 
87  (*sepastore)->cuts = NULL;
88  (*sepastore)->efficacies = NULL;
89  (*sepastore)->objparallelisms = NULL;
90  (*sepastore)->orthogonalities = NULL;
91  (*sepastore)->scores = NULL;
92  (*sepastore)->cutssize = 0;
93  (*sepastore)->ncuts = 0;
94  (*sepastore)->nforcedcuts = 0;
95  (*sepastore)->ncutsfound = 0;
96  (*sepastore)->ncutsfoundround = 0;
97  (*sepastore)->ncutsapplied = 0;
98  (*sepastore)->initiallp = FALSE;
99  (*sepastore)->forcecuts = FALSE;
100 
101  return SCIP_OKAY;
102 }
103 
104 /** frees separation storage */
106  SCIP_SEPASTORE** sepastore /**< pointer to store separation storage */
107  )
108 {
109  assert(sepastore != NULL);
110  assert(*sepastore != NULL);
111  assert((*sepastore)->ncuts == 0);
112 
113  BMSfreeMemoryArrayNull(&(*sepastore)->cuts);
114  BMSfreeMemoryArrayNull(&(*sepastore)->efficacies);
115  BMSfreeMemoryArrayNull(&(*sepastore)->objparallelisms);
116  BMSfreeMemoryArrayNull(&(*sepastore)->orthogonalities);
117  BMSfreeMemoryArrayNull(&(*sepastore)->scores);
118  BMSfreeMemory(sepastore);
119 
120  return SCIP_OKAY;
121 }
122 
123 /** informs separation storage, that the setup of the initial LP starts now */
125  SCIP_SEPASTORE* sepastore /**< separation storage */
126  )
127 {
128  assert(sepastore != NULL);
129  assert(!sepastore->initiallp);
130  assert(sepastore->ncuts == 0);
131 
132  sepastore->initiallp = TRUE;
133 }
134 
135 /** informs separation storage, that the setup of the initial LP is now finished */
137  SCIP_SEPASTORE* sepastore /**< separation storage */
138  )
139 {
140  assert(sepastore != NULL);
141  assert(sepastore->initiallp);
142  assert(sepastore->ncuts == 0);
143 
144  sepastore->initiallp = FALSE;
145 }
146 
147 /** informs separation storage, that the following cuts should be used in any case */
149  SCIP_SEPASTORE* sepastore /**< separation storage */
150  )
151 {
152  assert(sepastore != NULL);
153  assert(!sepastore->forcecuts);
154 
155  sepastore->forcecuts = TRUE;
156 }
157 
158 /** informs separation storage, that the following cuts should no longer be used in any case */
160  SCIP_SEPASTORE* sepastore /**< separation storage */
161  )
162 {
163  assert(sepastore != NULL);
164  assert(sepastore->forcecuts);
165 
166  sepastore->forcecuts = FALSE;
167 }
168 
169 /** checks cut for redundancy due to activity bounds */
170 static
172  SCIP_SEPASTORE* sepastore, /**< separation storage */
173  SCIP_SET* set, /**< global SCIP settings */
174  SCIP_STAT* stat, /**< problem statistics data */
175  SCIP_ROW* cut /**< separated cut */
176  )
177 {
178  SCIP_Real minactivity;
179  SCIP_Real maxactivity;
180  SCIP_Real lhs;
181  SCIP_Real rhs;
182 
183  assert(sepastore != NULL);
184  assert(cut != NULL);
185 
186  /* modifiable cuts cannot be declared redundant, since we don't know all coefficients */
187  if( SCIProwIsModifiable(cut) )
188  return FALSE;
189 
190  /* check for activity redundancy */
191  lhs = SCIProwGetLhs(cut);
192  rhs = SCIProwGetRhs(cut);
193  minactivity = SCIProwGetMinActivity(cut, set, stat);
194  maxactivity = SCIProwGetMaxActivity(cut, set, stat);
195  if( SCIPsetIsLE(set, lhs, minactivity) && SCIPsetIsLE(set, maxactivity, rhs) )
196  {
197  SCIPdebugMessage("ignoring activity redundant cut <%s> (sides=[%g,%g], act=[%g,%g])\n",
198  SCIProwGetName(cut), lhs, rhs, minactivity, maxactivity);
199  /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
200  return TRUE;
201  }
202 
203  return FALSE;
204 }
205 
206 /** checks cut for redundancy or infeasibility due to activity bounds */
207 static
209  SCIP_SEPASTORE* sepastore, /**< separation storage */
210  SCIP_SET* set, /**< global SCIP settings */
211  SCIP_STAT* stat, /**< problem statistics data */
212  SCIP_ROW* cut, /**< separated cut */
213  SCIP_Bool* infeasible /**< pointer to store whether the cut has been detected to be infeasible */
214  )
215 {
216  SCIP_Real minactivity;
217  SCIP_Real maxactivity;
218  SCIP_Real lhs;
219  SCIP_Real rhs;
220 
221  assert(sepastore != NULL);
222  assert(cut != NULL);
223  assert(infeasible != NULL);
224 
225  *infeasible = FALSE;
226 
227  /* modifiable cuts cannot be declared redundant or infeasible, since we don't know all coefficients */
228  if( SCIProwIsModifiable(cut) )
229  return FALSE;
230 
231  /* check for activity redundancy */
232  lhs = SCIProwGetLhs(cut);
233  rhs = SCIProwGetRhs(cut);
234  minactivity = SCIProwGetMinActivity(cut, set, stat);
235  maxactivity = SCIProwGetMaxActivity(cut, set, stat);
236  if( (SCIPsetIsInfinity(set, -lhs) || SCIPsetIsLE(set, lhs, minactivity))
237  && (SCIPsetIsInfinity(set, rhs) || SCIPsetIsLE(set, maxactivity, rhs)) )
238  {
239  SCIPdebugMessage("ignoring activity redundant cut <%s> (sides=[%g,%g], act=[%g,%g])\n",
240  SCIProwGetName(cut), lhs, rhs, minactivity, maxactivity);
241  /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
242  return TRUE;
243  }
244  if( (!SCIPsetIsInfinity(set, rhs) && SCIPsetIsFeasGT(set, minactivity, rhs))
245  || (!SCIPsetIsInfinity(set, -lhs) && SCIPsetIsFeasLT(set, maxactivity, lhs) ))
246  {
247  SCIPdebugMessage("cut <%s> is infeasible (sides=[%g,%g], act=[%g,%g])\n",
248  SCIProwGetName(cut), lhs, rhs, minactivity, maxactivity);
249  /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
250  *infeasible = TRUE;
251  return TRUE;
252  }
253 
254  return FALSE;
255 }
256 
257 /** checks whether a cut with only one variable can be applied as boundchange
258  *
259  * This is the case if the bound change would prove infeasibility (w.r.t feastol),
260  * or if the new bound is at least epsilon better than the old bound.
261  * In the latter case, also the opposite bound has to be taken into account.
262  */
263 static
265  SCIP_SET* set, /**< global SCIP settings */
266  SCIP_ROW* cut /**< cut with a single variable */
267 )
268 {
269  SCIP_COL** cols;
270  SCIP_Real* vals;
271  SCIP_VAR* var;
272  SCIP_Real lhs;
273  SCIP_Real rhs;
274  SCIP_Bool local;
275  SCIP_Real oldlb;
276  SCIP_Real oldub;
277 
278  assert(set != NULL);
279  assert(!SCIProwIsModifiable(cut));
280  assert(SCIProwGetNNonz(cut) == 1);
281 
282  /* get the single variable and its coefficient of the cut */
283  cols = SCIProwGetCols(cut);
284  assert(cols != NULL);
285 
286  var = SCIPcolGetVar(cols[0]);
287  vals = SCIProwGetVals(cut);
288  assert(vals != NULL);
289  assert(!SCIPsetIsZero(set, vals[0]));
290 
291  /* if the coefficient is nearly zero, we better ignore this cut for numerical reasons */
292  if( SCIPsetIsFeasZero(set, vals[0]) )
293  return FALSE;
294 
295  local = SCIProwIsLocal(cut);
296 
297  oldlb = local ? SCIPvarGetLbLocal(var) : SCIPvarGetLbGlobal(var);
298  oldub = local ? SCIPvarGetUbLocal(var) : SCIPvarGetUbGlobal(var);
299 
300  /* get the left hand side of the cut and convert it to a bound */
301  lhs = SCIProwGetLhs(cut);
302  if( !SCIPsetIsInfinity(set, -lhs) )
303  {
304  lhs -= SCIProwGetConstant(cut);
305  if( vals[0] > 0.0 )
306  {
307  /* coefficient is positive -> lhs corresponds to lower bound */
308  SCIP_Real newlb;
309 
310  newlb = lhs/vals[0];
311  SCIPvarAdjustLb(var, set, &newlb);
312 
313  if( SCIPsetIsFeasGT(set, newlb, oldub) || SCIPsetIsGT(set, MIN(newlb, oldub), oldlb) )
314  return TRUE;
315  }
316  else
317  {
318  /* coefficient is negative -> lhs corresponds to upper bound */
319  SCIP_Real newub;
320 
321  newub = lhs/vals[0];
322  SCIPvarAdjustUb(var, set, &newub);
323 
324  if( SCIPsetIsFeasLT(set, newub, oldlb) || SCIPsetIsLT(set, MAX(newub, oldlb), oldub) )
325  return TRUE;
326  }
327  }
328 
329  /* get the right hand side of the cut and convert it to a bound */
330  rhs = SCIProwGetRhs(cut);
331  if( !SCIPsetIsInfinity(set, rhs) )
332  {
333  rhs -= SCIProwGetConstant(cut);
334  if( vals[0] > 0.0 )
335  {
336  /* coefficient is positive -> rhs corresponds to upper bound */
337  SCIP_Real newub;
338 
339  newub = rhs/vals[0];
340  SCIPvarAdjustUb(var, set, &newub);
341 
342  if( SCIPsetIsFeasLT(set, newub, oldlb) || SCIPsetIsLT(set, MAX(newub, oldlb), oldub) )
343  return TRUE;
344  }
345  else
346  {
347  /* coefficient is negative -> rhs corresponds to lower bound */
348  SCIP_Real newlb;
349 
350  newlb = rhs/vals[0];
351  SCIPvarAdjustLb(var, set, &newlb);
352 
353  if( SCIPsetIsFeasGT(set, newlb, oldub) || SCIPsetIsGT(set, MIN(newlb, oldub), oldlb) )
354  return TRUE;
355  }
356  }
357 
358  return FALSE;
359 }
360 
361 /** adds cut stored as LP row to separation storage and captures it;
362  * if the cut should be forced to be used, an infinite score has to be used
363  */
364 static
366  SCIP_SEPASTORE* sepastore, /**< separation storage */
367  BMS_BLKMEM* blkmem, /**< block memory */
368  SCIP_SET* set, /**< global SCIP settings */
369  SCIP_STAT* stat, /**< problem statistics data */
370  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
371  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
372  SCIP_LP* lp, /**< LP data */
373  SCIP_SOL* sol, /**< primal solution that was separated, or NULL for LP solution */
374  SCIP_ROW* cut, /**< separated cut */
375  SCIP_Bool forcecut, /**< should the cut be forced to enter the LP? */
376  SCIP_Bool root, /**< are we at the root node? */
377  SCIP_Bool* infeasible /**< pointer to store whether the cut is infeasible */
378  )
379 {
380  SCIP_Real cutefficacy;
381  SCIP_Real cutobjparallelism;
382  SCIP_Real cutscore;
383  SCIP_Bool redundant;
384  int pos;
385 
386  assert(sepastore != NULL);
387  assert(sepastore->nforcedcuts <= sepastore->ncuts);
388  assert(set != NULL);
389  assert(cut != NULL);
390  assert(sol != NULL || !SCIProwIsInLP(cut));
391  assert(!SCIPsetIsInfinity(set, -SCIProwGetLhs(cut)) || !SCIPsetIsInfinity(set, SCIProwGetRhs(cut)));
392  assert(eventqueue != NULL);
393  assert(eventfilter != NULL);
394 
395  /* in the root node, every local cut is a global cut, and global cuts are nicer in many ways...*/
396  if( root && SCIProwIsLocal(cut) )
397  {
398  SCIPdebugMessage("change local flag of cut <%s> to FALSE due to addition in root node\n", SCIProwGetName(cut));
399 
401 
402  assert(!SCIProwIsLocal(cut));
403  }
404 
405  /* check cut for redundancy or infeasibility */
406  redundant = sepastoreIsCutRedundantOrInfeasible(sepastore, set, stat, cut, infeasible);
407  /* Note that we add infeasible rows in any case, since we cannot be sure whether the return values are handled
408  * correctly. In this way, the LP becomes infeasible. */
409 
410  /* in each separation round, make sure that at least one (even redundant) cut enters the LP to avoid cycling */
411  if( !forcecut && sepastore->ncuts > 0 && redundant )
412  return SCIP_OKAY;
413 
414  /* if only one cut is currently present in the cut store, it could be redundant; in this case, it can now be removed
415  * again, because now a non redundant cut enters the store
416  */
417  if( sepastore->ncuts == 1 && sepastoreIsCutRedundant(sepastore, set, stat, sepastore->cuts[0]) )
418  {
419  /* check, if the row deletions from separation storage events are tracked if so, issue ROWDELETEDSEPA event */
420  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
421  {
422  SCIP_EVENT* event;
423 
424  SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[0]) );
425  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
426  }
427 
428  SCIP_CALL( SCIProwRelease(&sepastore->cuts[0], blkmem, set, lp) );
429  sepastore->ncuts = 0;
430  sepastore->nforcedcuts = 0;
431  }
432 
433  /* a cut is forced to enter the LP if
434  * - we construct the initial LP, or
435  * - it has infinite score factor, or
436  * - it is a bound change that can be applied
437  * if it is a non-forced cut and no cuts should be added, abort
438  */
439  forcecut = forcecut || sepastore->initiallp || sepastore->forcecuts || (!SCIProwIsModifiable(cut) && SCIProwGetNNonz(cut) == 1 && sepastoreIsBdchgApplicable(set, cut));
440  if( !forcecut && SCIPsetGetSepaMaxcuts(set, root) == 0 )
441  return SCIP_OKAY;
442 
443  /* get enough memory to store the cut */
444  SCIP_CALL( sepastoreEnsureCutsMem(sepastore, set, sepastore->ncuts+1) );
445  assert(sepastore->ncuts < sepastore->cutssize);
446 
447  if( forcecut )
448  {
449  cutefficacy = SCIPsetInfinity(set);
450  cutscore = SCIPsetInfinity(set);
451  cutobjparallelism = 1.0;
452  }
453  else
454  {
455  /* initialize values to invalid (will be initialized during cut filtering) */
456  cutefficacy = SCIP_INVALID;
457  cutscore = SCIP_INVALID;
458 
459  /* initialize parallelism to objective (constant throughout filtering) */
460  if( set->sepa_objparalfac > 0.0 )
461  cutobjparallelism = SCIProwGetObjParallelism(cut, set, lp);
462  else
463  cutobjparallelism = 0.0; /* no need to calculate it */
464  }
465 
466  SCIPdebugMessage("adding cut <%s> to separation storage of size %d (forcecut=%u, len=%d)\n",
467  SCIProwGetName(cut), sepastore->ncuts, forcecut, SCIProwGetNNonz(cut));
468  /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
469 
470  /* capture the cut */
471  SCIProwCapture(cut);
472 
473  /* add cut to arrays */
474  if( forcecut )
475  {
476  /* make room at the beginning of the array for forced cut */
477  pos = sepastore->nforcedcuts;
478  sepastore->cuts[sepastore->ncuts] = sepastore->cuts[pos];
479  sepastore->efficacies[sepastore->ncuts] = sepastore->efficacies[pos];
480  sepastore->objparallelisms[sepastore->ncuts] = sepastore->objparallelisms[pos];
481  sepastore->orthogonalities[sepastore->ncuts] = sepastore->orthogonalities[pos];
482  sepastore->scores[sepastore->ncuts] = sepastore->scores[pos];
483  sepastore->nforcedcuts++;
484  }
485  else
486  pos = sepastore->ncuts;
487 
488  sepastore->cuts[pos] = cut;
489  sepastore->efficacies[pos] = cutefficacy;
490  sepastore->objparallelisms[pos] = cutobjparallelism;
491  sepastore->orthogonalities[pos] = 1.0;
492  sepastore->scores[pos] = cutscore;
493  sepastore->ncuts++;
494 
495  /* check, if the row addition to separation storage events are tracked
496  * if so, issue ROWADDEDSEPA event
497  */
498  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDSEPA) != 0 )
499  {
500  SCIP_EVENT* event;
501 
502  SCIP_CALL( SCIPeventCreateRowAddedSepa(&event, blkmem, cut) );
503  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
504  }
505 
506  return SCIP_OKAY;
507 }
508 
509 /** removes a non-forced cut from the separation storage */
510 static
512  SCIP_SEPASTORE* sepastore, /**< separation storage */
513  BMS_BLKMEM* blkmem, /**< block memory */
514  SCIP_SET* set, /**< global SCIP settings */
515  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
516  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
517  SCIP_LP* lp, /**< LP data */
518  int pos /**< position of cut to delete */
519  )
520 {
521  assert(sepastore != NULL);
522  assert(sepastore->cuts != NULL);
523  assert(sepastore->nforcedcuts <= pos && pos < sepastore->ncuts);
524 
525  /* check, if the row deletions from separation storage events are tracked
526  * if so, issue ROWDELETEDSEPA event
527  */
528  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
529  {
530  SCIP_EVENT* event;
531 
532  SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[pos]) );
533  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
534  }
535 
536  /* release the row */
537  SCIP_CALL( SCIProwRelease(&sepastore->cuts[pos], blkmem, set, lp) );
538 
539  /* move last cut to the empty position */
540  sepastore->cuts[pos] = sepastore->cuts[sepastore->ncuts-1];
541  sepastore->efficacies[pos] = sepastore->efficacies[sepastore->ncuts-1];
542  sepastore->objparallelisms[pos] = sepastore->objparallelisms[sepastore->ncuts-1];
543  sepastore->orthogonalities[pos] = sepastore->orthogonalities[sepastore->ncuts-1];
544  sepastore->scores[pos] = sepastore->scores[sepastore->ncuts-1];
545  sepastore->ncuts--;
546 
547  return SCIP_OKAY;
548 }
549 
550 /** adds cut to separation storage and captures it;
551  * if the cut should be forced to enter the LP, an infinite score has to be used
552  */
554  SCIP_SEPASTORE* sepastore, /**< separation storage */
555  BMS_BLKMEM* blkmem, /**< block memory */
556  SCIP_SET* set, /**< global SCIP settings */
557  SCIP_STAT* stat, /**< problem statistics data */
558  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
559  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
560  SCIP_LP* lp, /**< LP data */
561  SCIP_SOL* sol, /**< primal solution that was separated, or NULL for LP solution */
562  SCIP_ROW* cut, /**< separated cut */
563  SCIP_Bool forcecut, /**< should the cut be forced to enter the LP? */
564  SCIP_Bool root, /**< are we at the root node? */
565  SCIP_Bool* infeasible /**< pointer to store whether the cut is infeasible */
566  )
567 {
568  assert(sepastore != NULL);
569  assert(cut != NULL);
570  assert(!SCIProwIsInLP(cut));
571  assert(!SCIPsetIsInfinity(set, -SCIProwGetLhs(cut)) || !SCIPsetIsInfinity(set, SCIProwGetRhs(cut)));
572 
573  /* debug: check cut for feasibility */
574  SCIP_CALL( SCIPdebugCheckRow(set, cut) ); /*lint !e506 !e774*/
575 
576  /* update statistics of total number of found cuts */
577  if( !sepastore->initiallp )
578  {
579  sepastore->ncutsfound++;
580  sepastore->ncutsfoundround++;
581  }
582 
583  /* add LP row cut to separation storage */
584  SCIP_CALL( sepastoreAddCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, sol, cut, forcecut, root, infeasible) );
585 
586  return SCIP_OKAY;
587 }
588 
589 /** applies a lower bound change */
590 static
592  SCIP_SEPASTORE* sepastore, /**< separation storage */
593  BMS_BLKMEM* blkmem, /**< block memory */
594  SCIP_SET* set, /**< global SCIP settings */
595  SCIP_STAT* stat, /**< problem statistics */
596  SCIP_PROB* transprob, /**< transformed problem */
597  SCIP_PROB* origprob, /**< original problem */
598  SCIP_TREE* tree, /**< branch and bound tree */
599  SCIP_REOPT* reopt, /**< reoptimization data structure */
600  SCIP_LP* lp, /**< LP data */
601  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
602  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
603  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
604  SCIP_VAR* var, /**< problem variable */
605  SCIP_Real bound, /**< new lower bound of variable */
606  SCIP_Bool local, /**< is it a local bound change? (otherwise global) */
607  SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
608  SCIP_Bool* cutoff /**< pointer to store TRUE, if an infeasibility has been detected */
609  )
610 {
611  assert(sepastore != NULL);
612  assert(cutoff != NULL);
613  assert(applied != NULL);
614 
615  /* adjust bound to the one that would be applied, so the SCIPsetIsGT check below is more reliable */
616  SCIPvarAdjustLb(var, set, &bound);
617 
618  if( local )
619  {
620  /* apply the local bound change or detect a cutoff */
621  if( SCIPsetIsGT(set, bound, SCIPvarGetLbLocal(var)) )
622  {
623  SCIPdebugMessage(" -> applying bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
625 
626  if( SCIPsetIsFeasLE(set, bound, SCIPvarGetUbLocal(var)) )
627  {
628  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob, tree,
629  reopt, lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_LOWER, FALSE) );
630  }
631  else
632  *cutoff = TRUE;
633 
634  *applied = TRUE;
635  }
636  else
637  {
638  SCIPdebugMessage(" -> ignoring bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
640  }
641  }
642  else
643  {
644  /* apply the global bound change or detect a global cutoff which means we can cutoff the root node */
645  if( SCIPsetIsGT(set, bound, SCIPvarGetLbGlobal(var)) )
646  {
647  SCIPdebugMessage(" -> applying global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
649 
650  if( SCIPsetIsFeasLE(set, bound, SCIPvarGetUbGlobal(var)) )
651  {
652  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob, tree, reopt,
653  lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_LOWER, FALSE) );
654  }
655  else
656  {
657  /* we are done with solving since a global bound change is infeasible */
658  SCIP_CALL( SCIPnodeCutoff(SCIPtreeGetRootNode(tree), set, stat, tree, reopt, lp, blkmem) );
659  *cutoff = TRUE;
660  }
661 
662  *applied = TRUE;
663  }
664  else
665  {
666  SCIPdebugMessage(" -> ignoring global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
668  }
669  }
670 
671  return SCIP_OKAY;
672 }
673 
674 /** applies an upper bound change */
675 static
677  SCIP_SEPASTORE* sepastore, /**< separation storage */
678  BMS_BLKMEM* blkmem, /**< block memory */
679  SCIP_SET* set, /**< global SCIP settings */
680  SCIP_STAT* stat, /**< problem statistics */
681  SCIP_PROB* transprob, /**< transformed problem */
682  SCIP_PROB* origprob, /**< original problem */
683  SCIP_TREE* tree, /**< branch and bound tree */
684  SCIP_REOPT* reopt, /**< reoptimization data structure */
685  SCIP_LP* lp, /**< LP data */
686  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
687  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
688  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
689  SCIP_VAR* var, /**< problem variable */
690  SCIP_Real bound, /**< new upper bound of variable */
691  SCIP_Bool local, /**< is it a local bound change? (otherwise global) */
692  SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
693  SCIP_Bool* cutoff /**< pointer to store TRUE, if an infeasibility has been detected */
694  )
695 {
696  assert(sepastore != NULL);
697  assert(cutoff != NULL);
698  assert(applied != NULL);
699 
700  /* adjust bound to the one that would be applied, so the SCIPsetIsGT check below is more reliable */
701  SCIPvarAdjustUb(var, set, &bound);
702 
703  if( local )
704  {
705  /* apply the local bound change or detect a cutoff */
706  if( SCIPsetIsLT(set, bound, SCIPvarGetUbLocal(var)) )
707  {
708  SCIPdebugMessage(" -> applying bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
710 
711  if( SCIPsetIsFeasGE(set, bound, SCIPvarGetLbLocal(var)) )
712  {
713  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob, tree,
714  reopt, lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_UPPER, FALSE) );
715  }
716  else
717  *cutoff = TRUE;
718 
719  *applied = TRUE;
720  }
721  else
722  {
723  SCIPdebugMessage(" -> ignoring bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
725  }
726  }
727  else
728  {
729  /* apply the global bound change or detect a global cutoff which means we can cutoff the root node */
730  if( SCIPsetIsLT(set, bound, SCIPvarGetUbGlobal(var)) )
731  {
732  SCIPdebugMessage(" -> applying global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
734 
735  if( SCIPsetIsFeasGE(set, bound, SCIPvarGetLbGlobal(var)) )
736  {
737  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob, tree, reopt,
738  lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_UPPER, FALSE) );
739  }
740  else
741  {
742  /* we are done with solving since a global bound change is infeasible */
743  SCIP_CALL( SCIPnodeCutoff(SCIPtreeGetRootNode(tree), set, stat, tree, reopt, lp, blkmem) );
744  *cutoff = TRUE;
745  }
746 
747  *applied = TRUE;
748  }
749  else
750  {
751  SCIPdebugMessage(" -> ignoring global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
753  }
754  }
755 
756  return SCIP_OKAY;
757 }
758 
759 /** applies a cut that is a bound change directly as bound change instead of adding it as row to the LP */
760 static
762  SCIP_SEPASTORE* sepastore, /**< separation storage */
763  BMS_BLKMEM* blkmem, /**< block memory */
764  SCIP_SET* set, /**< global SCIP settings */
765  SCIP_STAT* stat, /**< problem statistics */
766  SCIP_PROB* transprob, /**< transformed problem */
767  SCIP_PROB* origprob, /**< original problem */
768  SCIP_TREE* tree, /**< branch and bound tree */
769  SCIP_REOPT* reopt, /**< reoptimization data structure */
770  SCIP_LP* lp, /**< LP data */
771  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
772  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
773  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
774  SCIP_ROW* cut, /**< cut with a single variable */
775  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base feasibility computation on */
776  SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
777  SCIP_Bool* cutoff /**< pointer to store whether an empty domain was created */
778  )
779 {
780  SCIP_COL** cols;
781  SCIP_Real* vals;
782  SCIP_VAR* var;
783  SCIP_Real lhs;
784  SCIP_Real rhs;
785  SCIP_Bool local;
786 
787  assert(sepastore != NULL);
788  assert(!SCIProwIsModifiable(cut));
789  assert(SCIProwGetNNonz(cut) == 1);
790  assert(cutoff != NULL);
791  assert(applied != NULL);
792 
793  *applied = FALSE;
794  *cutoff = FALSE;
795 
796  /* get the single variable and its coefficient of the cut */
797  cols = SCIProwGetCols(cut);
798  assert(cols != NULL);
799 
800  var = SCIPcolGetVar(cols[0]);
801  vals = SCIProwGetVals(cut);
802  assert(vals != NULL);
803  assert(!SCIPsetIsZero(set, vals[0]));
804 
805  /* if the coefficient is nearly zero, we better ignore this cut for numerical reasons */
806  if( SCIPsetIsFeasZero(set, vals[0]) )
807  return SCIP_OKAY;
808 
809  local = SCIProwIsLocal(cut);
810 
811  /* get the left hand side of the cut and convert it to a bound */
812  lhs = SCIProwGetLhs(cut);
813  if( !SCIPsetIsInfinity(set, -lhs) )
814  {
815  lhs -= SCIProwGetConstant(cut);
816  if( vals[0] > 0.0 )
817  {
818  /* coefficient is positive -> lhs corresponds to lower bound */
819  SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
820  cliquetable, var, lhs/vals[0], local, applied, cutoff) );
821  }
822  else
823  {
824  /* coefficient is negative -> lhs corresponds to upper bound */
825  SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
826  cliquetable, var, lhs/vals[0], local, applied, cutoff) );
827  }
828  }
829 
830  /* get the right hand side of the cut and convert it to a bound */
831  rhs = SCIProwGetRhs(cut);
832  if( !SCIPsetIsInfinity(set, rhs) )
833  {
834  rhs -= SCIProwGetConstant(cut);
835  if( vals[0] > 0.0 )
836  {
837  /* coefficient is positive -> rhs corresponds to upper bound */
838  SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
839  cliquetable, var, rhs/vals[0], local, applied, cutoff) );
840  }
841  else
842  {
843  /* coefficient is negative -> rhs corresponds to lower bound */
844  SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
845  cliquetable, var, rhs/vals[0], local, applied, cutoff) );
846  }
847  }
848 
849  /* count the bound change as applied cut */
850  if( *applied && !sepastore->initiallp )
851  sepastore->ncutsapplied++;
852 
853  if( *applied && !sepastore->initiallp && set->sepa_feastolfac > 0.0 )
854  {
855  SCIP_Real infeasibility;
856 
857  /* calculate cut's infeasibility */
858  switch ( efficiacychoice )
859  {
861  infeasibility = -SCIProwGetLPFeasibility(cut, set, stat, lp);
862  break;
864  infeasibility = -SCIProwGetRelaxFeasibility(cut, set, stat);
865  break;
867  infeasibility = -SCIProwGetNLPFeasibility(cut, set, stat);
868  break;
869  default:
870  SCIPerrorMessage("Invalid efficiacy choice.\n");
871  return SCIP_INVALIDCALL;
872  }
873  /* a cut a*x<=b is applied as boundchange x<=b/a, so also the infeasibility needs to be divided by a (aka. scaled) */
874  infeasibility /= REALABS(vals[0]);
875 
876  /* reduce relaxation feasibility tolerance */
877  if( infeasibility > 0.0 && (set->sepa_primfeastol == SCIP_INVALID || set->sepa_primfeastol > set->sepa_feastolfac * infeasibility) ) /*lint !e777*/
878  {
879  SCIP_Real epsilon = SCIPsetEpsilon(set);
880 
881  set->sepa_primfeastol = MAX(set->sepa_feastolfac * infeasibility, epsilon);
882  SCIPdebugMessage("reduced feasibility tolerance for relaxations to %g due to cut <%s>\n", set->sepa_primfeastol, SCIProwGetName(cut));
883  }
884  }
885 
886  return SCIP_OKAY;
887 }
888 
889 /** updates the orthogonalities and scores of the non-forced cuts after the given cut was added to the LP */
890 static
892  SCIP_SEPASTORE* sepastore, /**< separation storage */
893  BMS_BLKMEM* blkmem, /**< block memory */
894  SCIP_SET* set, /**< global SCIP settings */
895  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
896  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
897  SCIP_LP* lp, /**< LP data */
898  SCIP_ROW* cut, /**< cut that was applied */
899  SCIP_Real mincutorthogonality /**< minimal orthogonality of cuts to apply to LP */
900  )
901 {
902  int pos;
903 
904  assert(sepastore != NULL);
905 
906  pos = sepastore->nforcedcuts;
907  while( pos < sepastore->ncuts )
908  {
909  SCIP_Real thisortho;
910 
911  /* update orthogonality */
912  thisortho = SCIProwGetOrthogonality(cut, sepastore->cuts[pos], set->sepa_orthofunc);
913  if( thisortho < sepastore->orthogonalities[pos] )
914  {
915  if( thisortho < mincutorthogonality )
916  {
917  /* cut is too parallel: release the row and delete the cut */
918  SCIPdebugMessage(" -> deleting parallel cut <%s> after adding <%s> (pos=%d, len=%d, orthogonality=%g, score=%g)\n",
919  SCIProwGetName(sepastore->cuts[pos]), SCIProwGetName(cut), pos, SCIProwGetNNonz(cut), thisortho, sepastore->scores[pos]);
920  SCIP_CALL( sepastoreDelCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, pos) );
921  continue;
922  }
923  else
924  {
925  /* recalculate score */
926  sepastore->orthogonalities[pos] = thisortho;
927  assert( sepastore->objparallelisms[pos] != SCIP_INVALID ); /*lint !e777*/
928  assert( sepastore->scores[pos] != SCIP_INVALID ); /*lint !e777*/
929  assert( sepastore->efficacies[pos] != SCIP_INVALID ); /*lint !e777*/
930  sepastore->scores[pos] = sepastore->efficacies[pos]
931  + set->sepa_objparalfac * sepastore->objparallelisms[pos]
932  + set->sepa_orthofac * thisortho;
933  }
934  }
935  pos++;
936  }
937 
938  return SCIP_OKAY;
939 }
940 
941 /** applies the given cut to the LP and updates the orthogonalities and scores of remaining cuts */
942 static
944  SCIP_SEPASTORE* sepastore, /**< separation storage */
945  BMS_BLKMEM* blkmem, /**< block memory */
946  SCIP_SET* set, /**< global SCIP settings */
947  SCIP_STAT* stat, /**< problem statistics */
948  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
949  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
950  SCIP_LP* lp, /**< LP data */
951  SCIP_ROW* cut, /**< cut to apply to the LP */
952  SCIP_Real mincutorthogonality,/**< minimal orthogonality of cuts to apply to LP */
953  int depth, /**< depth of current node */
954  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base feasibility computation on */
955  int* ncutsapplied /**< pointer to count the number of applied cuts */
956  )
957 {
958  assert(sepastore != NULL);
959  assert(ncutsapplied != NULL);
960 
961  /* a row could have been added twice to the separation store; add it only once! */
962  if( !SCIProwIsInLP(cut) )
963  {
964  /* add cut to the LP and capture it */
965  SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, cut, depth) );
966 
967  /* update statistics -> only if we are not in the initial lp (cuts are only counted if added during run) */
968  if( !sepastore->initiallp )
969  {
970  sepastore->ncutsapplied++;
971 
972  /* increase count of applied cuts for origins of row */
973  switch ( cut->origintype )
974  {
976  assert( cut->origin != NULL );
978  break;
980  assert( cut->origin != NULL );
982  break;
984  /* do nothing - cannot update statistics */
985  break;
986  default:
987  SCIPerrorMessage("unkown type of row origin.\n");
988  return SCIP_INVALIDDATA;
989  }
990  }
991 
992  /* update the orthogonalities */
993  SCIP_CALL( sepastoreUpdateOrthogonalities(sepastore, blkmem, set, eventqueue, eventfilter, lp, cut, mincutorthogonality) );
994  (*ncutsapplied)++;
995 
996  if( !sepastore->initiallp && set->sepa_feastolfac > 0.0 )
997  {
998  SCIP_Real infeasibility;
999 
1000  /* calculate cut's infeasibility */
1001  switch ( efficiacychoice )
1002  {
1004  infeasibility = -SCIProwGetLPFeasibility(cut, set, stat, lp);
1005  break;
1007  infeasibility = -SCIProwGetRelaxFeasibility(cut, set, stat);
1008  break;
1010  infeasibility = -SCIProwGetNLPFeasibility(cut, set, stat);
1011  break;
1012  default:
1013  SCIPerrorMessage("Invalid efficiacy choice.\n");
1014  return SCIP_INVALIDCALL;
1015  }
1016 
1017  /* reduce relaxation feasibility tolerance */
1018  if( infeasibility > 0.0 && (set->sepa_primfeastol == SCIP_INVALID || set->sepa_primfeastol > set->sepa_feastolfac * infeasibility) ) /*lint !e777*/
1019  {
1020  SCIP_Real epsilon = SCIPsetEpsilon(set);
1021 
1022  set->sepa_primfeastol = MAX(set->sepa_feastolfac * infeasibility, epsilon);
1023  SCIPdebugMessage("reduced feasibility tolerance for relaxations to %g due to cut <%s>\n", set->sepa_primfeastol, SCIProwGetName(cut));
1024  }
1025  }
1026  }
1027 
1028  return SCIP_OKAY;
1029 }
1030 
1031 /** returns the position of the best non-forced cut in the cuts array */
1032 static
1034  SCIP_SEPASTORE* sepastore /**< separation storage */
1035  )
1036 {
1037  SCIP_Real bestscore;
1038  int bestpos;
1039  int pos;
1040 
1041  assert(sepastore != NULL);
1042 
1043  bestscore = SCIP_REAL_MIN;
1044  bestpos = -1;
1045  for( pos = sepastore->nforcedcuts; pos < sepastore->ncuts; pos++ )
1046  {
1047  /* check if cut is current best cut */
1048  assert( sepastore->scores[pos] != SCIP_INVALID ); /*lint !e777*/
1049  if( sepastore->scores[pos] > bestscore )
1050  {
1051  bestscore = sepastore->scores[pos];
1052  bestpos = pos;
1053  }
1054  }
1055 
1056  return bestpos;
1057 }
1058 
1059 /** computes score for current LP solution and initialized orthogonalities */
1060 static
1062  SCIP_SEPASTORE* sepastore, /**< separation storage */
1063  SCIP_SET* set, /**< global SCIP settings */
1064  SCIP_STAT* stat, /**< problem statistics */
1065  SCIP_LP* lp, /**< LP data */
1066  SCIP_Bool handlepool, /**< whether the efficacy of cuts in the pool should be reduced */
1067  int pos, /**< position of cut to handle */
1068  SCIP_EFFICIACYCHOICE efficiacychoice /**< type of solution to base efficiacy computation on */
1069  )
1070 {
1071  SCIP_ROW* cut;
1072  SCIP_Real cutefficacy;
1073  SCIP_Real cutscore;
1074 
1075  cut = sepastore->cuts[pos];
1076 
1077  /* calculate cut's efficacy */
1078  switch ( efficiacychoice )
1079  {
1081  cutefficacy = SCIProwGetLPEfficacy(cut, set, stat, lp);
1082  break;
1084  cutefficacy = SCIProwGetRelaxEfficacy(cut, set, stat);
1085  break;
1087  cutefficacy = SCIProwGetNLPEfficacy(cut, set, stat);
1088  break;
1089  default:
1090  SCIPerrorMessage("Invalid efficiacy choice.\n");
1091  return SCIP_INVALIDCALL;
1092  }
1093 
1094  /* If a cut is not member of the cut pool, we slightly decrease its score to prefer identical
1095  * cuts which are in the cut pool. This is because the conversion of cuts into linear
1096  * constraints after a restart looks at the cut pool and cannot find tight non-pool cuts.
1097  */
1098  if( handlepool && !SCIProwIsInGlobalCutpool(cut) )
1099  cutefficacy *= 0.9999;
1100 
1101  /* calculate resulting score */
1102  assert( sepastore->objparallelisms[pos] != SCIP_INVALID ); /*lint !e777*/
1103  cutscore = cutefficacy + set->sepa_objparalfac * sepastore->objparallelisms[pos] + set->sepa_orthofac * 1.0;
1104  assert( !SCIPsetIsInfinity(set, cutscore) );
1105 
1106  sepastore->efficacies[pos] = cutefficacy;
1107  sepastore->scores[pos] = cutscore;
1108 
1109  /* make sure that the orthogonalities are initialized to 1.0 */
1110  sepastore->orthogonalities[pos] = 1.0;
1111 
1112  return SCIP_OKAY;
1113 }
1114 
1115 /** adds cuts to the LP and clears separation storage */
1117  SCIP_SEPASTORE* sepastore, /**< separation storage */
1118  BMS_BLKMEM* blkmem, /**< block memory */
1119  SCIP_SET* set, /**< global SCIP settings */
1120  SCIP_STAT* stat, /**< problem statistics */
1121  SCIP_PROB* transprob, /**< transformed problem */
1122  SCIP_PROB* origprob, /**< original problem */
1123  SCIP_TREE* tree, /**< branch and bound tree */
1124  SCIP_REOPT* reopt, /**< reoptimization data structure */
1125  SCIP_LP* lp, /**< LP data */
1126  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1127  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1128  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1129  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1130  SCIP_Bool root, /**< are we at the root node? */
1131  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base efficiacy computation on */
1132  SCIP_Bool* cutoff /**< pointer to store whether an empty domain was created */
1133  )
1134 {
1135  SCIP_NODE* node;
1136  SCIP_Real mincutorthogonality;
1137  SCIP_Bool applied;
1138  int depth;
1139  int maxsepacuts;
1140  int ncutsapplied;
1141  int pos;
1142 
1143  assert(sepastore != NULL);
1144  assert(set != NULL);
1145  assert(tree != NULL);
1146  assert(lp != NULL);
1147  assert(cutoff != NULL);
1148 
1149  *cutoff = FALSE;
1150 
1151  SCIPdebugMessage("applying %d cuts\n", sepastore->ncuts);
1152 
1153  node = SCIPtreeGetCurrentNode(tree);
1154  assert(node != NULL);
1155 
1156  /* get maximal number of cuts to add to the LP */
1157  maxsepacuts = SCIPsetGetSepaMaxcuts(set, root);
1158  ncutsapplied = 0;
1159 
1160  /* get depth of current node */
1161  depth = SCIPnodeGetDepth(node);
1162 
1163  /* calculate minimal cut orthogonality */
1164  mincutorthogonality = (root ? set->sepa_minorthoroot : set->sepa_minortho);
1165  mincutorthogonality = MAX(mincutorthogonality, set->num_epsilon);
1166 
1167  /* Compute scores for all non-forced cuts and initialize orthogonalities - make sure all cuts are initialized again for the current LP solution */
1168  for( pos = sepastore->nforcedcuts; pos < sepastore->ncuts; pos++ )
1169  {
1170  SCIP_CALL( computeScore(sepastore, set, stat, lp, TRUE, pos, efficiacychoice) );
1171  }
1172 
1173  /* apply all forced cuts */
1174  for( pos = 0; pos < sepastore->nforcedcuts && !(*cutoff); pos++ )
1175  {
1176  SCIP_ROW* cut;
1177 
1178  cut = sepastore->cuts[pos];
1179  assert(SCIPsetIsInfinity(set, sepastore->scores[pos]));
1180 
1181  /* if the cut is a bound change (i.e. a row with only one variable), add it as bound change instead of LP row */
1182  applied = FALSE;
1183  if( !SCIProwIsModifiable(cut) && SCIProwGetNNonz(cut) == 1 )
1184  {
1185  SCIPdebugMessage(" -> applying forced cut <%s> as boundchange\n", SCIProwGetName(cut));
1186  SCIP_CALL( sepastoreApplyBdchg(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
1187  eventqueue, cliquetable, cut, efficiacychoice, &applied, cutoff) );
1188 
1189  assert(applied || !sepastoreIsBdchgApplicable(set, cut));
1190  }
1191 
1192  if( !applied )
1193  {
1194  /* add cut to the LP and update orthogonalities */
1195  SCIPdebugMessage(" -> applying forced cut <%s>\n", SCIProwGetName(cut));
1196  /*SCIPdebug( SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
1197  SCIP_CALL( sepastoreApplyCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, mincutorthogonality, depth, efficiacychoice, &ncutsapplied) );
1198  }
1199  }
1200 
1201  /* apply non-forced cuts */
1202  while( ncutsapplied < maxsepacuts && sepastore->ncuts > sepastore->nforcedcuts && !(*cutoff) )
1203  {
1204  SCIP_ROW* cut;
1205  int bestpos;
1206 
1207  /* get best non-forced cut */
1208  bestpos = sepastoreGetBestCut(sepastore);
1209  assert(sepastore->nforcedcuts <= bestpos && bestpos < sepastore->ncuts);
1210  assert(sepastore->scores[bestpos] != SCIP_INVALID ); /*lint !e777*/
1211  assert(sepastore->efficacies[bestpos] != SCIP_INVALID ); /*lint !e777*/
1212  cut = sepastore->cuts[bestpos];
1213  assert(SCIProwIsModifiable(cut) || SCIProwGetNNonz(cut) != 1 || !sepastoreIsBdchgApplicable(set, cut)); /* applicable bound changes are forced cuts */
1214  assert(!SCIPsetIsInfinity(set, sepastore->scores[bestpos]));
1215 
1216  SCIPdebugMessage(" -> applying cut <%s> (pos=%d/%d, len=%d, efficacy=%g, objparallelism=%g, orthogonality=%g, score=%g)\n",
1217  SCIProwGetName(cut), bestpos, sepastore->ncuts, SCIProwGetNNonz(cut), sepastore->efficacies[bestpos], sepastore->objparallelisms[bestpos],
1218  sepastore->orthogonalities[bestpos], sepastore->scores[bestpos]);
1219  /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
1220 
1221  /* capture cut such that it is not destroyed in sepastoreDelCut() */
1222  SCIProwCapture(cut);
1223 
1224  /* release the row and delete the cut (also issuing ROWDELETEDSEPA event) */
1225  SCIP_CALL( sepastoreDelCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, bestpos) );
1226 
1227  /* Do not add (non-forced) non-violated cuts.
1228  * Note: do not take SCIPsetIsEfficacious(), because constraint handlers often add cuts w.r.t. SCIPsetIsFeasPositive().
1229  * Note2: if separating/feastolfac != -1, constraint handlers may even add cuts w.r.t. SCIPsetIsPositive(); those are currently rejected here
1230  */
1231  if( SCIPsetIsFeasPositive(set, sepastore->efficacies[bestpos]) )
1232  {
1233  /* add cut to the LP and update orthogonalities */
1234  SCIP_CALL( sepastoreApplyCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, mincutorthogonality, depth, efficiacychoice, &ncutsapplied) );
1235  }
1236 
1237  /* release cut */
1238  SCIP_CALL( SCIProwRelease(&cut, blkmem, set, lp) );
1239  }
1240 
1241  /* clear the separation storage and reset statistics for separation round */
1242  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
1243 
1244  return SCIP_OKAY;
1245 }
1246 
1247 /** clears the separation storage without adding the cuts to the LP */
1249  SCIP_SEPASTORE* sepastore, /**< separation storage */
1250  BMS_BLKMEM* blkmem, /**< block memory */
1251  SCIP_SET* set, /**< global SCIP settings */
1252  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1253  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
1254  SCIP_LP* lp /**< LP data */
1255  )
1256 {
1257  int c;
1258 
1259  assert(sepastore != NULL);
1260 
1261  SCIPdebugMessage("clearing %d cuts\n", sepastore->ncuts);
1262 
1263  /* release cuts */
1264  for( c = 0; c < sepastore->ncuts; ++c )
1265  {
1266  /* check, if the row deletions from separation storage events are tracked
1267  * if so, issue ROWDELETEDSEPA event
1268  */
1269  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
1270  {
1271  SCIP_EVENT* event;
1272 
1273  SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[c]) );
1274  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
1275  }
1276 
1277  SCIP_CALL( SCIProwRelease(&sepastore->cuts[c], blkmem, set, lp) );
1278  }
1279 
1280  /* reset counters */
1281  sepastore->ncuts = 0;
1282  sepastore->nforcedcuts = 0;
1283  sepastore->ncutsfoundround = 0;
1284 
1285  /* if we have just finished the initial LP construction, free the (potentially large) cuts array */
1286  if( sepastore->initiallp )
1287  {
1288  BMSfreeMemoryArrayNull(&sepastore->cuts);
1289  sepastore->cutssize = 0;
1290  }
1291 
1292  return SCIP_OKAY;
1293 }
1294 
1295 /** removes cuts that are inefficacious w.r.t. the current LP solution from separation storage without adding the cuts to the LP */
1297  SCIP_SEPASTORE* sepastore, /**< separation storage */
1298  BMS_BLKMEM* blkmem, /**< block memory */
1299  SCIP_SET* set, /**< global SCIP settings */
1300  SCIP_STAT* stat, /**< problem statistics data */
1301  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1302  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
1303  SCIP_LP* lp, /**< LP data */
1304  SCIP_Bool root, /**< are we at the root node? */
1305  SCIP_EFFICIACYCHOICE efficiacychoice /**< type of solution to base efficiacy computation on */
1306  )
1307 {
1308  int cnt;
1309  int c;
1310 
1311  assert( sepastore != NULL );
1312 
1313  /* check non-forced cuts only */
1314  cnt = 0;
1315  c = sepastore->nforcedcuts;
1316  while( c < sepastore->ncuts )
1317  {
1318  assert( sepastore->efficacies[c] == SCIP_INVALID ); /*lint !e777*/
1319  SCIP_CALL( computeScore(sepastore, set, stat, lp, FALSE, c, efficiacychoice) );
1320  if( !SCIPsetIsEfficacious(set, root, sepastore->efficacies[c]) )
1321  {
1322  SCIP_CALL( sepastoreDelCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, c) );
1323  ++cnt;
1324  }
1325  else
1326  ++c;
1327  }
1328  SCIPdebugMessage("removed %d non-efficacious cuts\n", cnt);
1329 
1330  return SCIP_OKAY;
1331 }
1332 
1333 /** indicates whether a cut is applicable
1334  *
1335  * A cut is applicable if it is modifiable, not a bound change, or a bound change that changes bounds by at least epsilon.
1336  */
1338  SCIP_SET* set, /**< global SCIP settings */
1339  SCIP_ROW* cut /**< cut to check */
1340  )
1341 {
1342  return SCIProwIsModifiable(cut) || SCIProwGetNNonz(cut) != 1 || sepastoreIsBdchgApplicable(set, cut);
1343 }
1344 
1345 /** get cuts in the separation storage */
1347  SCIP_SEPASTORE* sepastore /**< separation storage */
1348  )
1349 {
1350  assert(sepastore != NULL);
1351 
1352  return sepastore->cuts;
1353 }
1354 
1355 /** get number of cuts in the separation storage */
1357  SCIP_SEPASTORE* sepastore /**< separation storage */
1358  )
1359 {
1360  assert(sepastore != NULL);
1361 
1362  return sepastore->ncuts;
1363 }
1364 
1365 /** get total number of cuts found so far */
1367  SCIP_SEPASTORE* sepastore /**< separation storage */
1368  )
1369 {
1370  assert(sepastore != NULL);
1371 
1372  return sepastore->ncutsfound;
1373 }
1374 
1375 /** get number of cuts found so far in current separation round */
1377  SCIP_SEPASTORE* sepastore /**< separation storage */
1378  )
1379 {
1380  assert(sepastore != NULL);
1381 
1382  return sepastore->ncutsfoundround;
1383 }
1384 
1385 /** get total number of cuts applied to the LPs */
1387  SCIP_SEPASTORE* sepastore /**< separation storage */
1388  )
1389 {
1390  assert(sepastore != NULL);
1391 
1392  return sepastore->ncutsapplied;
1393 }
char sepa_orthofunc
Definition: struct_set.h:419
internal methods for separators
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5031
static SCIP_RETCODE sepastoreApplyLb(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real bound, SCIP_Bool local, SCIP_Bool *applied, SCIP_Bool *cutoff)
Definition: sepastore.c:591
internal methods for managing events
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5089
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16341
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5539
void * origin
Definition: struct_lp.h:213
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition: lp.c:19093
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:103
internal methods for branch and bound tree
enum SCIP_Efficiacychoice SCIP_EFFICIACYCHOICE
SCIP_Real SCIProwGetRelaxFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6038
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2057
void SCIPsepaIncNAppliedCuts(SCIP_SEPA *sepa)
Definition: sepa.c:800
unsigned int origintype
Definition: struct_lp.h:251
SCIP_ROW ** SCIPsepastoreGetCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1346
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17011
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18914
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18860
void SCIProwCapture(SCIP_ROW *row)
Definition: lp.c:5105
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16965
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7026
void SCIPsepastoreStartForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:148
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:4893
static SCIP_RETCODE sepastoreUpdateOrthogonalities(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_ROW *cut, SCIP_Real mincutorthogonality)
Definition: sepastore.c:891
int SCIPsepastoreGetNCutsApplied(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1386
#define FALSE
Definition: def.h:53
SCIP_Real sepa_primfeastol
Definition: struct_set.h:416
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5143
#define TRUE
Definition: def.h:52
#define SCIPdebugCheckRow(set, row)
Definition: debug.h:234
SCIP_Real sepa_minortho
Definition: struct_set.h:411
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIProwGetLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6487
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4626
SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6643
static SCIP_Bool sepastoreIsCutRedundant(SCIP_SEPASTORE *sepastore, SCIP_SET *set, SCIP_STAT *stat, SCIP_ROW *cut)
Definition: sepastore.c:171
SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
Definition: tree.c:1123
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18880
#define BMSfreeMemory(ptr)
Definition: memory.h:100
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6014
SCIP_Real * scores
internal methods for LP management
int SCIPsetGetSepaMaxcuts(SCIP_SET *set, SCIP_Bool root)
Definition: set.c:4782
SCIP_ROW ** cuts
SCIP_Bool SCIPsetIsEfficacious(SCIP_SET *set, SCIP_Bool root, SCIP_Real efficacy)
Definition: set.c:5893
SCIP_RETCODE SCIPeventCreateRowDeletedSepa(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:762
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5071
SCIP_Bool SCIPsepastoreIsCutApplicable(SCIP_SET *set, SCIP_ROW *cut)
Definition: sepastore.c:1337
SCIP_Real sepa_orthofac
Definition: struct_set.h:414
#define SCIP_EVENTTYPE_ROWADDEDSEPA
Definition: type_event.h:85
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:19033
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18924
static SCIP_RETCODE sepastoreApplyCut(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_Real mincutorthogonality, int depth, SCIP_EFFICIACYCHOICE efficiacychoice, int *ncutsapplied)
Definition: sepastore.c:943
SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
Definition: lp.c:5493
int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1356
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:19125
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:19023
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:1296
SCIP_RETCODE SCIPsepastoreCreate(SCIP_SEPASTORE **sepastore)
Definition: sepastore.c:79
SCIP_Real SCIProwGetNLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6100
SCIP_RETCODE SCIPlpAddRow(SCIP_LP *lp, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_ROW *row, int depth)
Definition: lp.c:9022
#define REALABS(x)
Definition: def.h:148
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:263
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5517
static int sepastoreGetBestCut(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1033
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18973
SCIP_Real * orthogonalities
unsigned int eventmask
Definition: struct_event.h:179
internal methods for storing separated cuts
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5473
static SCIP_RETCODE sepastoreDelCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, int pos)
Definition: sepastore.c:511
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5118
data structures and methods for collecting reoptimization information
internal methods for problem variables
SCIP_Real sepa_feastolfac
Definition: struct_set.h:415
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17021
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_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool root, SCIP_Bool *infeasible)
Definition: sepastore.c:553
#define SCIP_Bool
Definition: def.h:50
static SCIP_Bool sepastoreIsCutRedundantOrInfeasible(SCIP_SEPASTORE *sepastore, SCIP_SET *set, SCIP_STAT *stat, SCIP_ROW *cut, SCIP_Bool *infeasible)
Definition: sepastore.c:208
static SCIP_RETCODE sepastoreApplyUb(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real bound, SCIP_Bool local, SCIP_Bool *applied, SCIP_Bool *cutoff)
Definition: sepastore.c:676
#define MAX(x, y)
Definition: tclique_def.h:75
void SCIPconshdlrIncNAppliedCuts(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4545
methods for debugging
SCIP_RETCODE SCIPsepastoreFree(SCIP_SEPASTORE **sepastore)
Definition: sepastore.c:105
#define SCIP_EVENTTYPE_ROWDELETEDSEPA
Definition: type_event.h:86
static SCIP_RETCODE sepastoreEnsureCutsMem(SCIP_SEPASTORE *sepastore, SCIP_SET *set, int num)
Definition: sepastore.c:49
static SCIP_Bool sepastoreIsBdchgApplicable(SCIP_SET *set, SCIP_ROW *cut)
Definition: sepastore.c:264
void SCIPsepastoreEndInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:136
SCIP_Real SCIProwGetRelaxEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6603
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5451
void SCIPsepastoreStartInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:124
SCIP_Real num_epsilon
Definition: struct_set.h:338
SCIP_Real SCIProwGetOrthogonality(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7435
SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6371
#define SCIP_REAL_MIN
Definition: def.h:126
int SCIPsepastoreGetNCutsFound(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1366
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16955
SCIP_Real sepa_minorthoroot
Definition: struct_set.h:412
SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6350
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8007
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:1979
SCIP_Real sepa_objparalfac
Definition: struct_set.h:413
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:7940
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18870
SCIP_RETCODE SCIPsepastoreApplyCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool root, SCIP_EFFICIACYCHOICE efficiacychoice, SCIP_Bool *cutoff)
Definition: sepastore.c:1116
SCIP_Real SCIProwGetLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6018
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5107
static SCIP_RETCODE computeScore(SCIP_SEPASTORE *sepastore, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_Bool handlepool, int pos, SCIP_EFFICIACYCHOICE efficiacychoice)
Definition: sepastore.c:1061
#define SCIP_Real
Definition: def.h:124
internal methods for problem statistics
#define MIN(x, y)
Definition: memory.c:63
SCIP_Real SCIProwGetObjParallelism(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:7447
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5550
int SCIPsepastoreGetNCutsFoundRound(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1376
#define BMSallocMemory(ptr)
Definition: memory.h:74
SCIP_Real * efficacies
#define SCIP_INVALID
Definition: def.h:144
#define BMSreallocMemoryArray(ptr, num)
Definition: memory.h:82
internal methods for constraints and constraint handlers
static SCIP_RETCODE sepastoreApplyBdchg(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_ROW *cut, SCIP_EFFICIACYCHOICE efficiacychoice, SCIP_Bool *applied, SCIP_Bool *cutoff)
Definition: sepastore.c:761
SCIP_Real * objparallelisms
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5495
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:4915
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18835
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6031
SCIP_Bool initiallp
datastructures for storing separated cuts
common defines and data types used in all packages of SCIP
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18684
SCIP_RETCODE SCIPsepastoreClearCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
Definition: sepastore.c:1248
#define SCIP_ALLOC(x)
Definition: def.h:274
SCIP_Bool forcecuts
static SCIP_RETCODE sepastoreAddCut(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp, SCIP_SOL *sol, SCIP_ROW *cut, SCIP_Bool forcecut, SCIP_Bool root, SCIP_Bool *infeasible)
Definition: sepastore.c:365
void SCIPsepastoreEndForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:159
SCIP_RETCODE SCIPeventCreateRowAddedSepa(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:743