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