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-2017 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  SCIPsetDebugMsg(set, "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  SCIPsetDebugMsg(set, "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  SCIPsetDebugMsg(set, "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 /** removes a non-forced cut from the separation storage */
363 static
365  SCIP_SEPASTORE* sepastore, /**< separation storage */
366  BMS_BLKMEM* blkmem, /**< block memory */
367  SCIP_SET* set, /**< global SCIP settings */
368  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
369  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
370  SCIP_LP* lp, /**< LP data */
371  int pos /**< position of cut to delete */
372  )
373 {
374  assert(sepastore != NULL);
375  assert(sepastore->cuts != NULL);
376  assert(sepastore->nforcedcuts <= pos && pos < sepastore->ncuts);
377 
378  /* check, if the row deletions from separation storage events are tracked
379  * if so, issue ROWDELETEDSEPA event
380  */
381  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
382  {
383  SCIP_EVENT* event;
384 
385  SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[pos]) );
386  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
387  }
388 
389  /* release the row */
390  SCIP_CALL( SCIProwRelease(&sepastore->cuts[pos], blkmem, set, lp) );
391 
392  /* move last cut to the empty position */
393  sepastore->cuts[pos] = sepastore->cuts[sepastore->ncuts-1];
394  sepastore->efficacies[pos] = sepastore->efficacies[sepastore->ncuts-1];
395  sepastore->objparallelisms[pos] = sepastore->objparallelisms[sepastore->ncuts-1];
396  sepastore->orthogonalities[pos] = sepastore->orthogonalities[sepastore->ncuts-1];
397  sepastore->scores[pos] = sepastore->scores[sepastore->ncuts-1];
398  sepastore->ncuts--;
399 
400  return SCIP_OKAY;
401 }
402 
403 /** adds cut to separation storage and captures it;
404  * if the cut should be forced to enter the LP, an infinite score has to be used
405  */
407  SCIP_SEPASTORE* sepastore, /**< separation storage */
408  BMS_BLKMEM* blkmem, /**< block memory */
409  SCIP_SET* set, /**< global SCIP settings */
410  SCIP_STAT* stat, /**< problem statistics data */
411  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
412  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
413  SCIP_LP* lp, /**< LP data */
414  SCIP_SOL* sol, /**< primal solution that was separated, or NULL for LP solution */
415  SCIP_ROW* cut, /**< separated cut */
416  SCIP_Bool forcecut, /**< should the cut be forced to enter the LP? */
417  SCIP_Bool root, /**< are we at the root node? */
418  SCIP_Bool* infeasible /**< pointer to store whether the cut is infeasible */
419  )
420 {
421  SCIP_Real cutefficacy;
422  SCIP_Real cutobjparallelism;
423  SCIP_Real cutscore;
424  SCIP_Bool redundant;
425  int pos;
426 
427  assert(sepastore != NULL);
428  assert(sepastore->nforcedcuts <= sepastore->ncuts);
429  assert(set != NULL);
430  assert(cut != NULL);
431  assert(sol != NULL || !SCIProwIsInLP(cut));
432  assert(!SCIPsetIsInfinity(set, -SCIProwGetLhs(cut)) || !SCIPsetIsInfinity(set, SCIProwGetRhs(cut)));
433  assert(eventqueue != NULL);
434  assert(eventfilter != NULL);
435 
436  /* debug: check cut for feasibility */
437  SCIP_CALL( SCIPdebugCheckRow(set, cut) ); /*lint !e506 !e774*/
438 
439  /* update statistics of total number of found cuts */
440  if( !sepastore->initiallp )
441  {
442  sepastore->ncutsfound++;
443  sepastore->ncutsfoundround++;
444  }
445 
446  /* in the root node, every local cut is a global cut, and global cuts are nicer in many ways...*/
447  if( root && SCIProwIsLocal(cut) )
448  {
449  SCIPsetDebugMsg(set, "change local flag of cut <%s> to FALSE due to addition in root node\n", SCIProwGetName(cut));
450 
452 
453  assert(!SCIProwIsLocal(cut));
454  }
455 
456  /* check cut for redundancy or infeasibility */
457  redundant = sepastoreIsCutRedundantOrInfeasible(sepastore, set, stat, cut, infeasible);
458  /* Note that we add infeasible rows in any case, since we cannot be sure whether the return values are handled
459  * correctly. In this way, the LP becomes infeasible. */
460 
461  /* in each separation round, make sure that at least one (even redundant) cut enters the LP to avoid cycling */
462  if( !forcecut && sepastore->ncuts > 0 && redundant )
463  return SCIP_OKAY;
464 
465  /* if only one cut is currently present in the cut store, it could be redundant; in this case, it can now be removed
466  * again, because now a non redundant cut enters the store
467  */
468  if( sepastore->ncuts == 1 && sepastoreIsCutRedundant(sepastore, set, stat, sepastore->cuts[0]) )
469  {
470  /* check, if the row deletions from separation storage events are tracked if so, issue ROWDELETEDSEPA event */
471  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
472  {
473  SCIP_EVENT* event;
474 
475  SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[0]) );
476  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
477  }
478 
479  SCIP_CALL( SCIProwRelease(&sepastore->cuts[0], blkmem, set, lp) );
480  sepastore->ncuts = 0;
481  sepastore->nforcedcuts = 0;
482  }
483 
484  /* a cut is forced to enter the LP if
485  * - we construct the initial LP, or
486  * - it has infinite score factor, or
487  * - it is a bound change that can be applied
488  * if it is a non-forced cut and no cuts should be added, abort
489  */
490  forcecut = forcecut || sepastore->initiallp || sepastore->forcecuts || (!SCIProwIsModifiable(cut) && SCIProwGetNNonz(cut) == 1 && sepastoreIsBdchgApplicable(set, cut));
491  if( !forcecut && SCIPsetGetSepaMaxcuts(set, root) == 0 )
492  return SCIP_OKAY;
493 
494  /* get enough memory to store the cut */
495  SCIP_CALL( sepastoreEnsureCutsMem(sepastore, set, sepastore->ncuts+1) );
496  assert(sepastore->ncuts < sepastore->cutssize);
497 
498  if( forcecut )
499  {
500  cutefficacy = SCIPsetInfinity(set);
501  cutscore = SCIPsetInfinity(set);
502  cutobjparallelism = 1.0;
503  }
504  else
505  {
506  /* initialize values to invalid (will be initialized during cut filtering) */
507  cutefficacy = SCIP_INVALID;
508  cutscore = SCIP_INVALID;
509 
510  /* initialize parallelism to objective (constant throughout filtering) */
511  if( set->sepa_objparalfac > 0.0 )
512  cutobjparallelism = SCIProwGetObjParallelism(cut, set, lp);
513  else
514  cutobjparallelism = 0.0; /* no need to calculate it */
515  }
516 
517  SCIPsetDebugMsg(set, "adding cut <%s> to separation storage of size %d (forcecut=%u, len=%d)\n",
518  SCIProwGetName(cut), sepastore->ncuts, forcecut, SCIProwGetNNonz(cut));
519  /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
520 
521  /* capture the cut */
522  SCIProwCapture(cut);
523 
524  /* add cut to arrays */
525  if( forcecut )
526  {
527  /* make room at the beginning of the array for forced cut */
528  pos = sepastore->nforcedcuts;
529  sepastore->cuts[sepastore->ncuts] = sepastore->cuts[pos];
530  sepastore->efficacies[sepastore->ncuts] = sepastore->efficacies[pos];
531  sepastore->objparallelisms[sepastore->ncuts] = sepastore->objparallelisms[pos];
532  sepastore->orthogonalities[sepastore->ncuts] = sepastore->orthogonalities[pos];
533  sepastore->scores[sepastore->ncuts] = sepastore->scores[pos];
534  sepastore->nforcedcuts++;
535  }
536  else
537  pos = sepastore->ncuts;
538 
539  sepastore->cuts[pos] = cut;
540  sepastore->efficacies[pos] = cutefficacy;
541  sepastore->objparallelisms[pos] = cutobjparallelism;
542  sepastore->orthogonalities[pos] = 1.0;
543  sepastore->scores[pos] = cutscore;
544  sepastore->ncuts++;
545 
546  /* check, if the row addition to separation storage events are tracked
547  * if so, issue ROWADDEDSEPA event
548  */
549  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWADDEDSEPA) != 0 )
550  {
551  SCIP_EVENT* event;
552 
553  SCIP_CALL( SCIPeventCreateRowAddedSepa(&event, blkmem, cut) );
554  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
555  }
556 
557  return SCIP_OKAY;
558 }
559 
560 /** applies a lower bound change */
561 static
563  SCIP_SEPASTORE* sepastore, /**< separation storage */
564  BMS_BLKMEM* blkmem, /**< block memory */
565  SCIP_SET* set, /**< global SCIP settings */
566  SCIP_STAT* stat, /**< problem statistics */
567  SCIP_PROB* transprob, /**< transformed problem */
568  SCIP_PROB* origprob, /**< original problem */
569  SCIP_TREE* tree, /**< branch and bound tree */
570  SCIP_REOPT* reopt, /**< reoptimization data structure */
571  SCIP_LP* lp, /**< LP data */
572  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
573  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
574  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
575  SCIP_VAR* var, /**< problem variable */
576  SCIP_Real bound, /**< new lower bound of variable */
577  SCIP_Bool local, /**< is it a local bound change? (otherwise global) */
578  SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
579  SCIP_Bool* cutoff /**< pointer to store TRUE, if an infeasibility has been detected */
580  )
581 {
582  assert(sepastore != NULL);
583  assert(cutoff != NULL);
584  assert(applied != NULL);
585 
586  /* adjust bound to the one that would be applied, so the SCIPsetIsGT check below is more reliable */
587  SCIPvarAdjustLb(var, set, &bound);
588 
589  if( local )
590  {
591  /* apply the local bound change or detect a cutoff */
592  if( SCIPsetIsGT(set, bound, SCIPvarGetLbLocal(var)) )
593  {
594  SCIPsetDebugMsg(set, " -> applying bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
596 
597  if( SCIPsetIsFeasLE(set, bound, SCIPvarGetUbLocal(var)) )
598  {
599  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob, tree,
600  reopt, lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_LOWER, FALSE) );
601  }
602  else
603  *cutoff = TRUE;
604 
605  *applied = TRUE;
606  }
607  else
608  {
609  SCIPsetDebugMsg(set, " -> ignoring bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
611  }
612  }
613  else
614  {
615  /* apply the global bound change or detect a global cutoff which means we can cutoff the root node */
616  if( SCIPsetIsGT(set, bound, SCIPvarGetLbGlobal(var)) )
617  {
618  SCIPsetDebugMsg(set, " -> applying global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
620 
621  if( SCIPsetIsFeasLE(set, bound, SCIPvarGetUbGlobal(var)) )
622  {
623  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob, tree, reopt,
624  lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_LOWER, FALSE) );
625  }
626  else
627  {
628  /* we are done with solving since a global bound change is infeasible */
629  SCIP_CALL( SCIPnodeCutoff(SCIPtreeGetRootNode(tree), set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
630  *cutoff = TRUE;
631  }
632 
633  *applied = TRUE;
634  }
635  else
636  {
637  SCIPsetDebugMsg(set, " -> ignoring global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
639  }
640  }
641 
642  return SCIP_OKAY;
643 }
644 
645 /** applies an upper bound change */
646 static
648  SCIP_SEPASTORE* sepastore, /**< separation storage */
649  BMS_BLKMEM* blkmem, /**< block memory */
650  SCIP_SET* set, /**< global SCIP settings */
651  SCIP_STAT* stat, /**< problem statistics */
652  SCIP_PROB* transprob, /**< transformed problem */
653  SCIP_PROB* origprob, /**< original problem */
654  SCIP_TREE* tree, /**< branch and bound tree */
655  SCIP_REOPT* reopt, /**< reoptimization data structure */
656  SCIP_LP* lp, /**< LP data */
657  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
658  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
659  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
660  SCIP_VAR* var, /**< problem variable */
661  SCIP_Real bound, /**< new upper bound of variable */
662  SCIP_Bool local, /**< is it a local bound change? (otherwise global) */
663  SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
664  SCIP_Bool* cutoff /**< pointer to store TRUE, if an infeasibility has been detected */
665  )
666 {
667  assert(sepastore != NULL);
668  assert(cutoff != NULL);
669  assert(applied != NULL);
670 
671  /* adjust bound to the one that would be applied, so the SCIPsetIsGT check below is more reliable */
672  SCIPvarAdjustUb(var, set, &bound);
673 
674  if( local )
675  {
676  /* apply the local bound change or detect a cutoff */
677  if( SCIPsetIsLT(set, bound, SCIPvarGetUbLocal(var)) )
678  {
679  SCIPsetDebugMsg(set, " -> applying bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
681 
682  if( SCIPsetIsFeasGE(set, bound, SCIPvarGetLbLocal(var)) )
683  {
684  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetCurrentNode(tree), blkmem, set, stat, transprob, origprob, tree,
685  reopt, lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_UPPER, FALSE) );
686  }
687  else
688  *cutoff = TRUE;
689 
690  *applied = TRUE;
691  }
692  else
693  {
694  SCIPsetDebugMsg(set, " -> ignoring bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
696  }
697  }
698  else
699  {
700  /* apply the global bound change or detect a global cutoff which means we can cutoff the root node */
701  if( SCIPsetIsLT(set, bound, SCIPvarGetUbGlobal(var)) )
702  {
703  SCIPsetDebugMsg(set, " -> applying global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
705 
706  if( SCIPsetIsFeasGE(set, bound, SCIPvarGetLbGlobal(var)) )
707  {
708  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob, tree, reopt,
709  lp, branchcand, eventqueue, cliquetable, var, bound, SCIP_BOUNDTYPE_UPPER, FALSE) );
710  }
711  else
712  {
713  /* we are done with solving since a global bound change is infeasible */
714  SCIP_CALL( SCIPnodeCutoff(SCIPtreeGetRootNode(tree), set, stat, tree, transprob, origprob, reopt, lp, blkmem) );
715  *cutoff = TRUE;
716  }
717 
718  *applied = TRUE;
719  }
720  else
721  {
722  SCIPsetDebugMsg(set, " -> ignoring global bound change: <%s>: [%.20g,%.20g] -> [%.20g,%.20g]\n",
724  }
725  }
726 
727  return SCIP_OKAY;
728 }
729 
730 /** applies a cut that is a bound change directly as bound change instead of adding it as row to the LP */
731 static
733  SCIP_SEPASTORE* sepastore, /**< separation storage */
734  BMS_BLKMEM* blkmem, /**< block memory */
735  SCIP_SET* set, /**< global SCIP settings */
736  SCIP_STAT* stat, /**< problem statistics */
737  SCIP_PROB* transprob, /**< transformed problem */
738  SCIP_PROB* origprob, /**< original problem */
739  SCIP_TREE* tree, /**< branch and bound tree */
740  SCIP_REOPT* reopt, /**< reoptimization data structure */
741  SCIP_LP* lp, /**< LP data */
742  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
743  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
744  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
745  SCIP_ROW* cut, /**< cut with a single variable */
746  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base feasibility computation on */
747  SCIP_Bool* applied, /**< pointer to store whether the domain change was applied */
748  SCIP_Bool* cutoff /**< pointer to store whether an empty domain was created */
749  )
750 {
751  SCIP_COL** cols;
752  SCIP_Real* vals;
753  SCIP_VAR* var;
754  SCIP_Real lhs;
755  SCIP_Real rhs;
756  SCIP_Bool local;
757 
758  assert(sepastore != NULL);
759  assert(!SCIProwIsModifiable(cut));
760  assert(SCIProwGetNNonz(cut) == 1);
761  assert(cutoff != NULL);
762  assert(applied != NULL);
763 
764  *applied = FALSE;
765  *cutoff = FALSE;
766 
767  /* get the single variable and its coefficient of the cut */
768  cols = SCIProwGetCols(cut);
769  assert(cols != NULL);
770 
771  var = SCIPcolGetVar(cols[0]);
772  vals = SCIProwGetVals(cut);
773  assert(vals != NULL);
774  assert(!SCIPsetIsZero(set, vals[0]));
775 
776  /* if the coefficient is nearly zero, we better ignore this cut for numerical reasons */
777  if( SCIPsetIsFeasZero(set, vals[0]) )
778  return SCIP_OKAY;
779 
780  local = SCIProwIsLocal(cut);
781 
782  /* get the left hand side of the cut and convert it to a bound */
783  lhs = SCIProwGetLhs(cut);
784  if( !SCIPsetIsInfinity(set, -lhs) )
785  {
786  lhs -= SCIProwGetConstant(cut);
787  if( vals[0] > 0.0 )
788  {
789  /* coefficient is positive -> lhs corresponds to lower bound */
790  SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
791  cliquetable, var, lhs/vals[0], local, applied, cutoff) );
792  }
793  else
794  {
795  /* coefficient is negative -> lhs corresponds to upper bound */
796  SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
797  cliquetable, var, lhs/vals[0], local, applied, cutoff) );
798  }
799  }
800 
801  /* get the right hand side of the cut and convert it to a bound */
802  rhs = SCIProwGetRhs(cut);
803  if( !SCIPsetIsInfinity(set, rhs) )
804  {
805  rhs -= SCIProwGetConstant(cut);
806  if( vals[0] > 0.0 )
807  {
808  /* coefficient is positive -> rhs corresponds to upper bound */
809  SCIP_CALL( sepastoreApplyUb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
810  cliquetable, var, rhs/vals[0], local, applied, cutoff) );
811  }
812  else
813  {
814  /* coefficient is negative -> rhs corresponds to lower bound */
815  SCIP_CALL( sepastoreApplyLb(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
816  cliquetable, var, rhs/vals[0], local, applied, cutoff) );
817  }
818  }
819 
820  /* count the bound change as applied cut */
821  if( *applied && !sepastore->initiallp )
822  sepastore->ncutsapplied++;
823 
824  if( *applied && !sepastore->initiallp && set->sepa_feastolfac > 0.0 )
825  {
826  SCIP_Real infeasibility;
827 
828  /* calculate cut's infeasibility */
829  switch ( efficiacychoice )
830  {
832  infeasibility = -SCIProwGetLPFeasibility(cut, set, stat, lp);
833  break;
835  infeasibility = -SCIProwGetRelaxFeasibility(cut, set, stat);
836  break;
838  infeasibility = -SCIProwGetNLPFeasibility(cut, set, stat);
839  break;
840  default:
841  SCIPerrorMessage("Invalid efficiacy choice.\n");
842  return SCIP_INVALIDCALL;
843  }
844  /* a cut a*x<=b is applied as boundchange x<=b/a, so also the infeasibility needs to be divided by a (aka. scaled) */
845  infeasibility /= REALABS(vals[0]);
846 
847  /* reduce relaxation feasibility tolerance */
848  if( infeasibility > 0.0 && (set->sepa_primfeastol == SCIP_INVALID || set->sepa_primfeastol > set->sepa_feastolfac * infeasibility) ) /*lint !e777*/
849  {
850  SCIP_Real epsilon = SCIPsetEpsilon(set);
851 
852  set->sepa_primfeastol = MAX(set->sepa_feastolfac * infeasibility, epsilon);
853  SCIPsetDebugMsg(set, "reduced feasibility tolerance for relaxations to %g due to cut <%s>\n", set->sepa_primfeastol, SCIProwGetName(cut));
854  }
855  }
856 
857  return SCIP_OKAY;
858 }
859 
860 /** updates the orthogonalities and scores of the non-forced cuts after the given cut was added to the LP */
861 static
863  SCIP_SEPASTORE* sepastore, /**< separation storage */
864  BMS_BLKMEM* blkmem, /**< block memory */
865  SCIP_SET* set, /**< global SCIP settings */
866  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
867  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
868  SCIP_LP* lp, /**< LP data */
869  SCIP_ROW* cut, /**< cut that was applied */
870  SCIP_Real mincutorthogonality /**< minimal orthogonality of cuts to apply to LP */
871  )
872 {
873  int pos;
874 
875  assert(sepastore != NULL);
876 
877  pos = sepastore->nforcedcuts;
878  while( pos < sepastore->ncuts )
879  {
880  SCIP_Real thisortho;
881 
882  /* update orthogonality */
883  thisortho = SCIProwGetOrthogonality(cut, sepastore->cuts[pos], set->sepa_orthofunc);
884  if( thisortho < sepastore->orthogonalities[pos] )
885  {
886  if( thisortho < mincutorthogonality )
887  {
888  /* cut is too parallel: release the row and delete the cut */
889  SCIPsetDebugMsg(set, " -> deleting parallel cut <%s> after adding <%s> (pos=%d, len=%d, orthogonality=%g, score=%g)\n",
890  SCIProwGetName(sepastore->cuts[pos]), SCIProwGetName(cut), pos, SCIProwGetNNonz(cut), thisortho, sepastore->scores[pos]);
891  SCIP_CALL( sepastoreDelCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, pos) );
892  continue;
893  }
894  else
895  {
896  /* recalculate score */
897  sepastore->orthogonalities[pos] = thisortho;
898  assert( sepastore->objparallelisms[pos] != SCIP_INVALID ); /*lint !e777*/
899  assert( sepastore->scores[pos] != SCIP_INVALID ); /*lint !e777*/
900  assert( sepastore->efficacies[pos] != SCIP_INVALID ); /*lint !e777*/
901  sepastore->scores[pos] = sepastore->efficacies[pos]
902  + set->sepa_objparalfac * sepastore->objparallelisms[pos]
903  + set->sepa_orthofac * thisortho;
904  }
905  }
906  pos++;
907  }
908 
909  return SCIP_OKAY;
910 }
911 
912 /** applies the given cut to the LP and updates the orthogonalities and scores of remaining cuts */
913 static
915  SCIP_SEPASTORE* sepastore, /**< separation storage */
916  BMS_BLKMEM* blkmem, /**< block memory */
917  SCIP_SET* set, /**< global SCIP settings */
918  SCIP_STAT* stat, /**< problem statistics */
919  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
920  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
921  SCIP_LP* lp, /**< LP data */
922  SCIP_ROW* cut, /**< cut to apply to the LP */
923  SCIP_Real mincutorthogonality,/**< minimal orthogonality of cuts to apply to LP */
924  int depth, /**< depth of current node */
925  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base feasibility computation on */
926  int* ncutsapplied /**< pointer to count the number of applied cuts */
927  )
928 {
929  assert(sepastore != NULL);
930  assert(ncutsapplied != NULL);
931 
932  /* a row could have been added twice to the separation store; add it only once! */
933  if( !SCIProwIsInLP(cut) )
934  {
935  /* add cut to the LP and capture it */
936  SCIP_CALL( SCIPlpAddRow(lp, blkmem, set, eventqueue, eventfilter, cut, depth) );
937 
938  /* update statistics -> only if we are not in the initial lp (cuts are only counted if added during run) */
939  if( !sepastore->initiallp )
940  {
941  sepastore->ncutsapplied++;
942 
943  /* increase count of applied cuts for origins of row */
944  switch ( cut->origintype )
945  {
947  assert( cut->origin != NULL );
949  break;
951  assert( cut->origin != NULL );
953  break;
956  /* do nothing - cannot update statistics */
957  break;
958  default:
959  SCIPerrorMessage("unkown type of row origin.\n");
960  return SCIP_INVALIDDATA;
961  }
962  }
963 
964  /* update the orthogonalities */
965  SCIP_CALL( sepastoreUpdateOrthogonalities(sepastore, blkmem, set, eventqueue, eventfilter, lp, cut, mincutorthogonality) );
966  (*ncutsapplied)++;
967 
968  if( !sepastore->initiallp && set->sepa_feastolfac > 0.0 )
969  {
970  SCIP_Real infeasibility;
971 
972  /* calculate cut's infeasibility */
973  switch ( efficiacychoice )
974  {
976  infeasibility = -SCIProwGetLPFeasibility(cut, set, stat, lp);
977  break;
979  infeasibility = -SCIProwGetRelaxFeasibility(cut, set, stat);
980  break;
982  infeasibility = -SCIProwGetNLPFeasibility(cut, set, stat);
983  break;
984  default:
985  SCIPerrorMessage("Invalid efficiacy choice.\n");
986  return SCIP_INVALIDCALL;
987  }
988 
989  /* reduce relaxation feasibility tolerance */
990  if( infeasibility > 0.0 && (set->sepa_primfeastol == SCIP_INVALID || set->sepa_primfeastol > set->sepa_feastolfac * infeasibility) ) /*lint !e777*/
991  {
992  SCIP_Real epsilon = SCIPsetEpsilon(set);
993 
994  set->sepa_primfeastol = MAX(set->sepa_feastolfac * infeasibility, epsilon);
995  SCIPsetDebugMsg(set, "reduced feasibility tolerance for relaxations to %g due to cut <%s>\n", set->sepa_primfeastol, SCIProwGetName(cut));
996  }
997  }
998  }
999 
1000  return SCIP_OKAY;
1001 }
1002 
1003 /** returns the position of the best non-forced cut in the cuts array */
1004 static
1006  SCIP_SEPASTORE* sepastore /**< separation storage */
1007  )
1008 {
1009  SCIP_Real bestscore;
1010  int bestpos;
1011  int pos;
1012 
1013  assert(sepastore != NULL);
1014 
1015  bestscore = SCIP_REAL_MIN;
1016  bestpos = -1;
1017  for( pos = sepastore->nforcedcuts; pos < sepastore->ncuts; pos++ )
1018  {
1019  /* check if cut is current best cut */
1020  assert( sepastore->scores[pos] != SCIP_INVALID ); /*lint !e777*/
1021  if( sepastore->scores[pos] > bestscore )
1022  {
1023  bestscore = sepastore->scores[pos];
1024  bestpos = pos;
1025  }
1026  }
1027 
1028  return bestpos;
1029 }
1030 
1031 /** computes score for current LP solution and initialized orthogonalities */
1032 static
1034  SCIP_SEPASTORE* sepastore, /**< separation storage */
1035  SCIP_SET* set, /**< global SCIP settings */
1036  SCIP_STAT* stat, /**< problem statistics */
1037  SCIP_LP* lp, /**< LP data */
1038  SCIP_Bool handlepool, /**< whether the efficacy of cuts in the pool should be reduced */
1039  int pos, /**< position of cut to handle */
1040  SCIP_EFFICIACYCHOICE efficiacychoice /**< type of solution to base efficiacy computation on */
1041  )
1042 {
1043  SCIP_ROW* cut;
1044  SCIP_Real cutefficacy;
1045  SCIP_Real cutscore;
1046 
1047  cut = sepastore->cuts[pos];
1048 
1049  /* calculate cut's efficacy */
1050  switch ( efficiacychoice )
1051  {
1053  cutefficacy = SCIProwGetLPEfficacy(cut, set, stat, lp);
1054  break;
1056  cutefficacy = SCIProwGetRelaxEfficacy(cut, set, stat);
1057  break;
1059  cutefficacy = SCIProwGetNLPEfficacy(cut, set, stat);
1060  break;
1061  default:
1062  SCIPerrorMessage("Invalid efficiacy choice.\n");
1063  return SCIP_INVALIDCALL;
1064  }
1065 
1066  /* If a cut is not member of the cut pool, we slightly decrease its score to prefer identical
1067  * cuts which are in the cut pool. This is because the conversion of cuts into linear
1068  * constraints after a restart looks at the cut pool and cannot find tight non-pool cuts.
1069  */
1070  if( handlepool && !SCIProwIsInGlobalCutpool(cut) )
1071  cutefficacy *= 0.9999;
1072 
1073  /* calculate resulting score */
1074  assert( sepastore->objparallelisms[pos] != SCIP_INVALID ); /*lint !e777*/
1075  cutscore = cutefficacy + set->sepa_objparalfac * sepastore->objparallelisms[pos] + set->sepa_orthofac * 1.0;
1076  assert( !SCIPsetIsInfinity(set, cutscore) );
1077 
1078  sepastore->efficacies[pos] = cutefficacy;
1079  sepastore->scores[pos] = cutscore;
1080 
1081  /* make sure that the orthogonalities are initialized to 1.0 */
1082  sepastore->orthogonalities[pos] = 1.0;
1083 
1084  return SCIP_OKAY;
1085 }
1086 
1087 /** adds cuts to the LP and clears separation storage */
1089  SCIP_SEPASTORE* sepastore, /**< separation storage */
1090  BMS_BLKMEM* blkmem, /**< block memory */
1091  SCIP_SET* set, /**< global SCIP settings */
1092  SCIP_STAT* stat, /**< problem statistics */
1093  SCIP_PROB* transprob, /**< transformed problem */
1094  SCIP_PROB* origprob, /**< original problem */
1095  SCIP_TREE* tree, /**< branch and bound tree */
1096  SCIP_REOPT* reopt, /**< reoptimization data structure */
1097  SCIP_LP* lp, /**< LP data */
1098  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1099  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1100  SCIP_EVENTFILTER* eventfilter, /**< global event filter */
1101  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1102  SCIP_Bool root, /**< are we at the root node? */
1103  SCIP_EFFICIACYCHOICE efficiacychoice, /**< type of solution to base efficiacy computation on */
1104  SCIP_Bool* cutoff /**< pointer to store whether an empty domain was created */
1105  )
1106 {
1107  SCIP_NODE* node;
1108  SCIP_Real mincutorthogonality;
1109  SCIP_Bool applied;
1110  int depth;
1111  int maxsepacuts;
1112  int ncutsapplied;
1113  int pos;
1114 
1115  assert(sepastore != NULL);
1116  assert(set != NULL);
1117  assert(tree != NULL);
1118  assert(lp != NULL);
1119  assert(cutoff != NULL);
1120 
1121  *cutoff = FALSE;
1122 
1123  SCIPsetDebugMsg(set, "applying %d cuts\n", sepastore->ncuts);
1124 
1125  node = SCIPtreeGetCurrentNode(tree);
1126  assert(node != NULL);
1127 
1128  /* get maximal number of cuts to add to the LP */
1129  maxsepacuts = SCIPsetGetSepaMaxcuts(set, root);
1130  ncutsapplied = 0;
1131 
1132  /* get depth of current node */
1133  depth = SCIPnodeGetDepth(node);
1134 
1135  /* calculate minimal cut orthogonality */
1136  mincutorthogonality = (root ? set->sepa_minorthoroot : set->sepa_minortho);
1137  mincutorthogonality = MAX(mincutorthogonality, set->num_epsilon);
1138 
1139  /* Compute scores for all non-forced cuts and initialize orthogonalities - make sure all cuts are initialized again for the current LP solution */
1140  for( pos = sepastore->nforcedcuts; pos < sepastore->ncuts; pos++ )
1141  {
1142  SCIP_CALL( computeScore(sepastore, set, stat, lp, TRUE, pos, efficiacychoice) );
1143  }
1144 
1145  /* apply all forced cuts */
1146  for( pos = 0; pos < sepastore->nforcedcuts && !(*cutoff); pos++ )
1147  {
1148  SCIP_ROW* cut;
1149 
1150  cut = sepastore->cuts[pos];
1151  assert(SCIPsetIsInfinity(set, sepastore->scores[pos]));
1152 
1153  /* if the cut is a bound change (i.e. a row with only one variable), add it as bound change instead of LP row */
1154  applied = FALSE;
1155  if( !SCIProwIsModifiable(cut) && SCIProwGetNNonz(cut) == 1 )
1156  {
1157  SCIPsetDebugMsg(set, " -> applying forced cut <%s> as boundchange\n", SCIProwGetName(cut));
1158  SCIP_CALL( sepastoreApplyBdchg(sepastore, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
1159  eventqueue, cliquetable, cut, efficiacychoice, &applied, cutoff) );
1160 
1161  assert(applied || !sepastoreIsBdchgApplicable(set, cut));
1162  }
1163 
1164  if( !applied )
1165  {
1166  /* add cut to the LP and update orthogonalities */
1167  SCIPsetDebugMsg(set, " -> applying forced cut <%s>\n", SCIProwGetName(cut));
1168  /*SCIPdebug( SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
1169  SCIP_CALL( sepastoreApplyCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, mincutorthogonality, depth, efficiacychoice, &ncutsapplied) );
1170  }
1171  }
1172 
1173  /* apply non-forced cuts */
1174  while( ncutsapplied < maxsepacuts && sepastore->ncuts > sepastore->nforcedcuts && !(*cutoff) )
1175  {
1176  SCIP_ROW* cut;
1177  int bestpos;
1178 
1179  /* get best non-forced cut */
1180  bestpos = sepastoreGetBestCut(sepastore);
1181  assert(sepastore->nforcedcuts <= bestpos && bestpos < sepastore->ncuts);
1182  assert(sepastore->scores[bestpos] != SCIP_INVALID ); /*lint !e777*/
1183  assert(sepastore->efficacies[bestpos] != SCIP_INVALID ); /*lint !e777*/
1184  cut = sepastore->cuts[bestpos];
1185  assert(SCIProwIsModifiable(cut) || SCIProwGetNNonz(cut) != 1 || !sepastoreIsBdchgApplicable(set, cut)); /* applicable bound changes are forced cuts */
1186  assert(!SCIPsetIsInfinity(set, sepastore->scores[bestpos]));
1187 
1188  SCIPsetDebugMsg(set, " -> applying cut <%s> (pos=%d/%d, len=%d, efficacy=%g, objparallelism=%g, orthogonality=%g, score=%g)\n",
1189  SCIProwGetName(cut), bestpos, sepastore->ncuts, SCIProwGetNNonz(cut), sepastore->efficacies[bestpos], sepastore->objparallelisms[bestpos],
1190  sepastore->orthogonalities[bestpos], sepastore->scores[bestpos]);
1191  /*SCIPdebug(SCIProwPrint(cut, set->scip->messagehdlr, NULL));*/
1192 
1193  /* capture cut such that it is not destroyed in sepastoreDelCut() */
1194  SCIProwCapture(cut);
1195 
1196  /* release the row and delete the cut (also issuing ROWDELETEDSEPA event) */
1197  SCIP_CALL( sepastoreDelCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, bestpos) );
1198 
1199  /* Do not add (non-forced) non-violated cuts.
1200  * Note: do not take SCIPsetIsEfficacious(), because constraint handlers often add cuts w.r.t. SCIPsetIsFeasPositive().
1201  * Note2: if separating/feastolfac != -1, constraint handlers may even add cuts w.r.t. SCIPsetIsPositive(); those are currently rejected here
1202  */
1203  if( SCIPsetIsFeasPositive(set, sepastore->efficacies[bestpos]) )
1204  {
1205  /* add cut to the LP and update orthogonalities */
1206  SCIP_CALL( sepastoreApplyCut(sepastore, blkmem, set, stat, eventqueue, eventfilter, lp, cut, mincutorthogonality, depth, efficiacychoice, &ncutsapplied) );
1207  }
1208 
1209  /* release cut */
1210  SCIP_CALL( SCIProwRelease(&cut, blkmem, set, lp) );
1211  }
1212 
1213  /* clear the separation storage and reset statistics for separation round */
1214  SCIP_CALL( SCIPsepastoreClearCuts(sepastore, blkmem, set, eventqueue, eventfilter, lp) );
1215 
1216  return SCIP_OKAY;
1217 }
1218 
1219 /** clears the separation storage without adding the cuts to the LP */
1221  SCIP_SEPASTORE* sepastore, /**< separation storage */
1222  BMS_BLKMEM* blkmem, /**< block memory */
1223  SCIP_SET* set, /**< global SCIP settings */
1224  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1225  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
1226  SCIP_LP* lp /**< LP data */
1227  )
1228 {
1229  int c;
1230 
1231  assert(sepastore != NULL);
1232 
1233  SCIPsetDebugMsg(set, "clearing %d cuts\n", sepastore->ncuts);
1234 
1235  /* release cuts */
1236  for( c = 0; c < sepastore->ncuts; ++c )
1237  {
1238  /* check, if the row deletions from separation storage events are tracked
1239  * if so, issue ROWDELETEDSEPA event
1240  */
1241  if( eventfilter->len > 0 && (eventfilter->eventmask & SCIP_EVENTTYPE_ROWDELETEDSEPA) != 0 )
1242  {
1243  SCIP_EVENT* event;
1244 
1245  SCIP_CALL( SCIPeventCreateRowDeletedSepa(&event, blkmem, sepastore->cuts[c]) );
1246  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, eventfilter, &event) );
1247  }
1248 
1249  SCIP_CALL( SCIProwRelease(&sepastore->cuts[c], blkmem, set, lp) );
1250  }
1251 
1252  /* reset counters */
1253  sepastore->ncuts = 0;
1254  sepastore->nforcedcuts = 0;
1255  sepastore->ncutsfoundround = 0;
1256 
1257  /* if we have just finished the initial LP construction, free the (potentially large) cuts array */
1258  if( sepastore->initiallp )
1259  {
1260  BMSfreeMemoryArrayNull(&sepastore->cuts);
1261  sepastore->cutssize = 0;
1262  }
1263 
1264  return SCIP_OKAY;
1265 }
1266 
1267 /** removes cuts that are inefficacious w.r.t. the current LP solution from separation storage without adding the cuts to the LP */
1269  SCIP_SEPASTORE* sepastore, /**< separation storage */
1270  BMS_BLKMEM* blkmem, /**< block memory */
1271  SCIP_SET* set, /**< global SCIP settings */
1272  SCIP_STAT* stat, /**< problem statistics data */
1273  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1274  SCIP_EVENTFILTER* eventfilter, /**< event filter for global events */
1275  SCIP_LP* lp, /**< LP data */
1276  SCIP_Bool root, /**< are we at the root node? */
1277  SCIP_EFFICIACYCHOICE efficiacychoice /**< type of solution to base efficiacy computation on */
1278  )
1279 {
1280  int cnt;
1281  int c;
1282 
1283  assert( sepastore != NULL );
1284 
1285  /* check non-forced cuts only */
1286  cnt = 0;
1287  c = sepastore->nforcedcuts;
1288  while( c < sepastore->ncuts )
1289  {
1290  assert( sepastore->efficacies[c] == SCIP_INVALID ); /*lint !e777*/
1291  SCIP_CALL( computeScore(sepastore, set, stat, lp, FALSE, c, efficiacychoice) );
1292  if( !SCIPsetIsEfficacious(set, root, sepastore->efficacies[c]) )
1293  {
1294  SCIP_CALL( sepastoreDelCut(sepastore, blkmem, set, eventqueue, eventfilter, lp, c) );
1295  ++cnt;
1296  }
1297  else
1298  ++c;
1299  }
1300  SCIPsetDebugMsg(set, "removed %d non-efficacious cuts\n", cnt);
1301 
1302  return SCIP_OKAY;
1303 }
1304 
1305 /** indicates whether a cut is applicable
1306  *
1307  * A cut is applicable if it is modifiable, not a bound change, or a bound change that changes bounds by at least epsilon.
1308  */
1310  SCIP_SET* set, /**< global SCIP settings */
1311  SCIP_ROW* cut /**< cut to check */
1312  )
1313 {
1314  return SCIProwIsModifiable(cut) || SCIProwGetNNonz(cut) != 1 || sepastoreIsBdchgApplicable(set, cut);
1315 }
1316 
1317 /** get cuts in the separation storage */
1319  SCIP_SEPASTORE* sepastore /**< separation storage */
1320  )
1321 {
1322  assert(sepastore != NULL);
1323 
1324  return sepastore->cuts;
1325 }
1326 
1327 /** get number of cuts in the separation storage */
1329  SCIP_SEPASTORE* sepastore /**< separation storage */
1330  )
1331 {
1332  assert(sepastore != NULL);
1333 
1334  return sepastore->ncuts;
1335 }
1336 
1337 /** get total number of cuts found so far */
1339  SCIP_SEPASTORE* sepastore /**< separation storage */
1340  )
1341 {
1342  assert(sepastore != NULL);
1343 
1344  return sepastore->ncutsfound;
1345 }
1346 
1347 /** get number of cuts found so far in current separation round */
1349  SCIP_SEPASTORE* sepastore /**< separation storage */
1350  )
1351 {
1352  assert(sepastore != NULL);
1353 
1354  return sepastore->ncutsfoundround;
1355 }
1356 
1357 /** get total number of cuts applied to the LPs */
1359  SCIP_SEPASTORE* sepastore /**< separation storage */
1360  )
1361 {
1362  assert(sepastore != NULL);
1363 
1364  return sepastore->ncutsapplied;
1365 }
internal methods for separators
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5522
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:562
internal methods for managing events
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5580
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6030
void * origin
Definition: struct_lp.h:214
#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:6094
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:2112
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17166
void SCIPsepaIncNAppliedCuts(SCIP_SEPA *sepa)
Definition: sepa.c:799
unsigned int origintype
Definition: struct_lp.h:252
SCIP_ROW ** SCIPsepastoreGetCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1318
static long bound
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:16232
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17222
void SCIProwCapture(SCIP_ROW *row)
Definition: lp.c:5159
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:16370
void SCIPsepastoreStartForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:148
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5384
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:862
int SCIPsepastoreGetNCutsApplied(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1358
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:16311
#define FALSE
Definition: def.h:64
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5634
#define TRUE
Definition: def.h:63
#define SCIPdebugCheckRow(set, row)
Definition: debug.h:253
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:6543
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5096
SCIP_Real SCIProwGetNLPEfficacy(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6699
static SCIP_Bool sepastoreIsCutRedundant(SCIP_SEPASTORE *sepastore, SCIP_SET *set, SCIP_STAT *stat, SCIP_ROW *cut)
Definition: sepastore.c:171
int SCIPnodeGetDepth(SCIP_NODE *node)
Definition: tree.c:7153
#define BMSfreeMemory(ptr)
Definition: memory.h:100
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6052
SCIP_Real * scores
internal methods for LP management
int SCIPsetGetSepaMaxcuts(SCIP_SET *set, SCIP_Bool root)
Definition: set.c:5252
SCIP_ROW ** cuts
SCIP_Bool SCIProwIsInLP(SCIP_ROW *row)
Definition: lp.c:16522
SCIP_Bool SCIPsetIsEfficacious(SCIP_SET *set, SCIP_Bool root, SCIP_Real efficacy)
Definition: set.c:6392
SCIP_RETCODE SCIPnodeCutoff(SCIP_NODE *node, SCIP_SET *set, SCIP_STAT *stat, SCIP_TREE *tree, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_REOPT *reopt, SCIP_LP *lp, BMS_BLKMEM *blkmem)
Definition: tree.c:1120
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17176
SCIP_RETCODE SCIPeventCreateRowDeletedSepa(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:804
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5562
SCIP_Bool SCIPsepastoreIsCutApplicable(SCIP_SET *set, SCIP_ROW *cut)
Definition: sepastore.c:1309
#define SCIP_EVENTTYPE_ROWADDEDSEPA
Definition: type_event.h:91
#define SCIPerrorMessage
Definition: pub_message.h:45
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:914
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:16420
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:180
SCIP_RETCODE SCIProwChgLocal(SCIP_ROW *row, SCIP_Bool local)
Definition: lp.c:5550
int SCIPsepastoreGetNCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1328
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:1268
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
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:6156
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:9182
#define NULL
Definition: lpi_spx1.cpp:137
#define REALABS(x)
Definition: def.h:159
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6008
static int sepastoreGetBestCut(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1005
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:16321
SCIP_Real * orthogonalities
internal methods for storing separated cuts
SCIP_Bool SCIProwIsModifiable(SCIP_ROW *row)
Definition: lp.c:16430
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5964
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:364
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:16257
SCIP_RETCODE SCIProwRelease(SCIP_ROW **row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:5172
data structures and methods for collecting reoptimization information
internal methods for problem variables
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:16267
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:406
#define SCIP_Bool
Definition: def.h:61
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:647
#define MAX(x, y)
Definition: tclique_def.h:75
void SCIPconshdlrIncNAppliedCuts(SCIP_CONSHDLR *conshdlr)
Definition: cons.c:4789
methods for debugging
#define SCIPsetDebugMsg
Definition: set.h:1870
SCIP_RETCODE SCIPsepastoreFree(SCIP_SEPASTORE **sepastore)
Definition: sepastore.c:105
#define SCIP_EVENTTYPE_ROWDELETEDSEPA
Definition: type_event.h:92
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:6659
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5942
void SCIPsepastoreStartInitialLP(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:124
SCIP_Real SCIProwGetMaxActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6427
#define SCIP_REAL_MIN
Definition: def.h:137
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:16277
int SCIPsepastoreGetNCutsFound(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1338
SCIP_Real SCIProwGetMinActivity(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat)
Definition: lp.c:6406
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:16081
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8153
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:1991
SCIP_NODE * SCIPtreeGetCurrentNode(SCIP_TREE *tree)
Definition: tree.c:8086
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:1088
SCIP_Real SCIProwGetLPFeasibility(SCIP_ROW *row, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:6074
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5598
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:1033
#define SCIP_Real
Definition: def.h:135
internal methods for problem statistics
#define MIN(x, y)
Definition: memory.c:75
SCIP_Real SCIProwGetObjParallelism(SCIP_ROW *row, SCIP_SET *set, SCIP_LP *lp)
Definition: lp.c:7535
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6041
int SCIPsepastoreGetNCutsFoundRound(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:1348
#define BMSallocMemory(ptr)
Definition: memory.h:74
SCIP_Real * efficacies
#define SCIP_INVALID
Definition: def.h:155
#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:732
SCIP_Real * objparallelisms
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5986
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5406
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17232
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6069
SCIP_Bool initiallp
datastructures for storing conflicts
common defines and data types used in all packages of SCIP
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
SCIP_RETCODE SCIPsepastoreClearCuts(SCIP_SEPASTORE *sepastore, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_EVENTFILTER *eventfilter, SCIP_LP *lp)
Definition: sepastore.c:1220
#define SCIP_ALLOC(x)
Definition: def.h:317
SCIP_Bool forcecuts
void SCIPsepastoreEndForceCuts(SCIP_SEPASTORE *sepastore)
Definition: sepastore.c:159
SCIP_Real SCIProwGetOrthogonality(SCIP_ROW *row1, SCIP_ROW *row2, char orthofunc)
Definition: lp.c:7523
SCIP_RETCODE SCIPeventCreateRowAddedSepa(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_ROW *row)
Definition: event.c:785
SCIP_Bool SCIProwIsInGlobalCutpool(SCIP_ROW *row)
Definition: lp.c:16490