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